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

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