2121import javafx .application .Platform ;
2222import javafx .beans .binding .Bindings ;
2323import javafx .beans .property .ReadOnlyBooleanProperty ;
24+ import javafx .beans .property .SimpleListProperty ;
2425import javafx .beans .property .SimpleObjectProperty ;
2526import javafx .collections .FXCollections ;
2627import javafx .collections .ListChangeListener ;
4748import org .phoebus .framework .workbench .ApplicationService ;
4849import org .phoebus .logbook .Attachment ;
4950import org .phoebus .logbook .LogEntry ;
50- import org .phoebus .logbook .olog .ui .write .AttachmentsEditorController ;
5151import org .phoebus .ui .application .ApplicationLauncherService ;
5252import org .phoebus .ui .application .PhoebusApplication ;
5353import org .phoebus .ui .dialog .ExceptionDetailsErrorDialog ;
6161import java .net .URI ;
6262import java .nio .file .Files ;
6363import java .nio .file .StandardCopyOption ;
64- import java .util .ArrayList ;
6564import java .util .Collection ;
6665import java .util .Collections ;
6766import java .util .List ;
7574public 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,12 @@ 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 );
227238 // Update UI
228239 if (!this .attachments .isEmpty ()) {
229240 attachmentListView .getSelectionModel ().select (this .attachments .get (0 ));
@@ -246,13 +257,15 @@ public void updateItem(Attachment attachment, boolean empty) {
246257 /**
247258 * Shows selected attachment in preview pane.
248259 */
249- private void showPreview () {
250- if (selectedAttachment . get () == null ) {
260+ private void showPreview (Attachment attachment ) {
261+ if (attachment == null ) {
251262 imagePreview .visibleProperty ().setValue (false );
252263 return ;
253264 }
254- if (selectedAttachment .get ().getContentType ().startsWith ("image" )) {
255- showImagePreview (selectedAttachment .get ());
265+ if (attachment .getContentType ().startsWith ("image" )) {
266+ imagePreview .visibleProperty ().setValue (true );
267+ noPreviewPane .visibleProperty ().setValue (false );
268+ showImagePreview (attachment );
256269 } else {
257270 imagePreview .visibleProperty ().setValue (false );
258271 noPreviewPane .visibleProperty ().setValue (true );
@@ -279,9 +292,9 @@ private void showImagePreview(Attachment attachment) {
279292 Image image = SwingFXUtils .toFXImage (bufferedImage , null );
280293 imagePreview .visibleProperty ().setValue (true );
281294 imagePreview .setImage (image );
282- });
295+ });
283296 } catch (IOException ex ) {
284- Logger .getLogger (AttachmentsEditorController .class .getName ())
297+ Logger .getLogger (AttachmentsViewController .class .getName ())
285298 .log (Level .SEVERE , "Unable to load image file " + attachment .getFile ().getAbsolutePath (), ex );
286299 }
287300 });
@@ -313,26 +326,24 @@ private void copyAttachment(File targetFolder, Attachment attachment) {
313326 }
314327 }
315328
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 () {
329+ /**
330+ * @return The {@link ObservableList} of attachments.
331+ */
332+ public ObservableList <Attachment > getAttachments () {
325333 return attachments ;
326334 }
327335
328336 /**
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) .
337+ * Adds {@link Attachment}s to the list of {@link Attachment}s. If only one
338+ * {@link Attachment} is added it is also selected .
331339 *
332- * @param attachment The new {@link Attachment}
340+ * @param attachmentsList The new {@link Attachment}s
333341 */
334- public void addAttachment (Attachment attachment ) {
335- attachments .add (attachment );
336- attachmentListView .getSelectionModel ().select (attachment );
342+ public void addAttachments (List <Attachment > attachmentsList ) {
343+ Platform .runLater (() -> {
344+ attachmentListView .getSelectionModel ().clearSelection ();
345+ attachments .addAll (attachmentsList );
346+ attachmentListView .getSelectionModel ().select (attachmentsList .get (0 ));
347+ });
337348 }
338349}
0 commit comments