Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
TextContentViewerPanel.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2019-2021 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 */
19package org.sleuthkit.autopsy.contentviewers.textcontentviewer;
20
21import java.awt.Cursor;
22import java.beans.PropertyChangeEvent;
23import java.util.ArrayList;
24import java.util.Collection;
25import java.util.List;
26import java.util.logging.Level;
27import javax.swing.JTabbedPane;
28import javax.swing.event.ChangeEvent;
29import javax.swing.event.ChangeListener;
30import org.openide.nodes.Node;
31import org.openide.util.Lookup;
32import org.openide.util.NbBundle.Messages;
33import org.sleuthkit.autopsy.contentviewers.utils.ViewerPriority;
34import org.sleuthkit.autopsy.core.UserPreferences;
35import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
36import org.sleuthkit.autopsy.corecomponentinterfaces.TextViewer;
37import org.sleuthkit.datamodel.TskCoreException;
38import org.sleuthkit.autopsy.coreutils.Logger;
39import org.sleuthkit.datamodel.Content;
40
45public class TextContentViewerPanel extends javax.swing.JPanel implements DataContent, ChangeListener {
46
47 private static final Logger logger = Logger.getLogger(TextContentViewerPanel.class.getName());
48 private static final long serialVersionUID = 1L;
49 private final List<UpdateWrapper> textViewers = new ArrayList<>();
50 private Node currentNode;
51 private boolean listeningToTabbedPane = false;
52
56 public TextContentViewerPanel(boolean isMain) {
58 // add all implementors of DataContentViewer and put them in the tabbed pane
59 Collection<? extends TextViewer> dcvs = Lookup.getDefault().lookupAll(TextViewer.class);
60 for (TextViewer factory : dcvs) {
61 TextViewer dcv;
62 if (isMain) {
63 //use the instance from Lookup for the main viewer
64 dcv = factory;
65 } else {
66 dcv = factory.createInstance();
67 }
68 textViewers.add(new UpdateWrapper(dcv));
69 javax.swing.JScrollPane scrollTab = new javax.swing.JScrollPane(dcv.getComponent());
70 scrollTab.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_NEVER);
71 textViewerTabbedPane.addTab(dcv.getTitle(), null,
72 scrollTab, dcv.getToolTip());
73 }
74
75 // disable the tabs
76 int numTabs = textViewerTabbedPane.getTabCount();
77 for (int tab = 0; tab < numTabs; ++tab) {
78 textViewerTabbedPane.setEnabledAt(tab, false);
79 }
80 }
81
91 boolean isSupported(Node node) {
92 for (UpdateWrapper textViewer : textViewers) {
93 if (textViewer.isSupported(node)) {
94 return true;
95 }
96 }
97 return false;
98 }
99
109 int isPreffered(Node node) {
110 int max = ViewerPriority.viewerPriority.LevelOne.getFlag();
111 for (UpdateWrapper textViewer : textViewers) {
112 if (textViewer.isSupported(node)) {
113 max = Integer.max(max, textViewer.isPreferred(node));
114 }
115 }
116 return max;
117 }
118
119 @Messages({"TextContentViewerPanel.defaultName=Text"})
120 @Override
121 public void setNode(Node selectedNode) {
122 // change the cursor to "waiting cursor" for this operation
123 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
124 try {
125
126 String defaultName = Bundle.TextContentViewerPanel_defaultName();
127 // set the file path
128 if (selectedNode == null) {
129 setName(defaultName);
130 } else {
131 Content content = selectedNode.getLookup().lookup(Content.class);
132 if (content != null) {
133 String path = defaultName;
134 try {
135 path = content.getUniquePath();
136 } catch (TskCoreException ex) {
137 logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for " + content.toString(), ex); //NON-NLS
138 }
139 setName(path);
140 } else {
141 setName(defaultName);
142 }
143 }
144
145 currentNode = selectedNode;
146
147 setupTabs(selectedNode);
148 } finally {
149 this.setCursor(null);
150 }
151 }
152
159 public void setupTabs(Node selectedNode) {
160 // Deferring becoming a listener to the tabbed pane until this point
161 // eliminates handling a superfluous stateChanged event during construction.
162 if (listeningToTabbedPane == false) {
163 textViewerTabbedPane.addChangeListener(this);
165 }
166
167 int currTabIndex = textViewerTabbedPane.getSelectedIndex();
168 int totalTabs = textViewerTabbedPane.getTabCount();
169 int maxPreferred = 0;
170 int preferredViewerIndex = 0;
171 for (int i = 0; i < totalTabs; ++i) {
172 UpdateWrapper dcv = textViewers.get(i);
173 dcv.resetComponent();
174
175 // disable an unsupported tab (ex: picture viewer)
176 if ((selectedNode == null) || (dcv.isSupported(selectedNode) == false)) {
177 textViewerTabbedPane.setEnabledAt(i, false);
178 } else {
179 textViewerTabbedPane.setEnabledAt(i, true);
180
181 // remember the viewer with the highest preference value
182 int currentPreferred = dcv.isPreferred(selectedNode);
183 if (currentPreferred > maxPreferred) {
184 preferredViewerIndex = i;
185 maxPreferred = currentPreferred;
186 }
187 }
188 }
189
190 // let the user decide if we should stay with the current viewer
191 int tabIndex = UserPreferences.keepPreferredContentViewer() ? currTabIndex : preferredViewerIndex;
192
193 UpdateWrapper dcv = textViewers.get(tabIndex);
194 // this is really only needed if no tabs were enabled
195 if (textViewerTabbedPane.isEnabledAt(tabIndex) == false) {
196 dcv.resetComponent();
197 } else {
198 dcv.setNode(selectedNode);
199 }
200
201 // set the tab to the one the user wants, then set that viewer's node.
202 textViewerTabbedPane.setSelectedIndex(tabIndex);
203 textViewerTabbedPane.getSelectedComponent().repaint();
204 }
205
206 @Override
207 public void propertyChange(PropertyChangeEvent evt) {
208 //does nothing
209 }
210
211 @Override
212 public void stateChanged(ChangeEvent evt) {
213 JTabbedPane pane = (JTabbedPane) evt.getSource();
214
215 // Get and set current selected tab
216 int currentTab = pane.getSelectedIndex();
217 if (currentTab != -1 && pane.isEnabledAt(currentTab)) {
218 UpdateWrapper dcv = textViewers.get(currentTab);
219 if (dcv.isOutdated()) {
220 // change the cursor to "waiting cursor" for this operation
221 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
222 try {
223 dcv.setNode(currentNode);
224 } finally {
225 this.setCursor(null);
226 }
227 }
228 }
229 }
230
236 @SuppressWarnings("unchecked")
237 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
238 private void initComponents() {
239
240 textViewerTabbedPane = new javax.swing.JTabbedPane();
241
242 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
243 this.setLayout(layout);
244 layout.setHorizontalGroup(
245 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
246 .addGap(0, 50, Short.MAX_VALUE)
247 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
248 .addComponent(textViewerTabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE))
249 );
250 layout.setVerticalGroup(
251 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
252 .addGap(0, 27, Short.MAX_VALUE)
253 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
254 .addComponent(textViewerTabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE))
255 );
256 }// </editor-fold>//GEN-END:initComponents
257
258
259 // Variables declaration - do not modify//GEN-BEGIN:variables
260 private javax.swing.JTabbedPane textViewerTabbedPane;
261 // End of variables declaration//GEN-END:variables
262
266 private static class UpdateWrapper {
267
268 private final TextViewer wrapped;
269 private boolean outdated;
270
271 UpdateWrapper(TextViewer wrapped) {
272 this.wrapped = wrapped;
273 this.outdated = true;
274 }
275
276 void setNode(Node selectedNode) {
277 this.wrapped.setNode(selectedNode);
278 this.outdated = false;
279 }
280
281 void resetComponent() {
282 this.wrapped.resetComponent();
283 this.outdated = true;
284 }
285
286 boolean isOutdated() {
287 return this.outdated;
288 }
289
290 boolean isSupported(Node node) {
291 return this.wrapped.isSupported(node);
292 }
293
294 int isPreferred(Node node) {
295 return this.wrapped.isPreferred(node);
296 }
297 }
298}
synchronized static Logger getLogger(String name)
Definition Logger.java:124

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.