19 package org.sleuthkit.autopsy.filequery;
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.NbBundle.Messages;
39 final class VideoThumbnailPanel
extends javax.swing.JPanel implements ListCellRenderer<VideoThumbnailsWrapper> {
41 private static final int GAP_SIZE = 4;
42 private static final Color SELECTION_COLOR =
new Color(0, 120, 215);
43 private static final int BYTE_UNIT_CONVERSION = 1000;
44 private static final long serialVersionUID = 1L;
45 private static final int MAX_NAME_STRING = 120;
50 VideoThumbnailPanel() {
52 this.setFocusable(
true);
60 private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
61 imagePanel.removeAll();
62 GridBagConstraints gridBagConstraints =
new GridBagConstraints();
63 gridBagConstraints.gridx = 0;
64 gridBagConstraints.gridy = 0;
65 gridBagConstraints.anchor = GridBagConstraints.LINE_START;
66 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);
67 gridBagConstraints.gridy = 1;
68 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);
69 gridBagConstraints.gridx++;
71 int[] timeStamps = thumbnailWrapper.getTimeStamps();
72 for (Image image : thumbnailWrapper.getThumbnails()) {
73 gridBagConstraints.gridy = 0;
74 imagePanel.add(
new JLabel(
new ImageIcon(image)), gridBagConstraints);
76 gridBagConstraints.gridy = 1;
77 long millis = timeStamps[timeIndex];
78 long hours = TimeUnit.MILLISECONDS.toHours(millis);
79 millis -= TimeUnit.HOURS.toMillis(hours);
80 long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
81 millis -= TimeUnit.MINUTES.toMillis(minutes);
82 long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
83 imagePanel.add(
new JLabel(String.format(
"%01d:%02d:%02d", hours, minutes, seconds)), gridBagConstraints);
84 gridBagConstraints.gridx++;
85 gridBagConstraints.gridy = 0;
86 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);
87 gridBagConstraints.gridy = 1;
88 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);
89 gridBagConstraints.gridx++;
99 @SuppressWarnings(
"unchecked")
101 private
void initComponents() {
103 imagePanel =
new javax.swing.JPanel();
104 fileSizeLabel =
new javax.swing.JLabel();
105 nameLabel =
new javax.swing.JLabel();
106 scoreLabel =
new javax.swing.JLabel();
107 deletedLabel =
new javax.swing.JLabel();
109 setBorder(javax.swing.BorderFactory.createEtchedBorder());
111 imagePanel.setPreferredSize(
new java.awt.Dimension(776, 115));
112 imagePanel.setLayout(
new java.awt.GridBagLayout());
114 scoreLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/red-circle-exclamation.png")));
119 deletedLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/file-icon-deleted.png")));
124 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
125 this.setLayout(layout);
126 layout.setHorizontalGroup(
127 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
128 .addGroup(layout.createSequentialGroup()
130 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
131 .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
132 .addGroup(layout.createSequentialGroup()
133 .addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
134 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
135 .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
136 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
137 .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
138 .addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
141 layout.setVerticalGroup(
142 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
143 .addGroup(layout.createSequentialGroup()
145 .addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
146 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
147 .addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
148 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
149 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
150 .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
151 .addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
152 .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
159 private javax.swing.JLabel deletedLabel;
160 private javax.swing.JLabel fileSizeLabel;
161 private javax.swing.JPanel imagePanel;
162 private javax.swing.JLabel nameLabel;
163 private javax.swing.JLabel scoreLabel;
167 "# {0} - otherInstanceCount",
168 "VideoThumbnailPanel.nameLabel.more.text= and {0} more",
169 "VideoThumbnailPanel.deleted.text=All instances of file are deleted."})
171 public Component getListCellRendererComponent(JList<? extends VideoThumbnailsWrapper> list, VideoThumbnailsWrapper value,
int index,
boolean isSelected,
boolean cellHasFocus) {
172 fileSizeLabel.setText(getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
173 String nameText = value.getResultFile().getFirstInstance().getParentPath() + value.getResultFile().getFirstInstance().getName();
174 if (value.getResultFile().getAllInstances().size() > 1) {
175 nameText += Bundle.VideoThumbnailPanel_nameLabel_more_text(value.getResultFile().getAllInstances().size() - 1);
177 if (nameText.length() > MAX_NAME_STRING) {
178 nameText =
"..." + nameText.substring(nameText.length() - (MAX_NAME_STRING - 3));
180 nameLabel.setText(nameText);
181 addThumbnails(value);
182 imagePanel.setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
183 DiscoveryUiUtils.setDeletedIcon(value.getResultFile().isDeleted(), deletedLabel);
184 DiscoveryUiUtils.setScoreIcon(value.getResultFile(), scoreLabel);
185 setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
189 @Messages({
"# {0} - fileSize",
191 "VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}",
192 "VideoThumbnailPanel.bytes.text=bytes",
193 "VideoThumbnailPanel.kiloBytes.text=KB",
194 "VideoThumbnailPanel.megaBytes.text=MB",
195 "VideoThumbnailPanel.gigaBytes.text=GB",
196 "VideoThumbnailPanel.terraBytes.text=TB"})
205 private String getFileSizeString(
long bytes) {
207 int unitsSwitchValue = 0;
208 while (size > BYTE_UNIT_CONVERSION && unitsSwitchValue < 4) {
209 size /= BYTE_UNIT_CONVERSION;
213 switch (unitsSwitchValue) {
215 units = Bundle.VideoThumbnailPanel_kiloBytes_text();
218 units = Bundle.VideoThumbnailPanel_megaBytes_text();
221 units = Bundle.VideoThumbnailPanel_gigaBytes_text();
224 units = Bundle.VideoThumbnailPanel_terraBytes_text();
227 units = Bundle.VideoThumbnailPanel_bytes_text();
230 return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units);
234 public String getToolTipText(MouseEvent event) {
237 Point point =
event.getPoint();
238 for (Component comp : getComponents()) {
239 if (DiscoveryUiUtils.isPointOnIcon(comp, point)) {
240 String toolTip = ((JComponent) comp).getToolTipText();
241 if (toolTip == null || toolTip.isEmpty()) {