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

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