Autopsy  4.20.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-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  */
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;
37 import org.sleuthkit.datamodel.TskCoreException;
39 import org.sleuthkit.datamodel.Content;
40 
45 public 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);
164  listeningToTabbedPane = true;
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-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.