Skip to content

Commit dba0d2e

Browse files
committed
Bug fix logbook attachments handling
1 parent b1bcfd5 commit dba0d2e

File tree

7 files changed

+261
-149
lines changed

7 files changed

+261
-149
lines changed

app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/AttachmentsViewController.java

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import javafx.application.Platform;
2222
import javafx.beans.binding.Bindings;
2323
import javafx.beans.property.ReadOnlyBooleanProperty;
24+
import javafx.beans.property.SimpleListProperty;
2425
import javafx.beans.property.SimpleObjectProperty;
2526
import javafx.collections.FXCollections;
2627
import javafx.collections.ListChangeListener;
@@ -47,7 +48,6 @@
4748
import org.phoebus.framework.workbench.ApplicationService;
4849
import org.phoebus.logbook.Attachment;
4950
import org.phoebus.logbook.LogEntry;
50-
import org.phoebus.logbook.olog.ui.write.AttachmentsEditorController;
5151
import org.phoebus.ui.application.ApplicationLauncherService;
5252
import org.phoebus.ui.application.PhoebusApplication;
5353
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
@@ -61,7 +61,6 @@
6161
import java.net.URI;
6262
import java.nio.file.Files;
6363
import java.nio.file.StandardCopyOption;
64-
import java.util.ArrayList;
6564
import java.util.Collection;
6665
import java.util.Collections;
6766
import java.util.List;
@@ -75,49 +74,65 @@
7574
public class AttachmentsViewController {
7675

7776
@FXML
77+
@SuppressWarnings("unused")
7878
private SplitPane splitPane;
7979

8080
@FXML
81+
@SuppressWarnings("unused")
8182
private StackPane previewPane;
8283

8384
@FXML
85+
@SuppressWarnings("unused")
8486
private ImageView imagePreview;
8587

8688
@FXML
89+
@SuppressWarnings("unused")
8790
private GridPane noPreviewPane;
8891

8992
@FXML
93+
@SuppressWarnings("unused")
9094
private ListView<Attachment> attachmentListView;
9195

9296
@FXML
97+
@SuppressWarnings("unused")
9398
private Label placeholderLabel;
9499

95100
/**
96-
* List of attachments selected by user in the preview's {@link ListView}.
101+
* List of attachments selected by user in the {@link ListView}.
97102
*/
98103
private final ObservableList<Attachment> selectedAttachments = FXCollections.observableArrayList();
99104

105+
/**
106+
* Keeps track of the {@link Attachment} currently in the {@link ImageView}, if any.
107+
*/
100108
private final SimpleObjectProperty<Attachment> selectedAttachment = new SimpleObjectProperty<>();
101109

102110
/**
103-
* List of listeners that will be notified when user has selected one or multiple attachments in
104-
* the {@link ListView}.
111+
* List of all {@link Attachment}s currently in view.
105112
*/
106-
private final List<ListChangeListener<Attachment>> listSelectionChangeListeners = new ArrayList<>();
107-
108113
private final ObservableList<Attachment> attachments = FXCollections.observableArrayList();
109114

110-
public AttachmentsViewController(){
115+
public AttachmentsViewController() {
111116
}
112117

113118
@FXML
114119
public void initialize() {
115120

116121
attachmentListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
117122
attachmentListView.setCellFactory(view -> new AttachmentRow());
118-
attachmentListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
119-
selectedAttachment.set(newValue);
120-
showPreview();
123+
124+
// Show preview when single selection property changes
125+
selectedAttachment.addListener((obs, o, n) -> showPreview(n));
126+
127+
attachmentListView.getSelectionModel().getSelectedItems().addListener((ListChangeListener<Attachment>) change -> {
128+
selectedAttachments.setAll(change.getList());
129+
if (change.getList().size() == 1) {
130+
// Set single selection property only if selection contains a single element
131+
selectedAttachment.set(change.getList().get(0));
132+
}
133+
else if(attachments.isEmpty()){
134+
showPreview(null);
135+
}
121136
});
122137

123138
attachmentListView.setOnMouseClicked(me -> {
@@ -145,17 +160,12 @@ public void initialize() {
145160
ExceptionDetailsErrorDialog.openError(Messages.PreviewOpenErrorTitle, Messages.PreviewOpenErrorBody, null);
146161
}
147162
}
148-
}
149-
else {
150-
showImageAttachment();
163+
} else {
164+
showImageAttachment();
151165
}
152166
}
153167
});
154168

