19 package org.sleuthkit.autopsy.keywordsearch;
 
   21 import java.awt.ComponentOrientation;
 
   22 import java.awt.EventQueue;
 
   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.SizeRequirements;
 
   33 import javax.swing.SwingUtilities;
 
   34 import javax.swing.SwingWorker;
 
   35 import javax.swing.UIManager;
 
   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;
 
   56 @SuppressWarnings(
"PMD.SingularField") 
 
   57 class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextPanel {
 
   59     private static final Logger logger = Logger.getLogger(ExtractedContentPanel.class.getName());
 
   62     private static final Font DEFAULT_FONT = UIManager.getDefaults().getFont(
"Label.font");
 
   64     private static final long serialVersionUID = 1L;
 
   65     private String contentName;
 
   68     private final StyleSheet styleSheet;
 
   69     private final HTMLEditorKit editorKit;
 
   70     private String lastKnownAnchor = null;
 
   72     ExtractedContentPanel() {
 
   75         hitPreviousButton.setEnabled(
false);
 
   76         hitNextButton.setEnabled(
false);
 
   83         editorKit = 
new HTMLEditorKit() {
 
   84             private static final long serialVersionUID = 1L;
 
   87             public ViewFactory getViewFactory() {
 
   89                 return new HTMLFactory() {
 
   91                     public View create(Element e) {
 
   92                         View v = super.create(e);
 
   93                         if (v instanceof InlineView) {
 
   94                             return new InlineView(e) {
 
   96                                 public int getBreakWeight(
int axis, 
float pos, 
float len) {
 
   97                                     return GoodBreakWeight;
 
  101                                 public View breakView(
int axis, 
int p0, 
float pos, 
float len) {
 
  102                                     if (axis == View.X_AXIS) {
 
  104                                         int p1 = getGlyphPainter().getBoundedPosition(
this, p0, pos, len);
 
  105                                         if (p0 == getStartOffset() && p1 == getEndOffset()) {
 
  108                                         return createFragment(p0, p1);
 
  113                         } 
else if (v instanceof ParagraphView) {
 
  114                             return new ParagraphView(e) {
 
  116                                 protected SizeRequirements calculateMinorAxisRequirements(
int axis, SizeRequirements r) {
 
  117                                     SizeRequirements requirements = r;
 
  118                                     if (requirements == null) {
 
  119                                         requirements = 
new SizeRequirements();
 
  121                                     float pref = layoutPool.getPreferredSpan(axis);
 
  122                                     float min = layoutPool.getMinimumSpan(axis);
 
  124                                     requirements.minimum = (int) min;
 
  125                                     requirements.preferred = Math.max(requirements.minimum, (
int) pref);
 
  126                                     requirements.maximum = Integer.MAX_VALUE;
 
  127                                     requirements.alignment = 0.5f;
 
  138         styleSheet = editorKit.getStyleSheet();
 
  140         sourceComboBox.addItemListener(itemEvent -> {
 
  141             if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
 
  142                 refreshCurrentMarkup();
 
  145         extractedTextPane.setComponentPopupMenu(rightClickMenu);
 
  147         copyMenuItem.addActionListener(actionEvent -> extractedTextPane.copy());
 
  148         selectAllMenuItem.addActionListener(actionEvent -> extractedTextPane.selectAll());
 
  155         SwingUtilities.invokeLater(() -> {
 
  156             if (zoomPanel instanceof TextZoomPanel)
 
  157                 ((TextZoomPanel) this.zoomPanel).resetSize();
 
  160         setSources(
"", 
new ArrayList<>());
 
  164     private void setStyleSheetSize(StyleSheet styleSheet, 
int size) {
 
  166                 "body { font-family:\"" + DEFAULT_FONT.getFamily() + 
"\"; font-size:" + size + 
"pt; } " +
 
  167                 "pre { font-family:\"" + DEFAULT_FONT.getFamily() + 
"\"; font-size:" + size + 
"pt; } " 
  173     public int getTextSize() {
 
  178     public void setTextSize(
int newSize) {
 
  181         String curText = extractedTextPane.getText();
 
  183         setStyleSheetSize(styleSheet, curSize);
 
  185         editorKit.setStyleSheet(styleSheet);
 
  186         extractedTextPane.setEditorKit(editorKit);
 
  188         extractedTextPane.setText(curText);
 
  189         if (lastKnownAnchor != null)
 
  190             scrollToAnchor(lastKnownAnchor);
 
  194     private void additionalInit() {
 
  196         WrapLayout layout = 
new WrapLayout(0,5);
 
  197         layout.setOppositeAligned(Arrays.asList(textSourcePanel));
 
  198         controlPanel.setLayout(layout);
 
  207     @SuppressWarnings(
"unchecked")
 
  209     private 
void initComponents() {
 
  211         rightClickMenu = 
new javax.swing.JPopupMenu();
 
  212         copyMenuItem = 
new javax.swing.JMenuItem();
 
  213         selectAllMenuItem = 
new javax.swing.JMenuItem();
 
  214         controlPanel = 
new javax.swing.JPanel();
 
  215         javax.swing.JPanel pagePanel = 
new javax.swing.JPanel();
 
  216         pagesLabel = 
new javax.swing.JLabel();
 
  217         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));
 
  218         pageCurLabel = 
new javax.swing.JLabel();
 
  219         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));
 
  220         pageOfLabel = 
new javax.swing.JLabel();
 
  221         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));
 
  222         pageTotalLabel = 
new javax.swing.JLabel();
 
  223         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));
 
  224         pageButtonsLabel = 
new javax.swing.JLabel();
 
  225         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));
 
  226         pagePreviousButton = 
new javax.swing.JButton();
 
  227         pageNextButton = 
new javax.swing.JButton();
 
  228         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));
 
  229         jSeparator2 = 
new javax.swing.JSeparator();
 
  230         javax.swing.JPanel matchesPanel = 
new javax.swing.JPanel();
 
  231         hitLabel = 
new javax.swing.JLabel();
 
  232         hitCountLabel = 
new javax.swing.JLabel();
 
  233         hitOfLabel = 
new javax.swing.JLabel();
 
  234         hitTotalLabel = 
new javax.swing.JLabel();
 
  235         hitButtonsLabel = 
new javax.swing.JLabel();
 
  236         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));
 
  237         hitPreviousButton = 
new javax.swing.JButton();
 
  238         hitNextButton = 
new javax.swing.JButton();
 
  239         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));
 
  240         jSeparator3 = 
new javax.swing.JSeparator();
 
  241         javax.swing.JPanel zoomPanelWrapper = 
new javax.swing.JPanel();
 
  242         zoomPanel = 
new TextZoomPanel(
this);
 
  243         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));
 
  244         jSeparator4 = 
new javax.swing.JSeparator();
 
  245         textSourcePanel = 
new javax.swing.JPanel();
 
  246         jLabel1 = 
new javax.swing.JLabel();
 
  247         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));
 
  248         sourceComboBox = 
new javax.swing.JComboBox<>();
 
  249         extractedScrollPane = 
new javax.swing.JScrollPane();
 
  250         extractedTextPane = 
new javax.swing.JTextPane();
 
  252         copyMenuItem.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.copyMenuItem.text")); 
 
  253         rightClickMenu.add(copyMenuItem);
 
  255         selectAllMenuItem.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.selectAllMenuItem.text")); 
 
  256         rightClickMenu.add(selectAllMenuItem);
 
  258         setMinimumSize(
new java.awt.Dimension(250, 0));
 
  259         setPreferredSize(
new java.awt.Dimension(250, 58));
 
  260         setLayout(
new java.awt.BorderLayout());
 
  262         controlPanel.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
 
  264         pagePanel.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
 
  266         pagesLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pagesLabel.text")); 
 
  267         pagePanel.add(pagesLabel);
 
  268         pagePanel.add(fillerSmall1);
 
  270         pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
 
  271         pageCurLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pageCurLabel.text")); 
 
  272         pagePanel.add(pageCurLabel);
 
  273         pagePanel.add(fillerSmall2);
 
  275         pageOfLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pageOfLabel.text")); 
 
  276         pagePanel.add(pageOfLabel);
 
  277         pagePanel.add(fillerSmall3);
 
  279         pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
 
  280         pageTotalLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pageTotalLabel.text")); 
 
  281         pagePanel.add(pageTotalLabel);
 
  282         pagePanel.add(fillerSmall4);
 
  284         pageButtonsLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pageButtonsLabel.text")); 
 
  285         pagePanel.add(pageButtonsLabel);
 
  286         pagePanel.add(fillerMed1);
 
  288         pagePreviousButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); 
 
  289         pagePreviousButton.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pagePreviousButton.text")); 
 
  290         pagePreviousButton.setActionCommand(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pagePreviousButton.actionCommand")); 
 
  291         pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  292         pagePreviousButton.setBorderPainted(
false);
 
  293         pagePreviousButton.setContentAreaFilled(
false);
 
  294         pagePreviousButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); 
 
  295         pagePreviousButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  296         pagePanel.add(pagePreviousButton);
 
  298         pageNextButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); 
 
  299         pageNextButton.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.pageNextButton.text")); 
 
  300         pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  301         pageNextButton.setBorderPainted(
false);
 
  302         pageNextButton.setContentAreaFilled(
false);
 
  303         pageNextButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); 
 
  304         pageNextButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  305         pageNextButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  306         pagePanel.add(pageNextButton);
 
  307         pagePanel.add(fillerSmall6);
 
  309         jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);
 
  310         jSeparator2.setMaximumSize(
new java.awt.Dimension(2, 25));
 
  311         jSeparator2.setMinimumSize(
new java.awt.Dimension(2, 25));
 
  312         jSeparator2.setPreferredSize(
new java.awt.Dimension(2, 25));
 
  313         pagePanel.add(jSeparator2);
 
  315         controlPanel.add(pagePanel);
 
  317         matchesPanel.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
 
  319         hitLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitLabel.text")); 
 
  320         hitLabel.setToolTipText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitLabel.toolTipText")); 
 
  321         matchesPanel.add(hitLabel);
 
  323         hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
 
  324         hitCountLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitCountLabel.text")); 
 
  325         hitCountLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
 
  326         hitCountLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
 
  327         hitCountLabel.setPreferredSize(
new java.awt.Dimension(18, 14));
 
  328         matchesPanel.add(hitCountLabel);
 
  330         hitOfLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitOfLabel.text")); 
 
  331         matchesPanel.add(hitOfLabel);
 
  333         hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
 
  334         hitTotalLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitTotalLabel.text")); 
 
  335         hitTotalLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
 
  336         hitTotalLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
 
  337         hitTotalLabel.setPreferredSize(
new java.awt.Dimension(18, 14));
 
  338         matchesPanel.add(hitTotalLabel);
 
  340         hitButtonsLabel.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitButtonsLabel.text")); 
 
  341         matchesPanel.add(hitButtonsLabel);
 
  342         matchesPanel.add(fillerMed2);
 
  344         hitPreviousButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); 
 
  345         hitPreviousButton.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitPreviousButton.text")); 
 
  346         hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  347         hitPreviousButton.setBorderPainted(
false);
 
  348         hitPreviousButton.setContentAreaFilled(
false);
 
  349         hitPreviousButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); 
 
  350         hitPreviousButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  351         hitPreviousButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  352         hitPreviousButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); 
 
  353         matchesPanel.add(hitPreviousButton);
 
  355         hitNextButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); 
 
  356         hitNextButton.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.hitNextButton.text")); 
 
  357         hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  358         hitNextButton.setBorderPainted(
false);
 
  359         hitNextButton.setContentAreaFilled(
false);
 
  360         hitNextButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); 
 
  361         hitNextButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
 
  362         hitNextButton.setPreferredSize(
new java.awt.Dimension(23, 23));
 
  363         hitNextButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); 
 
  364         matchesPanel.add(hitNextButton);
 
  365         matchesPanel.add(fillerSmall11);
 
  367         jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL);
 
  368         jSeparator3.setMaximumSize(
new java.awt.Dimension(2, 25));
 
  369         jSeparator3.setMinimumSize(
new java.awt.Dimension(2, 25));
 
  370         jSeparator3.setName(
""); 
 
  371         jSeparator3.setPreferredSize(
new java.awt.Dimension(2, 25));
 
  372         matchesPanel.add(jSeparator3);
 
  374         controlPanel.add(matchesPanel);
 
  376         zoomPanelWrapper.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
 
  378         zoomPanel.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
 
  379         zoomPanelWrapper.add(zoomPanel);
 
  380         zoomPanel.getAccessibleContext().setAccessibleName(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.AccessibleContext.accessibleName")); 
 
  382         zoomPanelWrapper.add(fillerSmall14);
 
  384         jSeparator4.setOrientation(javax.swing.SwingConstants.VERTICAL);
 
  385         jSeparator4.setMaximumSize(
new java.awt.Dimension(2, 25));
 
  386         jSeparator4.setMinimumSize(
new java.awt.Dimension(2, 25));
 
  387         jSeparator4.setName(
""); 
 
  388         jSeparator4.setPreferredSize(
new java.awt.Dimension(2, 25));
 
  389         zoomPanelWrapper.add(jSeparator4);
 
  391         controlPanel.add(zoomPanelWrapper);
 
  393         textSourcePanel.setLayout(
new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 0));
 
  395         jLabel1.setText(
org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, 
"ExtractedContentPanel.jLabel1.text")); 
 
  396         textSourcePanel.add(jLabel1);
 
  397         textSourcePanel.add(fillerSmall12);
 
  400         sourceComboBox.setMaximumSize(
new java.awt.Dimension(150, 32767));
 
  401         sourceComboBox.setMinimumSize(
new java.awt.Dimension(150, 25));
 
  402         sourceComboBox.setPreferredSize(
new java.awt.Dimension(150, 25));
 
  403         textSourcePanel.add(sourceComboBox);
 
  405         controlPanel.add(textSourcePanel);
 
  407         add(controlPanel, java.awt.BorderLayout.NORTH);
 
  409         extractedScrollPane.setBackground(
new java.awt.Color(255, 255, 255));
 
  410         extractedScrollPane.setPreferredSize(
new java.awt.Dimension(640, 29));
 
  412         extractedTextPane.setEditable(
false);
 
  413         extractedTextPane.setAutoscrolls(
false);
 
  414         extractedTextPane.setInheritsPopupMenu(
true);
 
  415         extractedTextPane.setMaximumSize(
new java.awt.Dimension(2000, 2000));
 
  416         extractedTextPane.setPreferredSize(
new java.awt.Dimension(600, 29));
 
  417         extractedScrollPane.setViewportView(extractedTextPane);
 
  419         add(extractedScrollPane, java.awt.BorderLayout.CENTER);
 
  422     private javax.swing.JPanel controlPanel;
 
  423     private javax.swing.JMenuItem copyMenuItem;
 
  424     private javax.swing.JScrollPane extractedScrollPane;
 
  425     private javax.swing.JTextPane extractedTextPane;
 
  426     private javax.swing.JLabel hitButtonsLabel;
 
  427     private javax.swing.JLabel hitCountLabel;
 
  428     private javax.swing.JLabel hitLabel;
 
  429     private javax.swing.JButton hitNextButton;
 
  430     private javax.swing.JLabel hitOfLabel;
 
  431     private javax.swing.JButton hitPreviousButton;
 
  432     private javax.swing.JLabel hitTotalLabel;
 
  433     private javax.swing.JLabel jLabel1;
 
  434     private javax.swing.JSeparator jSeparator2;
 
  435     private javax.swing.JSeparator jSeparator3;
 
  436     private javax.swing.JSeparator jSeparator4;
 
  437     private javax.swing.JLabel pageButtonsLabel;
 
  438     private javax.swing.JLabel pageCurLabel;
 
  439     private javax.swing.JButton pageNextButton;
 
  440     private javax.swing.JLabel pageOfLabel;
 
  441     private javax.swing.JButton pagePreviousButton;
 
  442     private javax.swing.JLabel pageTotalLabel;
 
  443     private javax.swing.JLabel pagesLabel;
 
  444     private javax.swing.JPopupMenu rightClickMenu;
 
  445     private javax.swing.JMenuItem selectAllMenuItem;
 
  447     private javax.swing.JPanel textSourcePanel;
 
  448     private javax.swing.JPanel zoomPanel;
 
  451     void refreshCurrentMarkup() {
 
  452         setMarkup(getSelectedSource());
 
  463     final void setSources(String contentName, List<ExtractedText> sources) {
 
  464         this.lastKnownAnchor = null;
 
  465         this.contentName = contentName;
 
  466         setPanelText(null, 
false);
 
  468         sourceComboBox.removeAllItems();
 
  469         sources.forEach(sourceComboBox::addItem);
 
  470         if (
false == sources.isEmpty()) {
 
  471             sourceComboBox.setEnabled(
true);
 
  472             sourceComboBox.setSelectedIndex(0);
 
  474             sourceComboBox.setEnabled(
false);
 
  483     public ExtractedText getSelectedSource() {
 
  484         return (ExtractedText) sourceComboBox.getSelectedItem();
 
  487     private void setPanelText(String text, 
boolean detectDirection) {
 
  488         String safeText = StringUtils.defaultString(text);
 
  490         if (detectDirection) {
 
  493             final int len = safeText.length();
 
  494             final int prefixLen = 
"<pre>".length(); 
 
  495             if (len > prefixLen) {
 
  496                 final int maxOrientChars = Math.min(len, 1024);
 
  497                 final String orientDetectText = EscapeUtil.unEscapeHtml(safeText.substring(prefixLen, maxOrientChars));
 
  498                 ComponentOrientation direction = TextUtil.getTextDirection(orientDetectText);
 
  499                 extractedTextPane.applyComponentOrientation(direction);
 
  501                 extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
 
  504             extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
 
  508         setStyleSheetSize(styleSheet, curSize);
 
  509         extractedTextPane.setText(safeText);
 
  510         extractedTextPane.setCaretPosition(0);
 
  513     void scrollToAnchor(String anchor) {
 
  514         lastKnownAnchor = anchor;
 
  515         extractedTextPane.scrollToReference(anchor);
 
  523     void updateCurrentMatchDisplay(
int current) {
 
  525             hitCountLabel.setText(
"-");
 
  527             hitCountLabel.setText(Integer.toString(current));
 
  536     void updateTotaMatcheslDisplay(
int total) {
 
  538             hitTotalLabel.setText(
"-");
 
  540             hitTotalLabel.setText(Integer.toString(total));
 
  549     void updateCurrentPageDisplay(
int current) {
 
  550         pageCurLabel.setText(Integer.toString(current));
 
  558     void updateTotalPagesDisplay(
int total) {
 
  560             pageTotalLabel.setText(Integer.toString(total));
 
  562             pageTotalLabel.setText(
"-");
 
  570     void resetDisplay() {
 
  571         setSources(
"", 
new ArrayList<>());
 
  572         hitTotalLabel.setText(
"-");
 
  573         hitCountLabel.setText(
"-");
 
  574         pageCurLabel.setText(
"-");
 
  575         pageTotalLabel.setText(
"-");
 
  583     void enablePrevMatchControl(
boolean enable) {
 
  584         hitPreviousButton.setEnabled(enable);
 
  592     void enableNextMatchControl(
boolean enable) {
 
  593         hitNextButton.setEnabled(enable);
 
  596     void addPrevMatchControlListener(ActionListener l) {
 
  597         hitPreviousButton.addActionListener(l);
 
  600     void addNextMatchControlListener(ActionListener l) {
 
  601         hitNextButton.addActionListener(l);
 
  609     void enablePrevPageControl(
boolean enable) {
 
  610         pagePreviousButton.setEnabled(enable);
 
  618     void enableNextPageControl(
boolean enable) {
 
  619         pageNextButton.setEnabled(enable);
 
  622     void addPrevPageControlListener(ActionListener l) {
 
  623         pagePreviousButton.addActionListener(l);
 
  626     void addNextPageControlListener(ActionListener l) {
 
  627         pageNextButton.addActionListener(l);
 
  630     void addSourceComboControlListener(ActionListener l) {
 
  631         sourceComboBox.addActionListener(l);
 
  639     void updateControls(ExtractedText source) {
 
  640         updatePageControls(source);
 
  641         updateSearchControls(source);
 
  649     void updatePageControls(ExtractedText source) {
 
  650         if (source == null) {
 
  651             enableNextPageControl(
false);
 
  652             enablePrevPageControl(
false);
 
  653             updateCurrentPageDisplay(0);
 
  654             updateTotalPagesDisplay(0);
 
  658         updateCurrentPageDisplay(source.getCurrentPage());
 
  659         int totalPages = source.getNumberPages();
 
  660         updateTotalPagesDisplay(totalPages);
 
  662         enableNextPageControl(source.hasNextPage());
 
  663         enablePrevPageControl(source.hasPreviousPage());
 
  671     void updateSearchControls(ExtractedText source) {
 
  673         if (source != null && source.isSearchable()) {
 
  674             updateCurrentMatchDisplay(source.currentItem());
 
  675             updateTotaMatcheslDisplay(source.getNumberHits());
 
  676             enableNextMatchControl(source.hasNextItem() || source.hasNextPage());
 
  677             enablePrevMatchControl(source.hasPreviousItem() || source.hasPreviousPage());
 
  679             enableNextMatchControl(
false);
 
  680             enablePrevMatchControl(
false);
 
  681             updateCurrentMatchDisplay(0);
 
  682             updateTotaMatcheslDisplay(0);
 
  691     private void scrollToCurrentHit(
final ExtractedText source) {
 
  692         if (source == null || !source.isSearchable()) {
 
  697         EventQueue.invokeLater(() -> scrollToAnchor(source.getAnchorPrefix() + source.currentItem()));
 
  706     @NbBundle.Messages(
"ExtractedContentPanel.setMarkup.panelTxt=<span style='font-style:italic'>Loading text... Please wait</span>")
 
  707     private void setMarkup(ExtractedText source) {
 
  708         setPanelText(Bundle.ExtractedContentPanel_setMarkup_panelTxt(), 
false);
 
  709         new SetMarkupWorker(contentName, source).execute();
 
  726             this.contentName = contentName;
 
  727             this.source = source;
 
  731         @NbBundle.Messages({
"# {0} - Content name",
 
  732             "ExtractedContentPanel.SetMarkup.progress.loading=Loading text for {0}"})
 
  734             progress = ProgressHandle.createHandle(Bundle.ExtractedContentPanel_SetMarkup_progress_loading(contentName));
 
  736             progress.switchToIndeterminate();
 
  738             return source.getText();
 
  748                 String markup = 
get();
 
  749                 if (markup != null) {
 
  750                     setPanelText(markup, 
true);
 
  752                     setPanelText(
"", 
false);
 
  754             } 
catch (InterruptedException | CancellationException | ExecutionException ex) {
 
  755                 logger.log(Level.SEVERE, 
"Error getting marked up text", ex); 
 
  756                 setPanelText(Bundle.ExtractedText_errorMessage_errorGettingText(), 
true);
 
  759             updateControls(source);
 
  760             scrollToCurrentHit(source);