Autopsy  4.5.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 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.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;
54 import static org.sleuthkit.autopsy.corecomponents.Bundle.*;
58 import org.sleuthkit.datamodel.AbstractFile;
59 import org.sleuthkit.datamodel.TskCoreException;
60 
72 //@ServiceProvider(service = DataResultViewer.class)
73 final class DataResultViewerThumbnail extends AbstractDataResultViewer {
74 
75  private static final long serialVersionUID = 1L;
76  private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
77  private int curPage;
78  private int totalPages;
79  private int curPageImages;
80  private int thumbSize = ImageUtils.ICON_SIZE_MEDIUM;
81  private final PageUpdater pageUpdater = new PageUpdater();
82  private TableFilterNode tfn;
83  private ThumbnailViewChildren tvc;
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 (thumbSize != newIconSize) {
299  thumbSize = newIconSize;
300  Node root = em.getRootContext();
301  ((ThumbnailViewChildren) root.getChildren()).setThumbsSize(thumbSize);
302 
303 
304 
305  // Temporarily set the explored context to the root, instead of a child node.
306  // This is a workaround hack to convince org.openide.explorer.ExplorerManager to
307  // update even though the new and old Node values are identical. This in turn
308  // will cause the entire view to update completely. After this we
309  // immediately set the node back to the current child by calling switchPage().
310  em.setExploredContext(root);
311  switchPage();
312  }
313  }//GEN-LAST:event_thumbnailSizeComboBoxActionPerformed
314 
315  private void sortButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortButtonActionPerformed
316  List<Node.Property<?>> childProperties = ResultViewerPersistence.getAllChildProperties(em.getRootContext(), 100);
317  SortChooser sortChooser = new SortChooser(childProperties, ResultViewerPersistence.loadSortCriteria(tfn));
318  DialogDescriptor dialogDescriptor = new DialogDescriptor(sortChooser, sortChooser.getDialogTitle());
319  Dialog createDialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
320  createDialog.setVisible(true);
321  final Object dialogReturnValue = dialogDescriptor.getValue();
322  if (DialogDescriptor.OK_OPTION == dialogReturnValue) {
323  //apply new sort
324  List<SortCriterion> criteria = sortChooser.getCriteria();
325  final Preferences preferences = NbPreferences.forModule(DataResultViewerThumbnail.class);
326 
327  Map<Node.Property<?>, SortCriterion> criteriaMap = criteria.stream()
328  .collect(Collectors.toMap(SortCriterion::getProperty,
329  Function.identity(),
330  (u, v) -> u)); //keep first criteria if property is selected multiple times.
331 
332  //store the sorting information
333  int numProperties = childProperties.size();
334  for (int i = 0; i < numProperties; i++) {
335  Node.Property<?> prop = childProperties.get(i);
336  String propName = prop.getName();
337  SortCriterion criterion = criteriaMap.get(prop);
338  final String columnSortOrderKey = ResultViewerPersistence.getColumnSortOrderKey(tfn, propName);
339  final String columnSortRankKey = ResultViewerPersistence.getColumnSortRankKey(tfn, propName);
340 
341  if (criterion != null) {
342  preferences.putBoolean(columnSortOrderKey, criterion.getSortOrder() == SortOrder.ASCENDING);
343  preferences.putInt(columnSortRankKey, criterion.getSortRank() + 1);
344  } else {
345  preferences.remove(columnSortOrderKey);
346  preferences.remove(columnSortRankKey);
347  }
348  }
349  setNode(tfn); //this is just to force a refresh
350  }
351  }//GEN-LAST:event_sortButtonActionPerformed
352 
353 
354  // Variables declaration - do not modify//GEN-BEGIN:variables
355  private javax.swing.JLabel filePathLabel;
356  private javax.swing.JTextField goToPageField;
357  private javax.swing.JLabel goToPageLabel;
358  private org.openide.explorer.view.IconView iconView;
359  private javax.swing.JLabel imagesLabel;
360  private javax.swing.JLabel imagesRangeLabel;
361  private javax.swing.JLabel pageLabel;
362  private javax.swing.JButton pageNextButton;
363  private javax.swing.JLabel pageNumLabel;
364  private javax.swing.JButton pagePrevButton;
365  private javax.swing.JLabel pagesLabel;
366  private javax.swing.JButton sortButton;
367  private javax.swing.JLabel sortLabel;
368  private javax.swing.JComboBox<String> thumbnailSizeComboBox;
369  // End of variables declaration//GEN-END:variables
370 
371  @Override
372  public boolean isSupported(Node selectedNode) {
373  if (selectedNode == null) {
374  return false;
375  }
376  return true;
377  }
378 
379  @Override
380  public void setNode(Node givenNode) {
381  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
382  if (tvc != null) {
383  tvc.cancelLoadingThumbnails();
384  }
385  try {
386  if (givenNode != null) {
387  tfn = (TableFilterNode) givenNode;
388  /*
389  * Wrap the given node in a ThumbnailViewChildren that will
390  * produce ThumbnailPageNodes with ThumbnailViewNode children
391  * from the child nodes of the given node.
392  */
393  tvc = new ThumbnailViewChildren(givenNode,thumbSize);
394  final Node root = new AbstractNode(tvc);
395 
396  pageUpdater.setRoot(root);
397  root.addNodeListener(pageUpdater);
398  em.setRootContext(root);
399  } else {
400  tfn = null;
401  tvc = null;
402  Node emptyNode = new AbstractNode(Children.LEAF);
403  em.setRootContext(emptyNode);
404  iconView.setBackground(Color.BLACK);
405  }
406  } finally {
407  this.setCursor(null);
408  }
409  }
410 
411  @Override
412  public String getTitle() {
413  return NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.title");
414  }
415 
416  @Override
417  public DataResultViewer createInstance() {
418  return new DataResultViewerThumbnail();
419  }
420 
421  @Override
422  public void resetComponent() {
423  super.resetComponent();
424  this.totalPages = 0;
425  this.curPage = -1;
426  curPageImages = 0;
427  updateControls();
428  }
429 
430  @Override
431  public void clearComponent() {
432  this.iconView.removeAll();
433  this.iconView = null;
434  super.clearComponent();
435  }
436 
437  private void nextPage() {
438  if (curPage < totalPages) {
439  curPage++;
440  switchPage();
441  }
442  }
443 
444  private void previousPage() {
445  if (curPage > 1) {
446  curPage--;
447  switchPage();
448  }
449  }
450 
451  private void goToPage(String pageNumText) {
452  int newPage;
453  try {
454  newPage = Integer.parseInt(pageNumText);
455  } catch (NumberFormatException e) {
456  //ignore input
457  return;
458  }
459 
460  if (newPage > totalPages || newPage < 1) {
461  JOptionPane.showMessageDialog(this,
462  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.goToPageTextField.msgDlg", totalPages),
463  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.goToPageTextField.err"),
464  JOptionPane.WARNING_MESSAGE);
465  return;
466  }
467 
468  curPage = newPage;
469  switchPage();
470  }
471 
472  private void switchPage() {
473 
474  EventQueue.invokeLater(() -> {
475  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
476  });
477 
478  //Note the nodes factories are likely creating nodes in EDT anyway, but worker still helps
479  new SwingWorker<Object, Void>() {
480  private ProgressHandle progress;
481 
482  @Override
483  protected Object doInBackground() throws Exception {
484  pagePrevButton.setEnabled(false);
485  pageNextButton.setEnabled(false);
486  goToPageField.setEnabled(false);
487  progress = ProgressHandle.createHandle(
488  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.genThumbs"));
489  progress.start();
490  progress.switchToIndeterminate();
491  Node root = em.getRootContext();
492  Node pageNode = root.getChildren().getNodeAt(curPage - 1);
493  em.setExploredContext(pageNode);
494  curPageImages = pageNode.getChildren().getNodesCount();
495  return null;
496  }
497 
498  @Override
499  protected void done() {
500  progress.finish();
501  setCursor(null);
502  updateControls();
503  // see if any exceptions were thrown
504  try {
505  get();
506  } catch (InterruptedException | ExecutionException ex) {
507  NotifyDescriptor d =
508  new NotifyDescriptor.Message(
509  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.switchPage.done.errMsg",
510  ex.getMessage()),
511  NotifyDescriptor.ERROR_MESSAGE);
512  DialogDisplayer.getDefault().notify(d);
513  logger.log(Level.SEVERE, "Error making thumbnails: {0}", ex.getMessage()); //NON-NLS
514  } // catch and ignore if we were cancelled
515  catch (java.util.concurrent.CancellationException ex) {
516  }
517  }
518  }.execute();
519 
520  }
521 
522  @NbBundle.Messages({
523  "# {0} - sort criteria", "DataResultViewerThumbnail.sortLabel.textTemplate=Sorted by: {0}",
524  "DataResultViewerThumbnail.sortLabel.text=Sorted by: ---"})
525  private void updateControls() {
526  if (totalPages == 0) {
527  pagePrevButton.setEnabled(false);
528  pageNextButton.setEnabled(false);
529  goToPageField.setEnabled(false);
530  pageNumLabel.setText("");
531  imagesRangeLabel.setText("");
532  thumbnailSizeComboBox.setEnabled(false);
533  sortButton.setEnabled(false);
534  sortLabel.setText(DataResultViewerThumbnail_sortLabel_text());
535 
536  } else {
537  pageNumLabel.setText(
538  NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
539  Integer.toString(curPage), Integer.toString(totalPages)));
540  final int imagesFrom = (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
541  final int imagesTo = curPageImages + (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
542  imagesRangeLabel.setText(imagesFrom + "-" + imagesTo);
543 
544  pageNextButton.setEnabled(!(curPage == totalPages));
545  pagePrevButton.setEnabled(!(curPage == 1));
546  goToPageField.setEnabled(totalPages > 1);
547  sortButton.setEnabled(true);
548  thumbnailSizeComboBox.setEnabled(true);
549  if (tfn != null) {
550  String sortString = ResultViewerPersistence.loadSortCriteria(tfn).stream()
551  .map(SortCriterion::toString)
552  .collect(Collectors.joining(" "));
553  sortString = StringUtils.defaultIfBlank(sortString, "---");
554  sortLabel.setText(Bundle.DataResultViewerThumbnail_sortLabel_textTemplate(sortString));
555  } else {
556  sortLabel.setText(DataResultViewerThumbnail_sortLabel_text());
557  }
558  }
559  }
560 
564  private class PageUpdater implements NodeListener {
565 
566  private Node root;
567 
568  void setRoot(Node root) {
569  this.root = root;
570  }
571 
572  @Override
573  public void propertyChange(PropertyChangeEvent evt) {
574  }
575 
576  @Override
577  public void childrenAdded(NodeMemberEvent nme) {
578  totalPages = root.getChildren().getNodesCount();
579 
580  if (totalPages == 0) {
581  curPage = -1;
582  updateControls();
583  return;
584  }
585 
586  if (curPage == -1 || curPage > totalPages) {
587  curPage = 1;
588  }
589 
590  //force load the curPage node
591  final Node pageNode = root.getChildren().getNodeAt(curPage - 1);
592 
593  //em.setSelectedNodes(new Node[]{pageNode});
594  if (pageNode != null) {
595  pageNode.addNodeListener(new NodeListener() {
596  @Override
597  public void childrenAdded(NodeMemberEvent nme) {
598  curPageImages = pageNode.getChildren().getNodesCount();
599  updateControls();
600  }
601 
602  @Override
603  public void childrenRemoved(NodeMemberEvent nme) {
604  curPageImages = 0;
605  updateControls();
606  }
607 
608  @Override
609  public void childrenReordered(NodeReorderEvent nre) {
610  }
611 
612  @Override
613  public void nodeDestroyed(NodeEvent ne) {
614  }
615 
616  @Override
617  public void propertyChange(PropertyChangeEvent evt) {
618  }
619  });
620 
621  em.setExploredContext(pageNode);
622  }
623 
624  updateControls();
625  }
626 
627  @Override
628  public void childrenRemoved(NodeMemberEvent nme) {
629  totalPages = 0;
630  curPage = -1;
631  updateControls();
632  }
633 
634  @Override
635  public void childrenReordered(NodeReorderEvent nre) {
636  }
637 
638  @Override
639  public void nodeDestroyed(NodeEvent ne) {
640  }
641  }
642 
643  private class ExplorerManagerNodeSelectionListener implements PropertyChangeListener {
644 
645  @Override
646  public void propertyChange(PropertyChangeEvent evt) {
647  if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
648  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
649  try {
650  Node[] selectedNodes = em.getSelectedNodes();
651  if (selectedNodes.length == 1) {
652  AbstractFile af = selectedNodes[0].getLookup().lookup(AbstractFile.class);
653  if (af == null) {
654  filePathLabel.setText("");
655  } else {
656  try {
657  String uPath = af.getUniquePath();
658  filePathLabel.setText(uPath);
659  filePathLabel.setToolTipText(uPath);
660  } catch (TskCoreException e) {
661  logger.log(Level.WARNING, "Could not get unique path for content: {0}", af.getName()); //NON-NLS
662  }
663  }
664  } else {
665  filePathLabel.setText("");
666  }
667  } finally {
668  setCursor(null);
669  }
670  }
671  }
672  }
673 
674 }

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