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;
31 import org.openide.util.NbBundle;
33 import javax.swing.ListSelectionModel;
34 import javax.swing.SwingWorker;
35 import org.netbeans.api.progress.ProgressHandle;
36 import org.netbeans.api.progress.ProgressHandleFactory;
37 import org.openide.DialogDisplayer;
38 import org.openide.NotifyDescriptor;
39 import org.openide.explorer.ExplorerManager;
40 import org.openide.explorer.view.IconView;
41 import org.openide.nodes.AbstractNode;
42 import org.openide.nodes.Children;
43 import org.openide.nodes.Node;
44 import org.openide.nodes.NodeEvent;
45 import org.openide.nodes.NodeListener;
46 import org.openide.nodes.NodeMemberEvent;
47 import org.openide.nodes.NodeReorderEvent;
48 import org.openide.util.Exceptions;
66 final class DataResultViewerThumbnail
extends AbstractDataResultViewer {
68 private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
71 private int totalPages;
72 private int curPageImages;
73 private int iconSize = ImageUtils.ICON_SIZE_MEDIUM;
74 private final PageUpdater pageUpdater =
new PageUpdater();
80 public DataResultViewerThumbnail(ExplorerManager explorerManager) {
81 super(explorerManager);
89 public DataResultViewerThumbnail() {
93 private void initialize() {
96 ((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
97 em.addPropertyChangeListener(
new ExplorerManagerNodeSelectionListener());
109 @SuppressWarnings(
"unchecked")
111 private
void initComponents() {
113 thumbnailScrollPanel =
new IconView();
114 pageLabel =
new javax.swing.JLabel();
115 pagesLabel =
new javax.swing.JLabel();
116 pagePrevButton =
new javax.swing.JButton();
117 pageNextButton =
new javax.swing.JButton();
118 imagesLabel =
new javax.swing.JLabel();
119 imagesRangeLabel =
new javax.swing.JLabel();
120 pageNumLabel =
new javax.swing.JLabel();
121 filePathLabel =
new javax.swing.JLabel();
122 goToPageLabel =
new javax.swing.JLabel();
123 goToPageField =
new javax.swing.JTextField();
124 thumbnailSizeComboBox =
new javax.swing.JComboBox<>();
126 thumbnailScrollPanel.setPreferredSize(
new java.awt.Dimension(582, 348));
128 pageLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageLabel.text"));
130 pagesLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pagesLabel.text"));
132 pagePrevButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
133 pagePrevButton.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pagePrevButton.text"));
134 pagePrevButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
135 pagePrevButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
136 pagePrevButton.setPreferredSize(
new java.awt.Dimension(55, 23));
137 pagePrevButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png")));
138 pagePrevButton.addActionListener(
new java.awt.event.ActionListener() {
139 public void actionPerformed(java.awt.event.ActionEvent evt) {
140 pagePrevButtonActionPerformed(evt);
144 pageNextButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
145 pageNextButton.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageNextButton.text"));
146 pageNextButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
147 pageNextButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
148 pageNextButton.setMaximumSize(
new java.awt.Dimension(27, 23));
149 pageNextButton.setMinimumSize(
new java.awt.Dimension(27, 23));
150 pageNextButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png")));
151 pageNextButton.addActionListener(
new java.awt.event.ActionListener() {
152 public void actionPerformed(java.awt.event.ActionEvent evt) {
153 pageNextButtonActionPerformed(evt);
157 imagesLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.imagesLabel.text"));
159 imagesRangeLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.imagesRangeLabel.text"));
161 pageNumLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.pageNumLabel.text"));
163 filePathLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.filePathLabel.text"));
165 goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.goToPageLabel.text"));
167 goToPageField.setText(
org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class,
"DataResultViewerThumbnail.goToPageField.text"));
168 goToPageField.addActionListener(
new java.awt.event.ActionListener() {
169 public void actionPerformed(java.awt.event.ActionEvent evt) {
170 goToPageFieldActionPerformed(evt);
174 thumbnailSizeComboBox.setModel(
new javax.swing.DefaultComboBoxModel<String>(
new String[] {
175 NbBundle.getMessage(this.getClass(),
"DataResultViewerThumbnail.comboBox.smallThumbnails"),
176 NbBundle.getMessage(this.getClass(),
"DataResultViewerThumbnail.comboBox.mediumThumbnails"),
177 NbBundle.getMessage(this.getClass(),
"DataResultViewerThumbnail.comboBox.largeThumbnails") }));
178 thumbnailSizeComboBox.addActionListener(
new java.awt.event.ActionListener() {
179 public void actionPerformed(java.awt.event.ActionEvent evt) {
180 thumbnailSizeComboBoxActionPerformed(evt);
184 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
185 this.setLayout(layout);
186 layout.setHorizontalGroup(
187 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
188 .addComponent(thumbnailScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 642, Short.MAX_VALUE)
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 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
215 layout.setVerticalGroup(
216 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
217 .addGroup(layout.createSequentialGroup()
218 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
219 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
220 .addComponent(pageLabel)
221 .addComponent(pagesLabel)
222 .addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
223 .addComponent(pageNumLabel))
224 .addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
225 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
226 .addComponent(imagesLabel)
227 .addComponent(imagesRangeLabel)
228 .addComponent(goToPageLabel)
229 .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
230 .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
232 .addComponent(thumbnailScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
233 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
234 .addComponent(filePathLabel))
238 private void pagePrevButtonActionPerformed(java.awt.event.ActionEvent evt) {
242 private void pageNextButtonActionPerformed(java.awt.event.ActionEvent evt) {
246 private void goToPageFieldActionPerformed(java.awt.event.ActionEvent evt) {
247 goToPage(goToPageField.getText());
250 private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
252 iconSize = ImageUtils.ICON_SIZE_MEDIUM;
253 switch(thumbnailSizeComboBox.getSelectedIndex()) {
255 iconSize = ImageUtils.ICON_SIZE_SMALL;
258 iconSize = ImageUtils.ICON_SIZE_LARGE;
262 Node root = em.getRootContext();
263 for (Children c : Arrays.asList(root.getChildren()) ) {
264 ((ThumbnailViewChildren)c).setIconSize(iconSize);
267 for (Node page : root.getChildren().getNodes()) {
268 for (Node node : page.getChildren().getNodes()) {
269 ((ThumbnailViewNode)node).setIconSize(iconSize);
278 em.setExploredContext(root);
283 private javax.swing.JLabel filePathLabel;
284 private javax.swing.JTextField goToPageField;
285 private javax.swing.JLabel goToPageLabel;
286 private javax.swing.JLabel imagesLabel;
287 private javax.swing.JLabel imagesRangeLabel;
288 private javax.swing.JLabel pageLabel;
289 private javax.swing.JButton pageNextButton;
290 private javax.swing.JLabel pageNumLabel;
291 private javax.swing.JButton pagePrevButton;
292 private javax.swing.JLabel pagesLabel;
293 private javax.swing.JScrollPane thumbnailScrollPanel;
294 private javax.swing.JComboBox<String> thumbnailSizeComboBox;
298 public boolean isSupported(Node selectedNode) {
299 if (selectedNode == null) {
306 public void setNode(Node givenNode) {
308 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
310 if (givenNode != null) {
311 ThumbnailViewChildren childNode =
new ThumbnailViewChildren(givenNode, iconSize);
313 final Node root =
new AbstractNode(childNode);
314 pageUpdater.setRoot(root);
315 root.addNodeListener(pageUpdater);
316 em.setRootContext(root);
318 Node emptyNode =
new AbstractNode(Children.LEAF);
319 em.setRootContext(emptyNode);
321 IconView iv = ((IconView) this.thumbnailScrollPanel);
322 iv.setBackground(Color.BLACK);
325 this.setCursor(null);
330 public String getTitle() {
331 return NbBundle.getMessage(this.getClass(),
"DataResultViewerThumbnail.title");
335 public DataResultViewer createInstance() {
336 return new DataResultViewerThumbnail();
340 public void resetComponent() {
341 super.resetComponent();
350 public void clearComponent() {
351 this.thumbnailScrollPanel.removeAll();
352 this.thumbnailScrollPanel = null;
354 super.clearComponent();
357 private void nextPage() {
358 if (curPage < totalPages) {
365 private void previousPage() {
373 private void goToPage(String pageNumText) {
376 newPage = Integer.parseInt(pageNumText);
378 catch (NumberFormatException e) {
383 if (newPage > totalPages || newPage < 1) {
384 JOptionPane.showMessageDialog(
this,
385 NbBundle.getMessage(
this.getClass(),
386 "DataResultViewerThumbnail.goToPageTextField.msgDlg",
388 NbBundle.getMessage(
this.getClass(),
389 "DataResultViewerThumbnail.goToPageTextField.err"),
390 JOptionPane.WARNING_MESSAGE);
398 private void switchPage() {
400 EventQueue.invokeLater(
new Runnable() {
403 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
408 new SwingWorker<Object, Void>() {
409 private ProgressHandle progress;
412 protected Object doInBackground() throws Exception {
413 pagePrevButton.setEnabled(
false);
414 pageNextButton.setEnabled(
false);
415 goToPageField.setEnabled(
false);
416 progress = ProgressHandleFactory.createHandle(
417 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.genThumbs"));
419 progress.switchToIndeterminate();
420 Node root = em.getRootContext();
421 Node pageNode = root.getChildren().getNodeAt(curPage - 1);
422 em.setExploredContext(pageNode);
423 curPageImages = pageNode.getChildren().getNodesCount();
428 protected void done() {
435 }
catch (InterruptedException | ExecutionException ex) {
437 new NotifyDescriptor.Message(
438 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.switchPage.done.errMsg",
440 NotifyDescriptor.ERROR_MESSAGE);
441 DialogDisplayer.getDefault().notify(d);
442 logger.log(Level.SEVERE,
"Error making thumbnails: " + ex.getMessage());
444 catch (java.util.concurrent.CancellationException ex) {
451 private void updateControls() {
452 if (totalPages == 0) {
453 pagePrevButton.setEnabled(
false);
454 pageNextButton.setEnabled(
false);
455 goToPageField.setEnabled(
false);
456 pageNumLabel.setText(
"");
457 imagesRangeLabel.setText(
"");
459 pageNumLabel.setText(
460 NbBundle.getMessage(
this.getClass(),
"DataResultViewerThumbnail.pageNumbers.curOfTotal",
461 Integer.toString(curPage), Integer.toString(totalPages)));
462 final int imagesFrom = (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
463 final int imagesTo = curPageImages + (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
464 imagesRangeLabel.setText(imagesFrom +
"-" + imagesTo);
466 pageNextButton.setEnabled(!(curPage == totalPages));
467 pagePrevButton.setEnabled(!(curPage == 1));
468 goToPageField.setEnabled(totalPages>1);
481 void setRoot(Node root) {
491 totalPages = root.getChildren().getNodesCount();
493 if (totalPages == 0) {
499 if (curPage == -1 || curPage > totalPages) {
504 final Node pageNode = root.getChildren().getNodeAt(curPage - 1);
507 if (pageNode != null) {
508 pageNode.addNodeListener(
new NodeListener() {
511 curPageImages = pageNode.getChildren().getNodesCount();
534 em.setExploredContext(pageNode);
561 if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
562 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
564 Node[] selectedNodes = em.getSelectedNodes();
565 if (selectedNodes.length == 1) {
568 filePathLabel.setText(
"");
573 filePathLabel.setText(uPath);
574 filePathLabel.setToolTipText(uPath);
577 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)