155-
attachmentListView.getSelectionModel().getSelectedItems().addListener((ListChangeListener<Attachment>) change -> {
156-
selectedAttachments.setAll(change.getList());
157-
listSelectionChangeListeners.forEach(l -> l.onChanged(change));
158-
});
159169

160170
attachmentListView.setOnContextMenuRequested((e) -> {
161171
ContextMenu contextMenu = new ContextMenu();
@@ -195,12 +205,14 @@ public void initialize() {
195205
}
196206
event.consume();
197207
});
208+
209+
attachmentListView.itemsProperty().bindBidirectional(new SimpleListProperty<>(attachments));
198210
}
199211

200212
/**
201213
* Launches the Image Viewer application to show the selected image attachment with a watermark.
202214
*/
203-
private void showImageAttachment(){
215+
private void showImageAttachment() {
204216
URI uri = selectedAttachment.get().getFile().toURI();
205217
URI withWatermark = UriBuilder.fromUri(uri).queryParam("watermark", "true").build();
206218
ApplicationLauncherService.openResource(withWatermark,
@@ -217,13 +229,13 @@ public void invalidateAttachmentList(LogEntry logEntry) {
217229
} else {
218230
placeholderLabel.setText(Messages.DownloadingAttachments);
219231
}
220-
setAttachments(Collections.emptyList());
232+
attachments.setAll(Collections.emptyList());
221233
}
222234

223-
public void setAttachments(Collection<Attachment> attachments) {
235+
public void setAttachments(Collection<Attachment> attachmentsList) {
224236
Platform.runLater(() -> {
225-
this.attachments.setAll(attachments);
226-
attachmentListView.setItems(this.attachments);
237+
this.attachments.setAll(attachmentsList);
238+
//attachmentListView.setItems(this.attachments);
227239
// Update UI
228240
if (!this.attachments.isEmpty()) {
229241
attachmentListView.getSelectionModel().select(this.attachments.get(0));
@@ -246,13 +258,15 @@ public void updateItem(Attachment attachment, boolean empty) {
246258
/**
247259
* Shows selected attachment in preview pane.
248260
*/
249-
private void showPreview() {
250-
if (selectedAttachment.get() == null) {
261+
private void showPreview(Attachment attachment) {
262+
if (attachment == null) {
251263
imagePreview.visibleProperty().setValue(false);
252264
return;
253265
}
254-
if (selectedAttachment.get().getContentType().startsWith("image")) {
255-
showImagePreview(selectedAttachment.get());
266+
if (attachment.getContentType().startsWith("image")) {
267+
imagePreview.visibleProperty().setValue(true);
268+
noPreviewPane.visibleProperty().setValue(false);
269+
showImagePreview(attachment);
256270
} else {
257271
imagePreview.visibleProperty().setValue(false);
258272
noPreviewPane.visibleProperty().setValue(true);
@@ -279,9 +293,9 @@ private void showImagePreview(Attachment attachment) {
279293
Image image = SwingFXUtils.toFXImage(bufferedImage, null);
280294
imagePreview.visibleProperty().setValue(true);
281295
imagePreview.setImage(image);
282-
});
296+
});
283297
} catch (IOException ex) {
284-
Logger.getLogger(AttachmentsEditorController.class.getName())
298+
Logger.getLogger(AttachmentsViewController.class.getName())
285299
.log(Level.SEVERE, "Unable to load image file " + attachment.getFile().getAbsolutePath(), ex);
286300
}
287301
});
@@ -313,26 +327,24 @@ private void copyAttachment(File targetFolder, Attachment attachment) {
313327
}
314328
}
315329

316-
public void addListSelectionChangeListener(ListChangeListener<Attachment> changeListener) {
317-
listSelectionChangeListeners.add(changeListener);
318-
}
319-
320-
public void removeAttachments(List<Attachment> attachmentsToRemove) {
321-
attachments.removeAll(attachmentsToRemove);
322-
}
323-
324-
public List<Attachment> getAttachments() {
330+
/**
331+
* @return The {@link ObservableList} of attachments.
332+
*/
333+
public ObservableList<Attachment> getAttachments() {
325334
return attachments;
326335
}
327336

328337
/**
329-
* Adds an {@link Attachment} to the list of {@link Attachment}s and selects it in order
330-
* to show a preview (image files only).
338+
* Adds {@link Attachment}s to the list of {@link Attachment}s. If only one
339+
* {@link Attachment} is added it is also selected.
331340
*
332-
* @param attachment The new {@link Attachment}
341+
* @param attachmentsList The new {@link Attachment}s
333342
*/
334-
public void addAttachment(Attachment attachment) {
335-
attachments.add(attachment);
336-
attachmentListView.getSelectionModel().select(attachment);
343+
public void addAttachments(List<Attachment> attachmentsList) {
344+
Platform.runLater(() -> {
345+
attachmentListView.getSelectionModel().clearSelection();
346+
attachments.addAll(attachmentsList);
347+
attachmentListView.getSelectionModel().select(attachmentsList.get(0));
348+
});
337349
}
338350
}

app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryDisplayController.java

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -160,35 +160,30 @@ public void goForward() {
160160
}
161161
}
162162

163+
/**
164+
* Sets/renders the {@link LogEntry} in the view unless already rendered or unedited.
165+
* @param logEntry A non-null {@link LogEntry}
166+
*/
163167
public void setLogEntry(LogEntry logEntry) {
164-
if(logEntry == null){
165-
currentViewProperty.set(EMPTY);
166-
}
167-
else{
168-
logEntryProperty.set(logEntry);
169-
singleLogEntryDisplayController.setLogEntry(logEntry);
170-
currentViewProperty.set(SINGLE);
171-
showHideLogEntryGroupButton.selectedProperty().set(false);
172-
hasLinkedEntriesProperty.set(logEntry.getProperties()
173-
.stream().anyMatch(p -> p.getName().equals(LogGroupProperty.NAME)));
168+
if(logEntryProperty.get() == null ||
169+
!logEntryProperty.get().getId().equals(logEntry.getId()) ||
170+
(logEntry.getModifiedDate() != null &&
171+
!logEntry.getModifiedDate().equals(logEntryProperty.get().getModifiedDate()))) {
172+
Platform.runLater(() -> {
173+
logEntryProperty.set(logEntry);
174+
singleLogEntryDisplayController.setLogEntry(logEntry);
175+
currentViewProperty.set(SINGLE);
176+
showHideLogEntryGroupButton.selectedProperty().set(false);
177+
hasLinkedEntriesProperty.set(logEntry.getProperties()
178+
.stream().anyMatch(p -> p.getName().equals(LogGroupProperty.NAME)));;
179+
});
174180
}
175181
}
176182

177183
public LogEntry getLogEntry() {
178184
return logEntryProperty.get();
179185
}
180186

181-
/**
182-
* Updates the current {@link LogEntry} if it matches the passed argument.
183-
* @param logEntry A log entry that has been updated by user and saved by service.
184-
*/
185-
public void updateLogEntry(LogEntry logEntry){
186-
// Log entry display may be "empty", i.e. logEntryProperty not set yet
187-
if(!logEntryProperty.isNull().get() && logEntryProperty.get().getId().equals(logEntry.getId())){
188-
setLogEntry(logEntry);
189-
}
190-
}
191-
192187
public void setLogEntryTableViewController(LogEntryTableViewController logEntryTableViewController){
193188
this.logEntryTableViewController = logEntryTableViewController;
194189
if (logEntryTableViewController.goBackAndGoForwardActions.isPresent()) {

0 commit comments

Comments
 (0)