Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractedContentPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2020 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.keywordsearch;
20 
21 import java.awt.ComponentOrientation;
22 import java.awt.EventQueue;
23 import java.awt.Font;
24 import java.awt.event.ActionListener;
25 import java.awt.event.ItemEvent;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.concurrent.CancellationException;
30 import java.util.concurrent.ExecutionException;
31 import java.util.logging.Level;
32 import javax.swing.JLabel;
33 import javax.swing.SizeRequirements;
34 import javax.swing.SwingUtilities;
35 import javax.swing.SwingWorker;
36 import javax.swing.text.Element;
37 import javax.swing.text.View;
38 import javax.swing.text.ViewFactory;
39 import javax.swing.text.html.HTMLEditorKit;
40 import javax.swing.text.html.HTMLEditorKit.HTMLFactory;
41 import javax.swing.text.html.InlineView;
42 import javax.swing.text.html.ParagraphView;
43 import javax.swing.text.html.StyleSheet;
44 import org.apache.commons.lang3.StringUtils;
45 import org.netbeans.api.progress.ProgressHandle;
46 import org.openide.util.NbBundle;
51 
56 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
57 class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextPanel {
58 
59  private static final Logger logger = Logger.getLogger(ExtractedContentPanel.class.getName());
60 
61  // set font as close as possible to default
62  private static final Font DEFAULT_FONT = new JLabel().getFont();
63 
64  private static final long serialVersionUID = 1L;
65  private String contentName;
66  private int curSize;
67 
68  private final StyleSheet styleSheet;
69  private final HTMLEditorKit editorKit;
70  private String lastKnownAnchor = null;
71 
72  ExtractedContentPanel() {
73  initComponents();
74  additionalInit();
75  setSources("", new ArrayList<>());
76  hitPreviousButton.setEnabled(false);
77  hitNextButton.setEnabled(false);
78 
79  /*
80  * This appears to be an attempt to modify the wrapping behavior of the
81  * extractedTextPane taken form this website:
82  * http://java-sl.com/tip_html_letter_wrap.html.
83  */
84  editorKit = new HTMLEditorKit() {
85  private static final long serialVersionUID = 1L;
86 
87  @Override
88  public ViewFactory getViewFactory() {
89 
90  return new HTMLFactory() {
91  @Override
92  public View create(Element e) {
93  View v = super.create(e);
94  if (v instanceof InlineView) {
95  return new InlineView(e) {
96  @Override
97  public int getBreakWeight(int axis, float pos, float len) {
98  return GoodBreakWeight;
99  }
100 
101  @Override
102  public View breakView(int axis, int p0, float pos, float len) {
103  if (axis == View.X_AXIS) {
104  checkPainter();
105  int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
106  if (p0 == getStartOffset() && p1 == getEndOffset()) {
107  return this;
108  }
109  return createFragment(p0, p1);
110  }
111  return this;
112  }
113  };
114  } else if (v instanceof ParagraphView) {
115  return new ParagraphView(e) {
116  @Override
117  protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
118  SizeRequirements requirements = r;
119  if (requirements == null) {
120  requirements = new SizeRequirements();
121  }
122  float pref = layoutPool.getPreferredSpan(axis);
123  float min = layoutPool.getMinimumSpan(axis);
124  // Don't include insets, Box.getXXXSpan will include them.
125  requirements.minimum = (int) min;
126  requirements.preferred = Math.max(requirements.minimum, (int) pref);
127  requirements.maximum = Integer.MAX_VALUE;
128  requirements.alignment = 0.5f;
129  return requirements;
130  }
131  };
132  }
133  return v;
134  }
135  };
136  }
137  };
138  // get the style sheet for editing font size
139  styleSheet = editorKit.getStyleSheet();
140 
141  sourceComboBox.addItemListener(itemEvent -> {
142  if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
143  refreshCurrentMarkup();
144  }
145  });
146  extractedTextPane.setComponentPopupMenu(rightClickMenu);
147  copyMenuItem.addActionListener(actionEvent -> extractedTextPane.copy());
148  selectAllMenuItem.addActionListener(actionEvent -> extractedTextPane.selectAll());
149 
150  // TextZoomPanel could not be directly instantiated in Swing WYSIWYG editor
151  // (because it was package private, couldn't use constructor, etc.)
152  // so it was identified as a JPanel for the WYSIWYG. This function is called for
153  // initial setup so the font size of this panel as well as the font size indicated
154  // in the TextZoomPanel are correct
155  SwingUtilities.invokeLater(() -> {
156  if (zoomPanel instanceof TextZoomPanel)
157  ((TextZoomPanel) this.zoomPanel).resetSize();
158  });
159  }
160 
161 
162  private void setStyleSheetSize(StyleSheet styleSheet, int size) {
163  styleSheet.addRule("body {font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } ");
164  }
165 
166 
167  @Override
168  public int getTextSize() {
169  return curSize;
170  }
171 
172  @Override
173  public void setTextSize(int newSize) {
174  curSize = newSize;
175 
176  String curText = extractedTextPane.getText();
177 
178  setStyleSheetSize(styleSheet, curSize);
179 
180  editorKit.setStyleSheet(styleSheet);
181  extractedTextPane.setEditorKit(editorKit);
182 
183  extractedTextPane.setText(curText);
184  if (lastKnownAnchor != null)
185  scrollToAnchor(lastKnownAnchor);
186  }
187 
188 
189  private void additionalInit() {
190  // use wrap layout for better component wrapping
191  WrapLayout layout = new WrapLayout(0,5);
192  layout.setOppositeAligned(Arrays.asList(textSourcePanel));
193  controlPanel.setLayout(layout);
194  }
195 
196 
202  @SuppressWarnings("unchecked")
203  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
204  private void initComponents() {
205 
206  rightClickMenu = new javax.swing.JPopupMenu();
207  copyMenuItem = new javax.swing.JMenuItem();
208  selectAllMenuItem = new javax.swing.JMenuItem();
209  controlPanel = new javax.swing.JPanel();
210  javax.swing.JPanel pagePanel = new javax.swing.JPanel();
211  pagesLabel = new javax.swing.JLabel();
212  javax.swing.Box.Filler fillerSmall1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
213  pageCurLabel = new javax.swing.JLabel();
214  javax.swing.Box.Filler fillerSmall2 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
215  pageOfLabel = new javax.swing.JLabel();
216  javax.swing.Box.Filler fillerSmall3 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
217  pageTotalLabel = new javax.swing.JLabel();
218  javax.swing.Box.Filler fillerSmall4 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
219  pageButtonsLabel = new javax.swing.JLabel();
220  javax.swing.Box.Filler fillerMed1 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
221  pagePreviousButton = new javax.swing.JButton();
222  pageNextButton = new javax.swing.JButton();
223  javax.swing.Box.Filler fillerSmall6 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
224  jSeparator2 = new javax.swing.JSeparator();
225  javax.swing.JPanel matchesPanel = new javax.swing.JPanel();
226  hitLabel = new javax.swing.JLabel();
227  hitCountLabel = new javax.swing.JLabel();
228  hitOfLabel = new javax.swing.JLabel();
229  hitTotalLabel = new javax.swing.JLabel();
230  hitButtonsLabel = new javax.swing.JLabel();
231  javax.swing.Box.Filler fillerMed2 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
232  hitPreviousButton = new javax.swing.JButton();
233  hitNextButton = new javax.swing.JButton();
234  javax.swing.Box.Filler fillerSmall11 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
235  jSeparator3 = new javax.swing.JSeparator();
236  javax.swing.JPanel zoomPanelWrapper = new javax.swing.JPanel();
237  zoomPanel = new TextZoomPanel(this);
238  javax.swing.Box.Filler fillerSmall14 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
239  jSeparator4 = new javax.swing.JSeparator();
240  textSourcePanel = new javax.swing.JPanel();
241  jLabel1 = new javax.swing.JLabel();
242  javax.swing.Box.Filler fillerSmall12 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
243  sourceComboBox = new javax.swing.JComboBox<>();
244  extractedScrollPane = new javax.swing.JScrollPane();
245  extractedTextPane = new javax.swing.JTextPane();
246 
247  copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.copyMenuItem.text")); // NOI18N
248  rightClickMenu.add(copyMenuItem);
249 
250  selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N
251  rightClickMenu.add(selectAllMenuItem);
252 
253  setMinimumSize(new java.awt.Dimension(250, 0));
254  setPreferredSize(new java.awt.Dimension(250, 58));
255  setLayout(new java.awt.BorderLayout());
256 
257  controlPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
258 
259  pagePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
260 
261  pagesLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagesLabel.text")); // NOI18N
262  pagePanel.add(pagesLabel);
263  pagePanel.add(fillerSmall1);
264 
265  pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
266  pageCurLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageCurLabel.text")); // NOI18N
267  pagePanel.add(pageCurLabel);
268  pagePanel.add(fillerSmall2);
269 
270  pageOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageOfLabel.text")); // NOI18N
271  pagePanel.add(pageOfLabel);
272  pagePanel.add(fillerSmall3);
273 
274  pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
275  pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
276  pagePanel.add(pageTotalLabel);
277  pagePanel.add(fillerSmall4);
278 
279  pageButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageButtonsLabel.text")); // NOI18N
280  pagePanel.add(pageButtonsLabel);
281  pagePanel.add(fillerMed1);
282 
283  pagePreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
284  pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
285  pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
286  pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
287  pagePreviousButton.setBorderPainted(false);
288  pagePreviousButton.setContentAreaFilled(false);
289  pagePreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
290  pagePreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
291  pagePanel.add(pagePreviousButton);
292 
293  pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
294  pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageNextButton.text")); // NOI18N
295  pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
296  pageNextButton.setBorderPainted(false);
297  pageNextButton.setContentAreaFilled(false);
298  pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
299  pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
300  pageNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
301  pagePanel.add(pageNextButton);
302  pagePanel.add(fillerSmall6);
303 
304  jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
305  jSeparator2.setMaximumSize(new java.awt.Dimension(2, 25));
306  jSeparator2.setMinimumSize(new java.awt.Dimension(2, 25));
307  jSeparator2.setPreferredSize(new java.awt.Dimension(2, 25));
308  pagePanel.add(jSeparator2);
309 
310  controlPanel.add(pagePanel);
311 
312  matchesPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
313 
314  hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.text")); // NOI18N
315  hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
316  matchesPanel.add(hitLabel);
317 
318  hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
319  hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitCountLabel.text")); // NOI18N
320  hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14));
321  hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14));
322  hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14));
323  matchesPanel.add(hitCountLabel);
324 
325  hitOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitOfLabel.text")); // NOI18N
326  matchesPanel.add(hitOfLabel);
327 
328  hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
329  hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
330  hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14));
331  hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14));
332  hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14));
333  matchesPanel.add(hitTotalLabel);
334 
335  hitButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitButtonsLabel.text")); // NOI18N
336  matchesPanel.add(hitButtonsLabel);
337  matchesPanel.add(fillerMed2);
338 
339  hitPreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
340  hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
341  hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
342  hitPreviousButton.setBorderPainted(false);
343  hitPreviousButton.setContentAreaFilled(false);
344  hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
345  hitPreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
346  hitPreviousButton.setPreferredSize(new java.awt.Dimension(23, 23));
347  hitPreviousButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); // NOI18N
348  matchesPanel.add(hitPreviousButton);
349 
350  hitNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
351  hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitNextButton.text")); // NOI18N
352  hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
353  hitNextButton.setBorderPainted(false);
354  hitNextButton.setContentAreaFilled(false);
355  hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
356  hitNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
357  hitNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
358  hitNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); // NOI18N
359  matchesPanel.add(hitNextButton);
360  matchesPanel.add(fillerSmall11);
361 
362  jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL);
363  jSeparator3.setMaximumSize(new java.awt.Dimension(2, 25));
364  jSeparator3.setMinimumSize(new java.awt.Dimension(2, 25));
365  jSeparator3.setName(""); // NOI18N
366  jSeparator3.setPreferredSize(new java.awt.Dimension(2, 25));
367  matchesPanel.add(jSeparator3);
368 
369  controlPanel.add(matchesPanel);
370 
371  zoomPanelWrapper.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
372 
373  zoomPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
374  zoomPanelWrapper.add(zoomPanel);
375  zoomPanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.AccessibleContext.accessibleName")); // NOI18N
376 
377  zoomPanelWrapper.add(fillerSmall14);
378 
379  jSeparator4.setOrientation(javax.swing.SwingConstants.VERTICAL);
380  jSeparator4.setMaximumSize(new java.awt.Dimension(2, 25));
381  jSeparator4.setMinimumSize(new java.awt.Dimension(2, 25));
382  jSeparator4.setName(""); // NOI18N
383  jSeparator4.setPreferredSize(new java.awt.Dimension(2, 25));
384  zoomPanelWrapper.add(jSeparator4);
385 
386  controlPanel.add(zoomPanelWrapper);
387 
388  textSourcePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 0));
389 
390  jLabel1.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.jLabel1.text")); // NOI18N
391  textSourcePanel.add(jLabel1);
392  textSourcePanel.add(fillerSmall12);
393 
394  sourceComboBox.setModel(new javax.swing.DefaultComboBoxModel<org.sleuthkit.autopsy.keywordsearch.IndexedText>());
395  sourceComboBox.setMaximumSize(new java.awt.Dimension(150, 32767));
396  sourceComboBox.setMinimumSize(new java.awt.Dimension(150, 25));
397  sourceComboBox.setPreferredSize(new java.awt.Dimension(150, 25));
398  textSourcePanel.add(sourceComboBox);
399 
400  controlPanel.add(textSourcePanel);
401 
402  add(controlPanel, java.awt.BorderLayout.NORTH);
403 
404  extractedScrollPane.setBackground(new java.awt.Color(255, 255, 255));
405  extractedScrollPane.setPreferredSize(new java.awt.Dimension(640, 29));
406 
407  extractedTextPane.setEditable(false);
408  extractedTextPane.setAutoscrolls(false);
409  extractedTextPane.setInheritsPopupMenu(true);
410  extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
411  extractedTextPane.setPreferredSize(new java.awt.Dimension(600, 29));
412  extractedScrollPane.setViewportView(extractedTextPane);
413 
414  add(extractedScrollPane, java.awt.BorderLayout.CENTER);
415  }// </editor-fold>//GEN-END:initComponents
416  // Variables declaration - do not modify//GEN-BEGIN:variables
417  private javax.swing.JPanel controlPanel;
418  private javax.swing.JMenuItem copyMenuItem;
419  private javax.swing.JScrollPane extractedScrollPane;
420  private javax.swing.JTextPane extractedTextPane;
421  private javax.swing.JLabel hitButtonsLabel;
422  private javax.swing.JLabel hitCountLabel;
423  private javax.swing.JLabel hitLabel;
424  private javax.swing.JButton hitNextButton;
425  private javax.swing.JLabel hitOfLabel;
426  private javax.swing.JButton hitPreviousButton;
427  private javax.swing.JLabel hitTotalLabel;
428  private javax.swing.JLabel jLabel1;
429  private javax.swing.JSeparator jSeparator2;
430  private javax.swing.JSeparator jSeparator3;
431  private javax.swing.JSeparator jSeparator4;
432  private javax.swing.JLabel pageButtonsLabel;
433  private javax.swing.JLabel pageCurLabel;
434  private javax.swing.JButton pageNextButton;
435  private javax.swing.JLabel pageOfLabel;
436  private javax.swing.JButton pagePreviousButton;
437  private javax.swing.JLabel pageTotalLabel;
438  private javax.swing.JLabel pagesLabel;
439  private javax.swing.JPopupMenu rightClickMenu;
440  private javax.swing.JMenuItem selectAllMenuItem;
441  private javax.swing.JComboBox<org.sleuthkit.autopsy.keywordsearch.IndexedText> sourceComboBox;
442  private javax.swing.JPanel textSourcePanel;
443  private javax.swing.JPanel zoomPanel;
444  // End of variables declaration//GEN-END:variables
445 
446  void refreshCurrentMarkup() {
447  setMarkup(getSelectedSource());
448  }
449 
458  final void setSources(String contentName, List<IndexedText> sources) {
459  this.lastKnownAnchor = null;
460  this.contentName = contentName;
461  setPanelText(null, false);
462 
463  sourceComboBox.removeAllItems();
464  sources.forEach(sourceComboBox::addItem);
465  if (false == sources.isEmpty()) {
466  sourceComboBox.setEnabled(true);
467  sourceComboBox.setSelectedIndex(0);
468  } else {
469  sourceComboBox.setEnabled(false);
470  }
471  }
472 
478  public IndexedText getSelectedSource() {
479  return (IndexedText) sourceComboBox.getSelectedItem();
480  }
481 
482  private void setPanelText(String text, boolean detectDirection) {
483  String safeText = StringUtils.defaultString(text);
484 
485  if (detectDirection) {
486  //detect text direction using first 1024 chars and set it
487  //get first up to 1024 chars, strip <pre> tag and unescape html to get the string on which to detect
488  final int len = safeText.length();
489  final int prefixLen = "<pre>".length(); //NON-NLS
490  if (len > prefixLen) {
491  final int maxOrientChars = Math.min(len, 1024);
492  final String orientDetectText = EscapeUtil.unEscapeHtml(safeText.substring(prefixLen, maxOrientChars));
493  ComponentOrientation direction = TextUtil.getTextDirection(orientDetectText);
494  extractedTextPane.applyComponentOrientation(direction);
495  } else {
496  extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
497  }
498  } else {
499  extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
500  }
501 
502  extractedTextPane.setText(safeText);
503  extractedTextPane.setCaretPosition(0);
504  }
505 
506  void scrollToAnchor(String anchor) {
507  lastKnownAnchor = anchor;
508  extractedTextPane.scrollToReference(anchor);
509  }
510 
516  void updateCurrentMatchDisplay(int current) {
517  if (current == 0) {
518  hitCountLabel.setText("-");
519  } else {
520  hitCountLabel.setText(Integer.toString(current));
521  }
522  }
523 
529  void updateTotaMatcheslDisplay(int total) {
530  if (total == 0) {
531  hitTotalLabel.setText("-");
532  } else {
533  hitTotalLabel.setText(Integer.toString(total));
534  }
535  }
536 
542  void updateCurrentPageDisplay(int current) {
543  pageCurLabel.setText(Integer.toString(current));
544  }
545 
551  void updateTotalPagesDisplay(int total) {
552  pageTotalLabel.setText(Integer.toString(total));
553  }
554 
559  void resetDisplay() {
560  setSources("", new ArrayList<>());
561  hitTotalLabel.setText("-");
562  hitCountLabel.setText("-");
563  pageCurLabel.setText("-");
564  pageTotalLabel.setText("-");
565  }
566 
572  void enablePrevMatchControl(boolean enable) {
573  hitPreviousButton.setEnabled(enable);
574  }
575 
581  void enableNextMatchControl(boolean enable) {
582  hitNextButton.setEnabled(enable);
583  }
584 
585  void addPrevMatchControlListener(ActionListener l) {
586  hitPreviousButton.addActionListener(l);
587  }
588 
589  void addNextMatchControlListener(ActionListener l) {
590  hitNextButton.addActionListener(l);
591  }
592 
598  void enablePrevPageControl(boolean enable) {
599  pagePreviousButton.setEnabled(enable);
600  }
601 
607  void enableNextPageControl(boolean enable) {
608  pageNextButton.setEnabled(enable);
609  }
610 
611  void addPrevPageControlListener(ActionListener l) {
612  pagePreviousButton.addActionListener(l);
613  }
614 
615  void addNextPageControlListener(ActionListener l) {
616  pageNextButton.addActionListener(l);
617  }
618 
619  void addSourceComboControlListener(ActionListener l) {
620  sourceComboBox.addActionListener(l);
621  }
622 
628  void updateControls(IndexedText source) {
629  updatePageControls(source);
630  updateSearchControls(source);
631  }
632 
638  void updatePageControls(IndexedText source) {
639  if (source == null) {
640  enableNextPageControl(false);
641  enablePrevPageControl(false);
642  updateCurrentPageDisplay(0);
643  updateTotalPagesDisplay(0);
644  return;
645  }
646 
647  updateCurrentPageDisplay(source.getCurrentPage());
648  int totalPages = source.getNumberPages();
649  updateTotalPagesDisplay(totalPages);
650 
651  if (totalPages < 2) {
652  enableNextPageControl(false);
653  enablePrevPageControl(false);
654  } else {
655  enableNextPageControl(source.hasNextPage());
656  enablePrevPageControl(source.hasPreviousPage());
657  }
658  }
659 
665  void updateSearchControls(IndexedText source) {
666  //setup search controls
667  if (source != null && source.isSearchable()) {
668  updateCurrentMatchDisplay(source.currentItem());
669  updateTotaMatcheslDisplay(source.getNumberHits());
670  enableNextMatchControl(source.hasNextItem() || source.hasNextPage());
671  enablePrevMatchControl(source.hasPreviousItem() || source.hasPreviousPage());
672  } else {
673  enableNextMatchControl(false);
674  enablePrevMatchControl(false);
675  updateCurrentMatchDisplay(0);
676  updateTotaMatcheslDisplay(0);
677  }
678  }
679 
685  private void scrollToCurrentHit(final IndexedText source) {
686  if (source == null || !source.isSearchable()) {
687  return;
688  }
689 
690  //scrolling required invokeLater to enqueue in EDT
691  EventQueue.invokeLater(() -> scrollToAnchor(source.getAnchorPrefix() + source.currentItem()));
692 
693  }
694 
700  @NbBundle.Messages("ExtractedContentPanel.setMarkup.panelTxt=<span style='font-style:italic'>Loading text... Please wait</span>")
701  private void setMarkup(IndexedText source) {
702  setPanelText(Bundle.ExtractedContentPanel_setMarkup_panelTxt(), false);
703  new SetMarkupWorker(contentName, source).execute();
704  }
705 
711  private final class SetMarkupWorker extends SwingWorker<String, Void> {
712 
713  private final String contentName;
714 
715  private final IndexedText source;
716 
717  private ProgressHandle progress;
718 
719  SetMarkupWorker(String contentName, IndexedText source) {
720  this.contentName = contentName;
721  this.source = source;
722  }
723 
724  @Override
725  @NbBundle.Messages({"# {0} - Content name",
726  "ExtractedContentPanel.SetMarkup.progress.loading=Loading text for {0}"})
727  protected String doInBackground() throws Exception {
728  progress = ProgressHandle.createHandle(Bundle.ExtractedContentPanel_SetMarkup_progress_loading(contentName));
729  progress.start();
730  progress.switchToIndeterminate();
731 
732  return source.getText();
733  }
734 
735  @Override
736  protected void done() {
737  super.done();
738  progress.finish();
739 
740  // see if there are any errors
741  try {
742  String markup = get();
743  if (markup != null) {
744  setPanelText(markup, true);
745  } else {
746  setPanelText("", false);
747  }
748  } catch (InterruptedException | CancellationException | ExecutionException ex) {
749  logger.log(Level.SEVERE, "Error getting marked up text", ex); //NON-NLS
750  setPanelText(Bundle.IndexedText_errorMessage_errorGettingText(), true);
751  }
752 
753  updateControls(source);
754  scrollToCurrentHit(source);
755  }
756  }
757 }

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.