19 package org.sleuthkit.autopsy.corecomponents;
21 import java.awt.Color;
22 import java.awt.Cursor;
23 import java.awt.EventQueue;
24 import java.beans.PropertyChangeEvent;
25 import java.beans.PropertyChangeListener;
26 import java.util.Arrays;
27 import java.util.concurrent.ExecutionException;
28 import java.util.logging.Level;
29 import javax.swing.JOptionPane;
30 import javax.swing.ListSelectionModel;
31 import javax.swing.SwingWorker;
32 import org.netbeans.api.progress.ProgressHandle;
33 import org.openide.DialogDisplayer;
34 import org.openide.NotifyDescriptor;
35 import org.openide.explorer.ExplorerManager;
36 import org.openide.nodes.AbstractNode;
37 import org.openide.nodes.Children;
38 import org.openide.nodes.Node;
39 import org.openide.nodes.NodeEvent;
40 import org.openide.nodes.NodeListener;
41 import org.openide.nodes.NodeMemberEvent;
42 import org.openide.nodes.NodeReorderEvent;
43 import org.openide.util.NbBundle;
62 final class DataResultViewerThumbnail
extends AbstractDataResultViewer {
64 private static final long serialVersionUID = 1L;
65 private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
68 private int totalPages;
69 private int curPageImages;
70 private int iconSize = ImageUtils.ICON_SIZE_MEDIUM;
71 private final PageUpdater pageUpdater =
new PageUpdater();
77 DataResultViewerThumbnail(ExplorerManager explorerManager) {
78 super(explorerManager);
86 DataResultViewerThumbnail() {
90 @NbBundle.Messages({
"DataResultViewerThumbnail.thumbnailSizeComboBox.small=Small Thumbnails",
91 "DataResultViewerThumbnail.thumbnailSizeComboBox.medium=Medium Thumbnails",
92 "DataResultViewerThumbnail.thumbnailSizeComboBox.large=Large Thumbnails"
94 private void initialize() {
97 iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
98 em.addPropertyChangeListener(
new ExplorerManagerNodeSelectionListener());
99 thumbnailSizeComboBox.setModel(
new javax.swing.DefaultComboBoxModel<>(
100 new String[]{Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
101 Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
102 Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large()}));
103 thumbnailSizeComboBox.setSelectedIndex(1);
114 @SuppressWarnings(
"unchecked")
116 private
void initComponents() {
118 pageLabel =
new javax.swing.JLabel();
119 pagesLabel =
new javax.swing.JLabel();
120 pagePrevButton =
new javax.swing.JButton();
121 pageNextButton =
new javax.swing.JButton();
122 imagesLabel =
new javax.swing.JLabel();
123 imagesRangeLabel =
new javax.swing.JLabel();
124 pageNumLabel =
new javax.swing.JLabel();
125 filePathLabel =
new javax.swing.JLabel();
126 goToPageLabel =
new javax.swing.JLabel();
127 goToPageField =
new javax.swing.JTextField();
128 thumbnailSizeComboBox =
new javax.swing.JComboBox<>();
129 iconView =
new org.openide.explorer.view.IconView();
131 pageLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageLabel.text"));
133 pagesLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pagesLabel.text"));
135 pagePrevButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
136 pagePrevButton.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pagePrevButton.text"));
137 pagePrevButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
138 pagePrevButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
139 pagePrevButton.setPreferredSize(
new java.awt.Dimension(55, 23));
140 pagePrevButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png")));
141 pagePrevButton.addActionListener(
new java.awt.event.ActionListener() {
142 public void actionPerformed(java.awt.event.ActionEvent evt) {
143 pagePrevButtonActionPerformed(evt);
147 pageNextButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
148 pageNextButton.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageNextButton.text"));
149 pageNextButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
150 pageNextButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
151 pageNextButton.setMaximumSize(
new java.awt.Dimension(27, 23));
152 pageNextButton.setMinimumSize(
new java.awt.Dimension(27, 23));
153 pageNextButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png")));
154 pageNextButton.addActionListener(
new java.awt.event.ActionListener() {
155 public void actionPerformed(java.awt.event.ActionEvent evt) {
156 pageNextButtonActionPerformed(evt);
160 imagesLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.imagesLabel.text"));
162 imagesRangeLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.imagesRangeLabel.text"));
164 pageNumLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageNumLabel.text"));
166 filePathLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.filePathLabel.text"));
168 goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.goToPageLabel.text"));
170 goToPageField.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.goToPageField.text"));
171 goToPageField.addActionListener(
new java.awt.event.ActionListener() {
172 public void actionPerformed(java.awt.event.ActionEvent evt) {
173 goToPageFieldActionPerformed(evt);
177 thumbnailSizeComboBox.addActionListener(
new java.awt.event.ActionListener() {
178 public void actionPerformed(java.awt.event.ActionEvent evt) {
179 thumbnailSizeComboBoxActionPerformed(evt);
183 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
184 this.setLayout(layout);
185 layout.setHorizontalGroup(
186 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
187 .addGroup(layout.createSequentialGroup()
188 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
189 .addGroup(layout.createSequentialGroup()
191 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
192 .addComponent(filePathLabel)
193 .addGroup(layout.createSequentialGroup()
194 .addComponent(pageLabel)
195 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
196 .addComponent(pageNumLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
197 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
198 .addComponent(pagesLabel)
199 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
200 .addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
202 .addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
203 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
204 .addComponent(goToPageLabel)
205 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
206 .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
208 .addComponent(imagesLabel)
209 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
210 .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
211 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
212 .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
213 .addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE))
216 layout.setVerticalGroup(
217 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
218 .addGroup(layout.createSequentialGroup()
219 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
220 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
221 .addComponent(pageLabel)
222 .addComponent(pagesLabel)
223 .addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
224 .addComponent(pageNumLabel))
225 .addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
226 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
227 .addComponent(imagesLabel)
228 .addComponent(imagesRangeLabel)
229 .addComponent(goToPageLabel)
230 .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
231 .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
232 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
233 .addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE)
234 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
235 .addComponent(filePathLabel))
239 private void pagePrevButtonActionPerformed(java.awt.event.ActionEvent evt) {
243 private void pageNextButtonActionPerformed(java.awt.event.ActionEvent evt) {
247 private void goToPageFieldActionPerformed(java.awt.event.ActionEvent evt) {
248 goToPage(goToPageField.getText());
251 private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
253 switch (thumbnailSizeComboBox.getSelectedIndex()) {
255 newIconSize = ImageUtils.ICON_SIZE_SMALL;
258 newIconSize = ImageUtils.ICON_SIZE_LARGE;
262 newIconSize = ImageUtils.ICON_SIZE_MEDIUM;
266 if (iconSize != newIconSize) {
267 iconSize = newIconSize;
268 Node root = em.getRootContext();
269 for (Children c : Arrays.asList(root.getChildren())) {
270 ((ThumbnailViewChildren) c).setIconSize(iconSize);
273 for (Node page : root.getChildren().getNodes()) {
274 for (Node node : page.getChildren().getNodes()) {
275 ((ThumbnailViewNode) node).setIconSize(iconSize);
284 em.setExploredContext(root);
290 private javax.swing.JLabel filePathLabel;
291 private javax.swing.JTextField goToPageField;
292 private javax.swing.JLabel goToPageLabel;
293 private org.openide.explorer.view.IconView iconView;
294 private javax.swing.JLabel imagesLabel;
295 private javax.swing.JLabel imagesRangeLabel;
296 private javax.swing.JLabel pageLabel;
297 private javax.swing.JButton pageNextButton;
298 private javax.swing.JLabel pageNumLabel;
299 private javax.swing.JButton pagePrevButton;
300 private javax.swing.JLabel pagesLabel;
301 private javax.swing.JComboBox<String> thumbnailSizeComboBox;
305 public boolean isSupported(Node selectedNode) {
306 if (selectedNode == null) {
313 public void setNode(Node givenNode) {
315 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
317 if (givenNode != null) {
318 ThumbnailViewChildren childNode =
new ThumbnailViewChildren(givenNode, iconSize);
320 final Node root =
new AbstractNode(childNode);
321 pageUpdater.setRoot(root);
322 root.addNodeListener(pageUpdater);
323 em.setRootContext(root);
325 Node emptyNode =
new AbstractNode(Children.LEAF);
326 em.setRootContext(emptyNode);
328 iconView.setBackground(Color.BLACK);
331 this.setCursor(null);
336 public String getTitle() {
337 return NbBundle.getMessage(this.getClass(),
"DataResultViewerThumbnail.title");
341 public DataResultViewer createInstance() {
342 return new DataResultViewerThumbnail();
346 public void resetComponent() {
347 super.resetComponent();
356 public void clearComponent() {
357 this.iconView.removeAll();
358 this.iconView = null;
360 super.clearComponent();
363 private void nextPage() {
364 if (curPage < totalPages) {
371 private void previousPage() {
379 private void goToPage(String pageNumText) {
382 newPage = Integer.parseInt(pageNumText);
383 }
catch (NumberFormatException e) {
388 if (newPage > totalPages || newPage < 1) {
389 JOptionPane.showMessageDialog(
this,
390 NbBundle.getMessage(
this.getClass(),
391 "DataResultViewerThumbnail.goToPageTextField.msgDlg",
393 NbBundle.getMessage(
this.getClass(),
394 "DataResultViewerThumbnail.goToPageTextField.err"),
395 JOptionPane.WARNING_MESSAGE);
403 private void switchPage() {
405 EventQueue.invokeLater(() -> {
406 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
410 new SwingWorker<Object, Void>() {
411 private ProgressHandle progress;
414 protected Object doInBackground() throws Exception {
415 pagePrevButton.setEnabled(
false);
416 pageNextButton.setEnabled(
false);
417 goToPageField.setEnabled(
false);
418 progress = ProgressHandle.createHandle(
419 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.genThumbs"));
421 progress.switchToIndeterminate();
422 Node root = em.getRootContext();
423 Node pageNode = root.getChildren().getNodeAt(curPage - 1);
424 em.setExploredContext(pageNode);
425 curPageImages = pageNode.getChildren().getNodesCount();
430 protected void done() {
437 }
catch (InterruptedException | ExecutionException ex) {
439 =
new NotifyDescriptor.Message(
440 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.switchPage.done.errMsg",
442 NotifyDescriptor.ERROR_MESSAGE);
443 DialogDisplayer.getDefault().notify(d);
444 logger.log(Level.SEVERE,
"Error making thumbnails: {0}", ex.getMessage());
446 catch (java.util.concurrent.CancellationException ex) {
453 private void updateControls() {
454 if (totalPages == 0) {
455 pagePrevButton.setEnabled(
false);
456 pageNextButton.setEnabled(
false);
457 goToPageField.setEnabled(
false);
458 pageNumLabel.setText(
"");
459 imagesRangeLabel.setText(
"");
460 thumbnailSizeComboBox.setEnabled(
false);
462 pageNumLabel.setText(
463 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.pageNumbers.curOfTotal",
464 Integer.toString(curPage), Integer.toString(totalPages)));
465 final int imagesFrom = (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
466 final int imagesTo = curPageImages + (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
467 imagesRangeLabel.setText(imagesFrom +
"-" + imagesTo);
469 pageNextButton.setEnabled(!(curPage == totalPages));
470 pagePrevButton.setEnabled(!(curPage == 1));
471 goToPageField.setEnabled(totalPages > 1);
472 thumbnailSizeComboBox.setEnabled(
true);
484 void setRoot(Node root) {
494 totalPages = root.getChildren().getNodesCount();
496 if (totalPages == 0) {
502 if (curPage == -1 || curPage > totalPages) {
507 final Node pageNode = root.getChildren().getNodeAt(curPage - 1);
510 if (pageNode != null) {
511 pageNode.addNodeListener(
new NodeListener() {
514 curPageImages = pageNode.getChildren().getNodesCount();
537 em.setExploredContext(pageNode);
564 if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
565 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
567 Node[] selectedNodes = em.getSelectedNodes();
568 if (selectedNodes.length == 1) {
571 filePathLabel.setText(
"");
575 filePathLabel.setText(uPath);
576 filePathLabel.setToolTipText(uPath);
578 logger.log(Level.WARNING,
"Could not get unique path for content: {0}", af.
getName());
582 filePathLabel.setText(
"");
void propertyChange(PropertyChangeEvent evt)
void nodeDestroyed(NodeEvent ne)
synchronized String getUniquePath()
void childrenAdded(NodeMemberEvent nme)
void childrenRemoved(NodeMemberEvent nme)
void propertyChange(PropertyChangeEvent evt)
void childrenReordered(NodeReorderEvent nre)