19 package org.sleuthkit.autopsy.discovery.ui;
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);
61 private void addThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
62 imagePanel.removeAll();
63 GridBagConstraints gridBagConstraints =
new GridBagConstraints();
64 gridBagConstraints.gridx = 0;
65 gridBagConstraints.gridy = 0;
66 gridBagConstraints.anchor = GridBagConstraints.LINE_START;
67 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);
68 gridBagConstraints.gridy = 1;
69 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);
70 gridBagConstraints.gridx++;
72 int[] timeStamps = thumbnailWrapper.getTimeStamps();
73 for (Image image : thumbnailWrapper.getThumbnails()) {
74 gridBagConstraints.gridy = 0;
75 imagePanel.add(
new JLabel(
new ImageIcon(image)), gridBagConstraints);
77 gridBagConstraints.gridy = 1;
78 long millis = timeStamps[timeIndex];
79 long hours = TimeUnit.MILLISECONDS.toHours(millis);
80 millis -= TimeUnit.HOURS.toMillis(hours);
81 long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
82 millis -= TimeUnit.MINUTES.toMillis(minutes);
83 long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
84 imagePanel.add(
new JLabel(String.format(
"%01d:%02d:%02d", hours, minutes, seconds)), gridBagConstraints);
85 gridBagConstraints.gridx++;
86 gridBagConstraints.gridy = 0;
87 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);
88 gridBagConstraints.gridy = 1;
89 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);
90 gridBagConstraints.gridx++;
100 @SuppressWarnings(
"unchecked")
102 private
void initComponents() {
104 imagePanel =
new javax.swing.JPanel();
105 fileSizeLabel =
new javax.swing.JLabel();
106 nameLabel =
new javax.swing.JLabel();
107 scoreLabel =
new javax.swing.JLabel();
108 deletedLabel =
new javax.swing.JLabel();
110 setBorder(javax.swing.BorderFactory.createEtchedBorder());
112 imagePanel.setPreferredSize(
new java.awt.Dimension(776, 115));
113 imagePanel.setLayout(
new java.awt.GridBagLayout());
115 scoreLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/red-circle-exclamation.png")));
120 deletedLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/file-icon-deleted.png")));
125 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
126 this.setLayout(layout);
127 layout.setHorizontalGroup(
128 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
129 .addGroup(layout.createSequentialGroup()
131 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
132 .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
133 .addGroup(layout.createSequentialGroup()
134 .addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
135 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
136 .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
137 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
138 .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
139 .addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
142 layout.setVerticalGroup(
143 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
144 .addGroup(layout.createSequentialGroup()
146 .addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
147 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
148 .addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
149 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
150 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
151 .addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
152 .addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
153 .addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
160 private javax.swing.JLabel deletedLabel;
161 private javax.swing.JLabel fileSizeLabel;
162 private javax.swing.JPanel imagePanel;
163 private javax.swing.JLabel nameLabel;
164 private javax.swing.JLabel scoreLabel;
168 "# {0} - otherInstanceCount",
169 "VideoThumbnailPanel.nameLabel.more.text= and {0} more",
170 "VideoThumbnailPanel.deleted.text=All instances of file are deleted."})
172 public Component getListCellRendererComponent(JList<? extends VideoThumbnailsWrapper> list, VideoThumbnailsWrapper value,
int index,
boolean isSelected,
boolean cellHasFocus) {
173 fileSizeLabel.setText(getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
174 String nameText = value.getResultFile().getFirstInstance().getParentPath() + value.getResultFile().getFirstInstance().getName();
175 if (value.getResultFile().getAllInstances().size() > 1) {
176 nameText += Bundle.VideoThumbnailPanel_nameLabel_more_text(value.getResultFile().getAllInstances().size() - 1);
178 if (nameText.length() > MAX_NAME_STRING) {
179 nameText =
"..." + nameText.substring(nameText.length() - (MAX_NAME_STRING - 3));
181 nameLabel.setText(nameText);
182 addThumbnails(value);
183 imagePanel.setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
184 DiscoveryUiUtils.setDeletedIcon(value.getResultFile().isDeleted(), deletedLabel);
185 DiscoveryUiUtils.setScoreIcon(value.getResultFile(), scoreLabel);
186 setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
190 @Messages({
"# {0} - fileSize",
192 "VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}",
193 "VideoThumbnailPanel.bytes.text=bytes",
194 "VideoThumbnailPanel.kiloBytes.text=KB",
195 "VideoThumbnailPanel.megaBytes.text=MB",
196 "VideoThumbnailPanel.gigaBytes.text=GB",
197 "VideoThumbnailPanel.terraBytes.text=TB"})
206 private String getFileSizeString(
long bytes) {
208 int unitsSwitchValue = 0;
209 while (size > BYTE_UNIT_CONVERSION && unitsSwitchValue < 4) {
210 size /= BYTE_UNIT_CONVERSION;
214 switch (unitsSwitchValue) {
216 units = Bundle.VideoThumbnailPanel_kiloBytes_text();
219 units = Bundle.VideoThumbnailPanel_megaBytes_text();
222 units = Bundle.VideoThumbnailPanel_gigaBytes_text();
225 units = Bundle.VideoThumbnailPanel_terraBytes_text();
228 units = Bundle.VideoThumbnailPanel_bytes_text();
231 return Bundle.VideoThumbnailPanel_sizeLabel_text(size, units);
235 public String getToolTipText(MouseEvent event) {
238 Point point =
event.getPoint();
239 for (Component comp : getComponents()) {
240 if (DiscoveryUiUtils.isPointOnIcon(comp, point)) {
241 String toolTip = ((JComponent) comp).getToolTipText();
242 if (toolTip == null || toolTip.isEmpty()) {