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

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