Autopsy  4.13.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
VideoThumbnailPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy
3  *
4  * Copyright 2019 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.filequery;
20 
21 import java.awt.Color;
22 import java.awt.Component;
23 import java.awt.Dimension;
24 import java.awt.Image;
25 import java.awt.GridBagConstraints;
26 import java.awt.Point;
27 import java.awt.event.MouseEvent;
28 import java.util.concurrent.TimeUnit;
29 import javax.swing.ImageIcon;
30 import javax.swing.JComponent;
31 import javax.swing.JLabel;
32 import javax.swing.JList;
33 import javax.swing.ListCellRenderer;
34 import org.openide.util.ImageUtilities;
35 import org.openide.util.NbBundle.Messages;
36 
40 final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRenderer<VideoThumbnailsWrapper> {
41 
42  private static final int GAP_SIZE = 4;
43  private static final Color SELECTION_COLOR = new Color(0, 120, 215);
44  private static final int BYTE_UNIT_CONVERSION = 1000;
45  private static final int ICON_SIZE = 16;
46  private static final String RED_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/red-circle-exclamation.png";
47  private static final String YELLOW_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/yellow-circle-yield.png";
48  private static final String DELETE_ICON_PATH = "/org/sleuthkit/autopsy/images/file-icon-deleted.png";
49  private static final ImageIcon INTERESTING_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(YELLOW_CIRCLE_ICON_PATH, false));
50  private static final ImageIcon NOTABLE_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(RED_CIRCLE_ICON_PATH, false));
51  private static final ImageIcon DELETED_ICON = new ImageIcon(ImageUtilities.loadImage(DELETE_ICON_PATH, false));
52  private static final long serialVersionUID = 1L;
53 
57  VideoThumbnailPanel() {
58  initComponents();
59  this.setFocusable(true);
60  }
61 
67  private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
68  imagePanel.removeAll();
69  GridBagConstraints gridBagConstraints = new GridBagConstraints();
70  gridBagConstraints.gridx = 0;
71  gridBagConstraints.gridy = 0;
72  gridBagConstraints.anchor = GridBagConstraints.LINE_START;
73  imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
74  gridBagConstraints.gridy = 1;
75  imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
76  gridBagConstraints.gridx++;
77  int timeIndex = 0;
78  int[] timeStamps = thumbnailWrapper.getTimeStamps();
79  for (Image image : thumbnailWrapper.getThumbnails()) {
80  gridBagConstraints.gridy = 0;
81  imagePanel.add(new JLabel(new ImageIcon(image)), gridBagConstraints);
82  gridBagConstraints.gridy = 1;
83  long millis = timeStamps[timeIndex];
84  long hours = TimeUnit.MILLISECONDS.toHours(millis);
85  millis -= TimeUnit.HOURS.toMillis(hours);
86  long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
87  millis -= TimeUnit.MINUTES.toMillis(minutes);
88  long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
89  imagePanel.add(new JLabel(String.format("%01d:%02d:%02d", hours, minutes, seconds)), gridBagConstraints);
90  gridBagConstraints.gridx++;
91  gridBagConstraints.gridy = 0;
92  imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
93  gridBagConstraints.gridy = 1;
94  imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
95  gridBagConstraints.gridx++;
96  timeIndex++;
97  }
98  }
99 
105  @SuppressWarnings("unchecked")
106  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
107  private void initComponents() {
108 
109  imagePanel = new javax.swing.JPanel();
110  fileSizeLabel = new javax.swing.JLabel();
111  countLabel = new javax.swing.JLabel();
112  scoreLabel = new javax.swing.JLabel();
113  deletedLabel = new javax.swing.JLabel();
114 
115  setBorder(javax.swing.BorderFactory.createEtchedBorder());
116 
117  imagePanel.setLayout(new java.awt.GridBagLayout());
118 
119  scoreLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/red-circle-exclamation.png"))); // NOI18N
120  scoreLabel.setMaximumSize(new Dimension(ICON_SIZE,ICON_SIZE));
121  scoreLabel.setMinimumSize(new Dimension(ICON_SIZE,ICON_SIZE));
122  scoreLabel.setPreferredSize(new Dimension(ICON_SIZE,ICON_SIZE));
123 
124  deletedLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/file-icon-deleted.png"))); // NOI18N
125  deletedLabel.setMaximumSize(new Dimension(ICON_SIZE,ICON_SIZE));
126  deletedLabel.setMinimumSize(new Dimension(ICON_SIZE,ICON_SIZE));
127  deletedLabel.setPreferredSize(new Dimension(ICON_SIZE,ICON_SIZE));
128 
129  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
130  this.setLayout(layout);
131  layout.setHorizontalGroup(
132  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
133  .addGroup(layout.createSequentialGroup()
134  .addContainerGap()
135  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
136  .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 776, Short.MAX_VALUE)
137  .addGroup(layout.createSequentialGroup()
138  .addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 248, javax.swing.GroupLayout.PREFERRED_SIZE)
139  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
140  .addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
141  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
142  .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
143  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
144  .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
145  .addContainerGap())
146  );
147  layout.setVerticalGroup(
148  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
149  .addGroup(layout.createSequentialGroup()
150  .addContainerGap()
151  .addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
152  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
153  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
154  .addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
155  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
156  .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
157  .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
158  .addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)))
159  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
160  );
161  }// </editor-fold>//GEN-END:initComponents
162 
163 
164  // Variables declaration - do not modify//GEN-BEGIN:variables
165  private javax.swing.JLabel countLabel;
166  private javax.swing.JLabel deletedLabel;
167  private javax.swing.JLabel fileSizeLabel;
168  private javax.swing.JPanel imagePanel;
169  private javax.swing.JLabel scoreLabel;
170  // End of variables declaration//GEN-END:variables
171 
172  @Messages({
173  "# {0} - numberOfInstances",
174  "VideoThumbnailPanel.countLabel.text=Number of Instances: {0}",
175  "VideoThumbnailPanel.deleted.text=All instances of file are deleted."})
176  @Override
177  public Component getListCellRendererComponent(JList<? extends VideoThumbnailsWrapper> list, VideoThumbnailsWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
178  fileSizeLabel.setText(getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
179  countLabel.setText(Bundle.VideoThumbnailPanel_countLabel_text(value.getResultFile().getAllInstances().size()));
180  addThumbnails(value);
181  imagePanel.setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
182  if (value.getResultFile().isDeleted()) {
183  deletedLabel.setIcon(DELETED_ICON);
184  deletedLabel.setToolTipText(Bundle.VideoThumbnailPanel_deleted_text());
185  } else {
186  deletedLabel.setIcon(null);
187  deletedLabel.setToolTipText("");
188  }
189  switch (value.getResultFile().getScore()) {
190  case NOTABLE_SCORE:
191  scoreLabel.setIcon(NOTABLE_SCORE_ICON);
192  break;
193  case INTERESTING_SCORE:
194  scoreLabel.setIcon(INTERESTING_SCORE_ICON);
195  break;
196  case NO_SCORE: // empty case - this is interpreted as an intentional fall-through
197  default:
198  scoreLabel.setIcon(null);
199  break;
200  }
201  scoreLabel.setToolTipText(value.getResultFile().getScoreDescription());
202  setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
203  return this;
204  }
205 
206  @Messages({"# {0} - fileSize",
207  "# {1} - units",
208  "VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}",
209  "VideoThumbnailPanel.bytes.text=bytes",
210  "VideoThumbnailPanel.kiloBytes.text=KB",
211  "VideoThumbnailPanel.megaBytes.text=MB",
212  "VideoThumbnailPanel.gigaBytes.text=GB",
213  "VideoThumbnailPanel.terraBytes.text=TB"})
222  private String getFileSizeString(long bytes) {
223  long size = bytes;
224  int unitsSwitchValue = 0;
225  while (size > BYTE_UNIT_CONVERSION && unitsSwitchValue < 4) {
226  size /= BYTE_UNIT_CONVERSION;
227  unitsSwitchValue++;
228  }
229  String units;
230  switch (unitsSwitchValue) {
231  case 1:
232  units = Bundle.VideoThumbnailPanel_kiloBytes_text();
233  break;
234  case 2:
235  units = Bundle.VideoThumbnailPanel_megaBytes_text();
236  break;
237  case 3:
238  units = Bundle.VideoThumbnailPanel_gigaBytes_text();
239  break;
240  case 4:
241  units = Bundle.VideoThumbnailPanel_terraBytes_text();
242  break;
243  default:
244  units = Bundle.VideoThumbnailPanel_bytes_text();
245  break;
246  }
247  return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units);
248  }
249 
250  @Override
251  public String getToolTipText(MouseEvent event) {
252  if (event != null) {
253  //gets tooltip of internal panel item mouse is over
254  Point point = event.getPoint();
255  for (Component comp : getComponents()) {
256  if (isPointOnIcon(comp, point)) {
257  String toolTip = ((JComponent) comp).getToolTipText();
258  if (toolTip == null || toolTip.isEmpty()) {
259  return null;
260  } else {
261  return toolTip;
262  }
263  }
264  }
265  }
266  return null;
267  }
268 
277  private boolean isPointOnIcon(Component comp, Point point) {
278  return comp instanceof JComponent && point.x >= comp.getX() && point.x <= comp.getX() + ICON_SIZE && point.y >= comp.getY() && point.y <= comp.getY() + ICON_SIZE;
279  }
280 }

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.