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

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.