Autopsy  4.7.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataResultViewerThumbnail.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2012-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.corecomponents;
20 
21 import java.awt.Color;
22 import java.awt.Cursor;
23 import java.awt.Dialog;
24 import java.awt.EventQueue;
25 import java.beans.PropertyChangeEvent;
26 import java.beans.PropertyChangeListener;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.ExecutionException;
30 import java.util.function.Function;
31 import java.util.logging.Level;
32 import java.util.prefs.Preferences;
33 import java.util.stream.Collectors;
34 import javax.swing.JOptionPane;
35 import javax.swing.ListSelectionModel;
36 import javax.swing.SortOrder;
37 import javax.swing.SwingWorker;
38 import org.apache.commons.lang3.StringUtils;
39 import org.netbeans.api.progress.ProgressHandle;
40 import org.openide.DialogDescriptor;
41 import org.openide.DialogDisplayer;
42 import org.openide.NotifyDescriptor;
43 import org.openide.explorer.ExplorerManager;
44 import org.openide.nodes.AbstractNode;
45 import org.openide.nodes.Children;
46 import org.openide.nodes.Node;
47 import org.openide.nodes.NodeEvent;
48 import org.openide.nodes.NodeListener;
49 import org.openide.nodes.NodeMemberEvent;
50 import org.openide.nodes.NodeReorderEvent;
51 import org.openide.util.NbBundle;
52 import org.openide.util.NbPreferences;
53 import org.openide.util.lookup.ServiceProvider;
55 import static org.sleuthkit.autopsy.corecomponents.Bundle.*;
59 import org.sleuthkit.datamodel.AbstractFile;
60 import org.sleuthkit.datamodel.TskCoreException;
61 
73 @ServiceProvider(service = DataResultViewer.class)
74 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
76 
77  private static final long serialVersionUID = 1L;
78  private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
79  private final PageUpdater pageUpdater = new PageUpdater();
81  private ThumbnailViewChildren rootNodeChildren;
83  private int currentPage;
84  private int totalPages;
85  private int currentPageImages;
86  private int thumbSize = ImageUtils.ICON_SIZE_MEDIUM;
87 
96  this(null);
97  }
98 
108  @NbBundle.Messages({
109  "DataResultViewerThumbnail.thumbnailSizeComboBox.small=Small Thumbnails",
110  "DataResultViewerThumbnail.thumbnailSizeComboBox.medium=Medium Thumbnails",
111  "DataResultViewerThumbnail.thumbnailSizeComboBox.large=Large Thumbnails"
112  })
113  public DataResultViewerThumbnail(ExplorerManager explorerManager) {
114  super(explorerManager);
115  initComponents();
116  iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
117  thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{
118  Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
119  Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
120  Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large()}));
121  thumbnailSizeComboBox.setSelectedIndex(1);
122  currentPage = -1;
123  totalPages = 0;
124  currentPageImages = 0;
125  }
126 
132  @SuppressWarnings("unchecked")
133  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
134  private void initComponents() {
135 
136  pageLabel = new javax.swing.JLabel();
137  pagesLabel = new javax.swing.JLabel();
138  pagePrevButton = new javax.swing.JButton();
139  pageNextButton = new javax.swing.JButton();
140  imagesLabel = new javax.swing.JLabel();
141  imagesRangeLabel = new javax.swing.JLabel();
142  pageNumLabel = new javax.swing.JLabel();
143  filePathLabel = new javax.swing.JLabel();
144  goToPageLabel = new javax.swing.JLabel();
145  goToPageField = new javax.swing.JTextField();
146  thumbnailSizeComboBox = new javax.swing.JComboBox<>();
147  iconView = new org.openide.explorer.view.IconView();
148  sortButton = new javax.swing.JButton();
149  sortLabel = new javax.swing.JLabel();
150 
151  pageLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageLabel.text")); // NOI18N
152 
153  pagesLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pagesLabel.text")); // NOI18N
154 
155  pagePrevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
156  pagePrevButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pagePrevButton.text")); // NOI18N
157  pagePrevButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
158  pagePrevButton.setFocusable(false);
159  pagePrevButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
160  pagePrevButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
161  pagePrevButton.setPreferredSize(new java.awt.Dimension(55, 23));
162  pagePrevButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N
163  pagePrevButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
164  pagePrevButton.addActionListener(new java.awt.event.ActionListener() {
165  public void actionPerformed(java.awt.event.ActionEvent evt) {
166  pagePrevButtonActionPerformed(evt);
167  }
168  });
169 
170  pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
171  pageNextButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageNextButton.text")); // NOI18N
172  pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
173  pageNextButton.setFocusable(false);
174  pageNextButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
175  pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
176  pageNextButton.setMaximumSize(new java.awt.Dimension(27, 23));
177  pageNextButton.setMinimumSize(new java.awt.Dimension(27, 23));
178  pageNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N
179  pageNextButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
180  pageNextButton.addActionListener(new java.awt.event.ActionListener() {
181  public void actionPerformed(java.awt.event.ActionEvent evt) {
182  pageNextButtonActionPerformed(evt);
183  }
184  });
185 
186  imagesLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesLabel.text")); // NOI18N
187 
188  imagesRangeLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesRangeLabel.text")); // NOI18N
189 
190  pageNumLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageNumLabel.text")); // NOI18N
191 
192  filePathLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.filePathLabel.text")); // NOI18N
193 
194  goToPageLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.goToPageLabel.text")); // NOI18N
195 
196  goToPageField.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.goToPageField.text")); // NOI18N
197  goToPageField.addActionListener(new java.awt.event.ActionListener() {
198  public void actionPerformed(java.awt.event.ActionEvent evt) {
199  goToPageFieldActionPerformed(evt);
200  }
201  });
202 
203  thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() {
204  public void actionPerformed(java.awt.event.ActionEvent evt) {
205  thumbnailSizeComboBoxActionPerformed(evt);
206  }
207  });
208 
209  sortButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.sortButton.text")); // NOI18N
210  sortButton.addActionListener(new java.awt.event.ActionListener() {
211  public void actionPerformed(java.awt.event.ActionEvent evt) {
212  sortButtonActionPerformed(evt);
213  }
214  });
215 
216  sortLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.sortLabel.text")); // NOI18N
217 
218  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
219  this.setLayout(layout);
220  layout.setHorizontalGroup(
221  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
222  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
223  .addContainerGap()
224  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
225  .addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
226  .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
227  .addComponent(pageLabel)
228  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
229  .addComponent(pageNumLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
230  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
231  .addComponent(pagesLabel)
232  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
233  .addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
234  .addGap(0, 0, 0)
235  .addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
236  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
237  .addComponent(goToPageLabel)
238  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
239  .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
240  .addGap(12, 12, 12)
241  .addComponent(imagesLabel)
242  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
243  .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
244  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
245  .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
246  .addGap(30, 30, 30)
247  .addComponent(sortButton)
248  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
249  .addComponent(sortLabel))
250  .addComponent(filePathLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
251  .addContainerGap())
252  );
253  layout.setVerticalGroup(
254  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
255  .addGroup(layout.createSequentialGroup()
256  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
257  .addComponent(pageLabel)
258  .addComponent(pageNumLabel)
259  .addComponent(pagesLabel)
260  .addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
261  .addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
262  .addComponent(goToPageLabel)
263  .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
264  .addComponent(imagesLabel)
265  .addComponent(imagesRangeLabel)
266  .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
267  .addComponent(sortButton)
268  .addComponent(sortLabel))
269  .addGap(13, 13, 13)
270  .addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 322, Short.MAX_VALUE)
271  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
272  .addComponent(filePathLabel))
273  );
274  }// </editor-fold>//GEN-END:initComponents
275 
276  private void pagePrevButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pagePrevButtonActionPerformed
277  previousPage();
278  }//GEN-LAST:event_pagePrevButtonActionPerformed
279 
280  private void pageNextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pageNextButtonActionPerformed
281  nextPage();
282  }//GEN-LAST:event_pageNextButtonActionPerformed
283 
284  private void goToPageFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageFieldActionPerformed
285  goToPage(goToPageField.getText());
286  }//GEN-LAST:event_goToPageFieldActionPerformed
287 
288  private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed
289  int newIconSize;
290  switch (thumbnailSizeComboBox.getSelectedIndex()) {
291  case 0:
292  newIconSize = ImageUtils.ICON_SIZE_SMALL;
293  break;
294  case 2:
295  newIconSize = ImageUtils.ICON_SIZE_LARGE;
296  break;
297  case 1:
298  default:
299  newIconSize = ImageUtils.ICON_SIZE_MEDIUM; //default size
300  break;
301  }
302 
303  if (thumbSize != newIconSize) {
304  thumbSize = newIconSize;
305  Node root = this.getExplorerManager().getRootContext();
306  ((ThumbnailViewChildren) root.getChildren()).setThumbsSize(thumbSize);
307 
308  // Temporarily set the explored context to the root, instead of a child node.
309  // This is a workaround hack to convince org.openide.explorer.ExplorerManager to
310  // update even though the new and old Node values are identical. This in turn
311  // will cause the entire view to update completely. After this we
312  // immediately set the node back to the current child by calling switchPage().
313  this.getExplorerManager().setExploredContext(root);
314  switchPage();
315  }
316  }//GEN-LAST:event_thumbnailSizeComboBoxActionPerformed
317 
318  private void sortButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortButtonActionPerformed
319  List<Node.Property<?>> childProperties = ResultViewerPersistence.getAllChildProperties(this.getExplorerManager().getRootContext(), 100);
320  SortChooser sortChooser = new SortChooser(childProperties, ResultViewerPersistence.loadSortCriteria(rootNode));
321  DialogDescriptor dialogDescriptor = new DialogDescriptor(sortChooser, sortChooser.getDialogTitle());
322  Dialog createDialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
323  createDialog.setVisible(true);
324  final Object dialogReturnValue = dialogDescriptor.getValue();
325  if (DialogDescriptor.OK_OPTION == dialogReturnValue) {
326  //apply new sort
327  List<SortCriterion> criteria = sortChooser.getCriteria();
328  final Preferences preferences = NbPreferences.forModule(DataResultViewerThumbnail.class);
329 
330  Map<Node.Property<?>, SortCriterion> criteriaMap = criteria.stream()
331  .collect(Collectors.toMap(SortCriterion::getProperty,
332  Function.identity(),
333  (u, v) -> u)); //keep first criteria if property is selected multiple times.
334 
335  //store the sorting information
336  int numProperties = childProperties.size();
337  for (int i = 0; i < numProperties; i++) {
338  Node.Property<?> prop = childProperties.get(i);
339  String propName = prop.getName();
340  SortCriterion criterion = criteriaMap.get(prop);
341  final String columnSortOrderKey = ResultViewerPersistence.getColumnSortOrderKey(rootNode, propName);
342  final String columnSortRankKey = ResultViewerPersistence.getColumnSortRankKey(rootNode, propName);
343 
344  if (criterion != null) {
345  preferences.putBoolean(columnSortOrderKey, criterion.getSortOrder() == SortOrder.ASCENDING);
346  preferences.putInt(columnSortRankKey, criterion.getSortRank() + 1);
347  } else {
348  preferences.remove(columnSortOrderKey);
349  preferences.remove(columnSortRankKey);
350  }
351  }
352  setNode(rootNode); //this is just to force a refresh
353  }
354  }//GEN-LAST:event_sortButtonActionPerformed
355 
356 
357  // Variables declaration - do not modify//GEN-BEGIN:variables
358  private javax.swing.JLabel filePathLabel;
359  private javax.swing.JTextField goToPageField;
360  private javax.swing.JLabel goToPageLabel;
361  private org.openide.explorer.view.IconView iconView;
362  private javax.swing.JLabel imagesLabel;
363  private javax.swing.JLabel imagesRangeLabel;
364  private javax.swing.JLabel pageLabel;
365  private javax.swing.JButton pageNextButton;
366  private javax.swing.JLabel pageNumLabel;
367  private javax.swing.JButton pagePrevButton;
368  private javax.swing.JLabel pagesLabel;
369  private javax.swing.JButton sortButton;
370  private javax.swing.JLabel sortLabel;
371  private javax.swing.JComboBox<String> thumbnailSizeComboBox;
372  // End of variables declaration//GEN-END:variables
373 
374  @Override
375  public boolean isSupported(Node selectedNode) {
376  return (selectedNode != null);
377  }
378 
379  @Override
380  public void setNode(Node givenNode) {
381  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
382  if (selectionListener == null) {
383  this.getExplorerManager().addPropertyChangeListener(new NodeSelectionListener()); // RJCTODO: remove listener on cleanup
384  }
385  if (rootNodeChildren != null) {
386  rootNodeChildren.cancelLoadingThumbnails();
387  }
388  try {
389  if (givenNode != null) {
390  rootNode = (TableFilterNode) givenNode;
391  /*
392  * Wrap the given node in a ThumbnailViewChildren that will
393  * produce ThumbnailPageNodes with ThumbnailViewNode children
394  * from the child nodes of the given node.
395  */
396  rootNodeChildren = new ThumbnailViewChildren(givenNode, thumbSize);
397  final Node root = new AbstractNode(rootNodeChildren);
398 
399  pageUpdater.setRoot(root);
400  root.addNodeListener(pageUpdater);
401  this.getExplorerManager().setRootContext(root);
402  } else {
403  rootNode = null;
404  rootNodeChildren = null;
405  Node emptyNode = new AbstractNode(Children.LEAF);
406  this.getExplorerManager().setRootContext(emptyNode);
407  iconView.setBackground(Color.BLACK);
408  }
409  } finally {
410  this.setCursor(null);
411  }
412  }
413 
414  @Override
415  public String getTitle() {
416  return NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.title");
417  }
418 
419  @Override
421  return new DataResultViewerThumbnail();
422  }
423 
424  @Override
425  public void resetComponent() {
426  super.resetComponent();
427  this.totalPages = 0;
428  this.currentPage = -1;
429  currentPageImages = 0;
430  updateControls();
431  }
432 
433  @Override
434  public void clearComponent() {
435  this.iconView.removeAll();
436  this.iconView = null;
437  super.clearComponent();
438  }
439 
440  private void nextPage() {
441  if (currentPage < totalPages) {
442  currentPage++;
443  switchPage();
444  }
445  }
446 
447  private void previousPage() {
448  if (currentPage > 1) {
449  currentPage--;
450  switchPage();
451  }
452  }
453 
454  private void goToPage(String pageNumText) {
455  int newPage;
456  try {
457  newPage = Integer.parseInt(pageNumText);
458  } catch (NumberFormatException e) {
459  //ignore input
460  return;
461  }
462 
463  if (newPage > totalPages || newPage < 1) {
464  JOptionPane.showMessageDialog(this,
465  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.goToPageTextField.msgDlg", totalPages),
466  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.goToPageTextField.err"),
467  JOptionPane.WARNING_MESSAGE);
468  return;
469  }
470 
471  currentPage = newPage;
472  switchPage();
473  }
474 
475  private void switchPage() {
476 
477  EventQueue.invokeLater(() -> {
478  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
479  });
480 
481  //Note the nodes factories are likely creating nodes in EDT anyway, but worker still helps
482  new SwingWorker<Object, Void>() {
483  private ProgressHandle progress;
484 
485  @Override
486  protected Object doInBackground() throws Exception {
487  pagePrevButton.setEnabled(false);
488  pageNextButton.setEnabled(false);
489  goToPageField.setEnabled(false);
490  progress = ProgressHandle.createHandle(
491  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.genThumbs"));
492  progress.start();
493  progress.switchToIndeterminate();
494  ExplorerManager explorerManager = DataResultViewerThumbnail.this.getExplorerManager();
495  Node root = explorerManager.getRootContext();
496  Node pageNode = root.getChildren().getNodeAt(currentPage - 1);
497  explorerManager.setExploredContext(pageNode);
498  currentPageImages = pageNode.getChildren().getNodesCount();
499  return null;
500  }
501 
502  @Override
503  protected void done() {
504  progress.finish();
505  setCursor(null);
506  updateControls();
507  // see if any exceptions were thrown
508  try {
509  get();
510  } catch (InterruptedException | ExecutionException ex) {
511  NotifyDescriptor d
512  = new NotifyDescriptor.Message(
513  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.switchPage.done.errMsg",
514  ex.getMessage()),
515  NotifyDescriptor.ERROR_MESSAGE);
516  DialogDisplayer.getDefault().notify(d);
517  logger.log(Level.SEVERE, "Error making thumbnails: {0}", ex.getMessage()); //NON-NLS
518  }
519  catch (java.util.concurrent.CancellationException ex) {
520  // catch and ignore if we were cancelled
521  }
522  }
523  }.execute();
524 
525  }
526 
527  @NbBundle.Messages({
528  "# {0} - sort criteria", "DataResultViewerThumbnail.sortLabel.textTemplate=Sorted by: {0}",
529  "DataResultViewerThumbnail.sortLabel.text=Sorted by: ---"})
530  private void updateControls() {
531  if (totalPages == 0) {
532  pagePrevButton.setEnabled(false);
533  pageNextButton.setEnabled(false);
534  goToPageField.setEnabled(false);
535  pageNumLabel.setText("");
536  imagesRangeLabel.setText("");
537  thumbnailSizeComboBox.setEnabled(false);
538  sortButton.setEnabled(false);
539  sortLabel.setText(DataResultViewerThumbnail_sortLabel_text());
540 
541  } else {
542  pageNumLabel.setText(NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
543  Integer.toString(currentPage), Integer.toString(totalPages)));
544  final int imagesFrom = (currentPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
545  final int imagesTo = currentPageImages + (currentPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
546  imagesRangeLabel.setText(imagesFrom + "-" + imagesTo);
547 
548  pageNextButton.setEnabled(!(currentPage == totalPages));
549  pagePrevButton.setEnabled(!(currentPage == 1));
550  goToPageField.setEnabled(totalPages > 1);
551  sortButton.setEnabled(true);
552  thumbnailSizeComboBox.setEnabled(true);
553  if (rootNode != null) {
554  String sortString = ResultViewerPersistence.loadSortCriteria(rootNode).stream()
555  .map(SortCriterion::toString)
556  .collect(Collectors.joining(" "));
557  sortString = StringUtils.defaultIfBlank(sortString, "---");
558  sortLabel.setText(Bundle.DataResultViewerThumbnail_sortLabel_textTemplate(sortString));
559  } else {
560  sortLabel.setText(DataResultViewerThumbnail_sortLabel_text());
561  }
562  }
563  }
564 
568  private class PageUpdater implements NodeListener {
569 
570  private Node root;
571 
572  void setRoot(Node root) {
573  this.root = root;
574  }
575 
576  @Override
577  public void propertyChange(PropertyChangeEvent evt) {
578  }
579 
580  @Override
581  public void childrenAdded(NodeMemberEvent nme) {
582  totalPages = root.getChildren().getNodesCount();
583 
584  if (totalPages == 0) {
585  currentPage = -1;
586  updateControls();
587  return;
588  }
589 
590  if (currentPage == -1 || currentPage > totalPages) {
591  currentPage = 1;
592  }
593 
594  //force load the curPage node
595  final Node pageNode = root.getChildren().getNodeAt(currentPage - 1);
596 
597  //em.setSelectedNodes(new Node[]{pageNode});
598  if (pageNode != null) {
599  pageNode.addNodeListener(new NodeListener() {
600  @Override
601  public void childrenAdded(NodeMemberEvent nme) {
602  currentPageImages = pageNode.getChildren().getNodesCount();
603  updateControls();
604  }
605 
606  @Override
607  public void childrenRemoved(NodeMemberEvent nme) {
608  currentPageImages = 0;
609  updateControls();
610  }
611 
612  @Override
613  public void childrenReordered(NodeReorderEvent nre) {
614  }
615 
616  @Override
617  public void nodeDestroyed(NodeEvent ne) {
618  }
619 
620  @Override
621  public void propertyChange(PropertyChangeEvent evt) {
622  }
623  });
624 
625  DataResultViewerThumbnail.this.getExplorerManager().setExploredContext(pageNode);
626  }
627 
628  updateControls();
629  }
630 
631  @Override
632  public void childrenRemoved(NodeMemberEvent nme) {
633  totalPages = 0;
634  currentPage = -1;
635  updateControls();
636  }
637 
638  @Override
639  public void childrenReordered(NodeReorderEvent nre) {
640  }
641 
642  @Override
643  public void nodeDestroyed(NodeEvent ne) {
644  }
645  }
646 
647  private class NodeSelectionListener implements PropertyChangeListener {
648 
649  @Override
650  public void propertyChange(PropertyChangeEvent evt) {
651  if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
652  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
653  try {
654  Node[] selectedNodes = DataResultViewerThumbnail.this.getExplorerManager().getSelectedNodes();
655  if (selectedNodes.length == 1) {
656  AbstractFile af = selectedNodes[0].getLookup().lookup(AbstractFile.class);
657  if (af == null) {
658  filePathLabel.setText("");
659  } else {
660  try {
661  String uPath = af.getUniquePath();
662  filePathLabel.setText(uPath);
663  filePathLabel.setToolTipText(uPath);
664  } catch (TskCoreException e) {
665  logger.log(Level.WARNING, "Could not get unique path for content: {0}", af.getName()); //NON-NLS
666  }
667  }
668  } else {
669  filePathLabel.setText("");
670  }
671  } finally {
672  setCursor(null);
673  }
674  }
675  }
676  }
677 }
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2016 Basis Technology. Generated on: Mon Jun 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.