
org.jpedal.examples.viewer.gui.javafx.JavaFXSearchWindow Maven / Gradle / Ivy
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2016 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* JavaFXSearchWindow.java
* ---------------
*/
package org.jpedal.examples.viewer.gui.javafx;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.jpedal.PdfDecoderInt;
import org.jpedal.display.GUIDisplay;
import org.jpedal.examples.viewer.Commands;
import org.jpedal.examples.viewer.Values;
import org.jpedal.examples.viewer.gui.GUI;
import org.jpedal.examples.viewer.gui.JavaFxGUI;
import org.jpedal.examples.viewer.gui.generic.GUISearchList;
import org.jpedal.examples.viewer.gui.generic.GUISearchWindow;
import org.jpedal.grouping.DefaultSearchListener;
import org.jpedal.grouping.PdfGroupingAlgorithms;
import org.jpedal.grouping.SearchListener;
import org.jpedal.grouping.SearchType;
import org.jpedal.gui.GUIFactory;
import org.jpedal.objects.PdfPageData;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Messages;
import org.jpedal.utils.repositories.generic.Vector_Rectangle_Int;
/**
* Provides interactive search Window and search capabilities.
*
* We extend from Stage to add search into the left side-tab or
* to pop open a search window when either
* style==SEARCH_EXTERNAL_WINDOW || style==SEARCH_TABBED_PANE
* search style can be controlled from Viewer preferences.
*/
public class JavaFXSearchWindow extends Stage implements GUISearchWindow {
/**Flag to show search has happened and needs reset*/
public boolean hasSearched;
/**flag to show searching taking place*/
public boolean isSearch;
int firstPageWithResults;
int searchTypeParameters;
private int style;
Values commonValues;
final GUIFactory currentGUI;
PdfDecoderInt decode_pdf;
/**flag to stop multiple listeners*/
private boolean isSetup;
boolean usingMenuBarSearch;
private boolean endSearch;
private boolean backGroundSearch;
private Map searchAreas;
VBox contentVB = new VBox();
private int searchKey;
private Thread searchThread;
private final Runnable searchRunner = new Runnable() {
@Override
public void run() {
resultsList.setStatus(GUISearchList.SEARCH_INCOMPLETE);
final boolean searchingInBackground = backGroundSearch;
//Now local variable is set we can turn off global variable
backGroundSearch = false;
final int currentKey = searchKey;
try{
// [AWI]: Create a new list model to append the search results to
// NOTE: This was added to prevent a deadlock issue that occurred on the
// EDT when the search resulted in a large number of hits
final ObservableList resultListModel;
if(updateListDuringSearch) {
resultListModel = listModel;
} else {
resultListModel = FXCollections.observableArrayList();
}
int start = 1;
int end = decode_pdf.getPageCount()+1;
if(singlePageSearch){
start = decode_pdf.getPageNumber();
end = start+1;
}
//Create new value as this current page could change half way through a search
final int currentPage = commonValues.getCurrentPage();
int page;
boolean continueSearch = true;
for(; start!=end; start++){
if(usingMenuBarSearch){
//When using menu bar, break from loop if result found
if(resultsList.getResultCount()>=1){
break;
}
page = currentPage+(start-1);
if(page>commonValues.getPageCount()) {
page -= commonValues.getPageCount();
}
}else{
page = start;
}
if(searchAreas!=null){
final int[][] highlights = (int[][])searchAreas.get(page);
if(highlights!=null){
for(int i = highlights.length-1; i>-1; i--){
final int[] a = highlights[i];
//[AWI]: Update the search method to take the target list model as a parameter
continueSearch = searchPage(page, a[0], a[1], a[0]+a[2], a[1]+a[3], currentKey, resultListModel);
}
}
}else{
continueSearch = searchPage(page, currentKey, resultListModel);
}
if(!continueSearch) {
break;
}
// new value or 16 pages elapsed
if (!searchingInBackground && (!resultListModel.isEmpty()) | ((page % 16) == 0)) {
final int pp = page;
Platform.runLater(new Runnable() {
@Override
public void run() {
searchCount.setText(Messages.getMessage("PdfViewerSearch.ItemsFound") + ' ' + itemFoundCount + ' '
+ Messages.getMessage("PdfViewerSearch.Scanning") + pp);
}
});
}
}
if(!searchingInBackground){
Platform.runLater(new Runnable() {
@Override
public void run() {
searchCount.setText(Messages.getMessage("PdfViewerSearch.ItemsFound") + ' ' + itemFoundCount + " "
+ Messages.getMessage("PdfViewerSearch.Done"));
}
});
}
if(!usingMenuBarSearch){ //MenuBarSearch freezes if we attempt to wait
//Wait for EDT to catch up and prevent losing results
while(resultListModel.size()!=itemFoundCount){
Thread.sleep(200);
}
}
// [AWI]: Update the list model displayed in the results list
// NOTE: This was added here to address an EDT lock-up and contention issue
// that can occur when a large result set is returned from a search. By
// setting the model once at the end, we only take the hit for updating the
// JList once.
listModel = resultListModel;
Platform.runLater(new Runnable() {
@Override
public void run() {
if ( resultsList != null && listModel != null ) {
resultsList.setItems(listModel);
}
}
});
if(continueSearch){
//resultsList.setLength(listModel.capacity());
Platform.runLater(new Runnable() {
@Override
public void run() {
currentGUI.setResults(resultsList);
resultsList.scrollTo(0);
resultsList.getSelectionModel().clearAndSelect(0);
}
});
}
if(itemFoundCount>0) {
resultsList.setStatus(GUISearchList.SEARCH_COMPLETE_SUCCESSFULLY);
} else {
resultsList.setStatus(GUISearchList.NO_RESULTS_FOUND);
}
//switch on buttons as soon as search produces valid results
if(!searchingInBackground){
Platform.runLater(new Runnable() {
@Override
public void run() {
currentGUI.getButtons().getButton(Commands.NEXTRESULT).setEnabled(true);
currentGUI.getButtons().getButton(Commands.PREVIOUSRESULT).setEnabled(true);
}
});
}
/**
* show time and memory usage
*/
if(GUI.debugFX){
System.out.println("Search memory="+((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000)+ 'K');
// System.out.println("Search time="+(((float) Math.abs(((System.currentTimeMillis() - startTime) / 100))) / 10)+ 's');
System.out.println("Found "+resultsList.getResultCount()+" Search Results");
}
}catch(final Exception e){
e.printStackTrace();
if(!searchingInBackground){
Platform.runLater(new Runnable() {
@Override
public void run() {
currentGUI.getButtons().getButton(Commands.NEXTRESULT).setEnabled(true);
currentGUI.getButtons().getButton(Commands.PREVIOUSRESULT).setEnabled(true);
}
});
}
resultsList.setStatus(GUISearchList.SEARCH_PRODUCED_ERROR);
}
}
};
int lastPage=-1;
String defaultMessage="Search PDF Here";
public boolean requestInterupt;
/**
* deletes message when user starts typing
*/
private boolean deleteOnClick;
final ProgressBar progress = new ProgressBar(100);
TextField searchText;
Label searchCount;
//DefaultListModel listModel;
JavaFXSearchList resultsList;
Button advOpts;
private final VBox nav=new VBox();
private VBox advancedPanel;
private ComboBox searchType;
private CheckBox wholeWordsOnlyBox, caseSensitiveBox, multiLineBox, highlightAll, searchAll, useRegEx, searchHighlightedOnly;
Button searchButton;
ObservableList listModel;
/**Search this page only*/
boolean singlePageSearch;
/**Current Search value*/
String[] searchTerms = {""};
/**number fo search items*/
private int itemFoundCount;
final Map textPages=new HashMap();
final Map textRectangles=new HashMap();
public JavaFXSearchWindow(final GUIFactory currentGUI) {
if(GUI.debugFX) {
System.out.println("JavaFXSearchWindow constructor not yet implemented for JavaFX in JavaFXSearchWindow.java");
}
this.currentGUI=currentGUI;
//setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
@Override
public void find(final PdfDecoderInt dec, final Values values) {
// System.out.println("clicked pdf = "+decode_pdf.getClass().getName() + "@" + Integer.toHexString(decode_pdf.hashCode()));
/**
* pop up new window to search text (initialise if required
*/
if(!backGroundSearch){
init(dec, values);
if(style==SEARCH_EXTERNAL_WINDOW) {
this.show();
}
}else{
try {
searchText();
} catch (final Exception e) {
e.printStackTrace();
}
}
}
@Override
public void findWithoutWindow(final PdfDecoderInt dec, final Values values, final int searchType, final boolean listOfTerms, final boolean singlePageOnly, final String searchValue) {
if(!isSearch){
backGroundSearch = true;
isSearch=true;
this.decode_pdf = dec;
this.commonValues = values;
progress.setProgress(0);
progress.setVisible(true);
if(!listOfTerms){ // find exact word or phrase
searchTerms = new String[] {searchValue};
} else { // match any of the words
searchTerms = searchValue.split(" ");
for (int i = 0; i < searchTerms.length; i++) {
searchTerms[i] = searchTerms[i].trim();
}
}
searchTypeParameters = searchType;
singlePageSearch = singlePageOnly;
find(dec, values);
}else{
currentGUI.showMessageDialog("Please wait for search to finish before starting another.");
}
}
@Override
public void grabFocusInInput() {
searchText.requestFocus();
}
@Override
public boolean isSearchVisible() {
return this.isShowing();
}
@Override
public void init(final PdfDecoderInt dec, final Values values) {
this.decode_pdf = dec;
this.commonValues = values;
if (isSetup) { //global variable so do NOT reinitialise
searchCount.setText(Messages.getMessage("PdfViewerSearch.ItemsFound") + ' ' + itemFoundCount);
searchText.selectAll();
//searchText.grabFocus();
} else {
isSetup = true;
setTitle(Messages.getMessage("PdfViewerSearchGUITitle.DefaultMessage"));
defaultMessage = Messages.getMessage("PdfViewerSearchGUI.DefaultMessage");
searchText = new TextField();
//may need to apply line wrap for searchText
searchText.setText(defaultMessage);
searchText.setId("searchText");
/*
* [AWI] Add a focus listener to detect when keyboard input is needed in the search text field. This
* registration was added to support systems configured with touchscreens and virtual keyboards.
*/
//searchText.addFocusListener(new SearchTextFocusListener());
searchButton = new Button(Messages.getMessage("PdfViewerSearch.Button"));
advancedPanel = new VBox();
final ObservableList searchOptions
= FXCollections.observableArrayList(
Messages.getMessage("PdfViewerSearch.MatchWhole"),
Messages.getMessage("PdfViewerSearch.MatchAny")
);
searchType = new ComboBox(searchOptions);
searchType.setValue(searchType.getItems().get(0));
wholeWordsOnlyBox = new CheckBox(Messages.getMessage("PdfViewerSearch.WholeWords"));
wholeWordsOnlyBox.setId("wholeWords");
caseSensitiveBox = new CheckBox(Messages.getMessage("PdfViewerSearch.CaseSense"));
caseSensitiveBox.setId("caseSensitive");
multiLineBox = new CheckBox(Messages.getMessage("PdfViewerSearch.MultiLine"));
multiLineBox.setId("multiLine");
highlightAll = new CheckBox(Messages.getMessage("PdfViewerSearch.HighlightsCheckBox"));
highlightAll.setId("highlightAll");
useRegEx = new CheckBox(Messages.getMessage("PdfViewerSearch.RegExCheckBox"));
useRegEx.setId("useregex");
searchHighlightedOnly = new CheckBox(Messages.getMessage("PdfViewerSearch.HighlightsOnly"));
searchHighlightedOnly.setId("highlightsOnly");
searchType.setId("combo");
advancedPanel.getChildren().add(new Label(Messages.getMessage("PdfViewerSearch.ReturnResultsAs")));
advancedPanel.getChildren().add(searchType);
advancedPanel.getChildren().add(new Label(Messages.getMessage("PdfViewerSearch.AdditionalOptions")));
advancedPanel.getChildren().add(wholeWordsOnlyBox);
advancedPanel.getChildren().add(caseSensitiveBox);
advancedPanel.getChildren().add(multiLineBox);
advancedPanel.getChildren().add(highlightAll);
advancedPanel.getChildren().add(useRegEx);
advancedPanel.getChildren().add(searchHighlightedOnly);
advancedPanel.setVisible(false);
searchAll = new CheckBox();
searchAll.setSelected(true);
searchAll.setText(Messages.getMessage("PdfViewerSearch.CheckBox"));
final VBox topPanel = new VBox();
topPanel.getChildren().add(searchAll);
advOpts = new Button(Messages.getMessage("PdfViewerSearch.ShowOptions"));
advOpts.setId("advSearch");
advOpts.setOnMouseEntered(new EventHandler() {
@Override
public void handle(final MouseEvent me) {
if (GUIDisplay.allowChangeCursor) {
nav.setCursor(Cursor.HAND);
}
}
});
advOpts.setOnMouseExited(new EventHandler() {
@Override
public void handle(final MouseEvent me) {
if (GUIDisplay.allowChangeCursor) {
nav.setCursor(Cursor.DEFAULT);
}
}
});
advOpts.setOnMouseClicked(new EventHandler() {
boolean isVisible;
@Override
public void handle(final MouseEvent me) {
if (isVisible) {
advOpts.setText(Messages.getMessage("PdfViewerSearch.ShowOptions"));
advancedPanel.setVisible(false);
} else {
advOpts.setText(Messages.getMessage("PdfViewerSearch.HideOptions"));
advancedPanel.setVisible(true);
}
isVisible = !isVisible;
}
});
topPanel.getChildren().add(advOpts);
nav.getChildren().add(topPanel);
final HBox navBox = new HBox();
navBox.getChildren().addAll(searchText, searchButton);
nav.getChildren().add(navBox);
itemFoundCount = 0;
textPages.clear();
textRectangles.clear();
//listModel = null;
searchCount = new Label(Messages.getMessage("PdfViewerSearch.ItemsFound") + ' ' + itemFoundCount);
nav.getChildren().add(searchCount);
listModel = FXCollections.observableArrayList();
listModel = FXCollections.observableArrayList();
resultsList = new JavaFXSearchList(listModel, textPages, textRectangles);
resultsList.setId("results");
//
/**
* highlight text on item selected
*/
resultsList.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() {
@Override
public void changed(final ObservableValue extends Number> ov, final Number t, final Number t1) {
/**
* Only do something on mouse button up, prevents this code
* being called twice on mouse click
*/
if (!Values.isProcessing()) {//{if (!event.getValueIsAdjusting()) {
final float scaling = currentGUI.getScaling();
//int inset=currentGUI.getPDFDisplayInset();
final int id = (Integer)t1;//resultsList.getSelectedIndex();
decode_pdf.getTextLines().clearHighlights();
//System.out.println("clicked pdf = "+decode_pdf.getClass().getName() + "@" + Integer.toHexString(decode_pdf.hashCode()));
if (id != -1) {
final Integer key = id;
final Object newPage = textPages.get(key);
if (newPage != null) {
final int nextPage = (Integer) newPage;
//move to new page
if (commonValues.getCurrentPage() != nextPage) {
commonValues.setCurrentPage(nextPage);
currentGUI.resetStatusMessage(Messages.getMessage("PdfViewer.LoadingPage") + ' ' + commonValues.getCurrentPage());
/**
* reset as rotation may change!
*/
decode_pdf.setPageParameters(scaling, commonValues.getCurrentPage());
//decode the page
currentGUI.decodePage();
}
while (Values.isProcessing()) {
//Ensure page has been processed else highlight may be incorrect
try {
Thread.sleep(500);
} catch (final InterruptedException ee) {
ee.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
/**
* Highlight all search results on page.
*/
if ((searchTypeParameters & SearchType.HIGHLIGHT_ALL_RESULTS) == SearchType.HIGHLIGHT_ALL_RESULTS) {
// PdfHighlights.clearAllHighlights(decode_pdf);
int[][] showAllOnPage;
Vector_Rectangle_Int storageVector = new Vector_Rectangle_Int();
int lastPage = -1;
for (int k = 0; k != resultsList.getItems().size(); k++) {
final Object page = textPages.get(k);
if (page != null) {
final int currentPage = (Integer) page;
if (currentPage != lastPage) {
storageVector.trim();
showAllOnPage = storageVector.get();
for (int p = 0; p != showAllOnPage.length; p++) {
System.out.println(Arrays.toString(showAllOnPage[p]));
}
decode_pdf.getTextLines().addHighlights(showAllOnPage, true, lastPage);
lastPage = currentPage;
storageVector = new Vector_Rectangle_Int();
}
final Object highlight = textRectangles.get(k);
if (highlight instanceof int[]) {
storageVector.addElement((int[]) highlight);
}
if (highlight instanceof int[][]) {
final int[][] areas = (int[][]) highlight;
for (int i = 0; i != areas.length; i++) {
storageVector.addElement(areas[i]);
}
}
//decode_pdf.addToHighlightAreas(decode_pdf, storageVector, currentPage);
// }
}
}
storageVector.trim();
showAllOnPage = storageVector.get();
decode_pdf.getTextLines().addHighlights(showAllOnPage, true, lastPage);
} else {
// PdfHighlights.clearAllHighlights(decode_pdf);
final Object page = textPages.get(key);
final int currentPage = (Integer) page;
final Vector_Rectangle_Int storageVector = new Vector_Rectangle_Int();
// int[] scroll = null;
final Object highlight = textRectangles.get(key);
if (highlight instanceof int[]) {
storageVector.addElement((int[]) highlight);
//scroll = (int[]) highlight;
}
if (highlight instanceof int[][]) {
final int[][] areas = (int[][]) highlight;
// scroll = areas[0];
for (int i = 0; i != areas.length; i++) {
storageVector.addElement(areas[i]);
}
}
//Scroll.rectToHighlight(scroll, currentPage, decode_pdf);
storageVector.trim();
decode_pdf.getTextLines().addHighlights(storageVector.get(), true, currentPage);
//PdfHighlights.addToHighlightAreas(decode_pdf, storageVector, currentPage);
}
Platform.runLater(new Runnable() {
@Override
public void run() {
decode_pdf.repaintPane(commonValues.getCurrentPage());
currentGUI.scaleAndRotate();
}
});
}
}
}
//When page changes make sure only relevant navigation buttons are displayed
if (commonValues.getCurrentPage() == 1) {
currentGUI.getButtons().setBackNavigationButtonsEnabled(false);
} else {
currentGUI.getButtons().setBackNavigationButtonsEnabled(true);
}
if (commonValues.getCurrentPage() == decode_pdf.getPageCount()) {
currentGUI.getButtons().setForwardNavigationButtonsEnabled(false);
} else {
currentGUI.getButtons().setForwardNavigationButtonsEnabled(true);
}
}
});
//setup searching
searchButton.setOnAction(new EventHandler() {
@Override
public void handle(final ActionEvent e) {
if (!isSearch) {
try {
searchTypeParameters = SearchType.DEFAULT;
if (wholeWordsOnlyBox.isSelected()) {
searchTypeParameters |= SearchType.WHOLE_WORDS_ONLY;
}
if (caseSensitiveBox.isSelected()) {
searchTypeParameters |= SearchType.CASE_SENSITIVE;
}
if (multiLineBox.isSelected()) {
searchTypeParameters |= SearchType.MUTLI_LINE_RESULTS;
}
if (highlightAll.isSelected()) {
searchTypeParameters |= SearchType.HIGHLIGHT_ALL_RESULTS;
}
if (useRegEx.isSelected()) {
searchTypeParameters |= SearchType.USE_REGULAR_EXPRESSIONS;
}
if (searchHighlightedOnly.isSelected()) {
searchTypeParameters |= SearchType.SEARCH_HIGHLIGHTS_ONLY;
}
final String textToFind = searchText.getText().trim();
if (searchType.getValue() == searchType.getItems().get(0)) { // find exact word or phrase
searchTerms = new String[]{textToFind};
} else { // match any of the words
searchTerms = textToFind.split(" ");
for (int i = 0; i < searchTerms.length; i++) {
searchTerms[i] = searchTerms[i].trim();
}
}
singlePageSearch = !searchAll.isSelected();
searchText();
} catch (final Exception e1) {
e1.printStackTrace();
}
} else {
requestInterupt = true;
isSearch = false;
searchButton.setText(Messages.getMessage("PdfViewerSearch.Button"));
}
((JavaFxGUI)currentGUI).getPdfDecoder().requestFocus();
}
});
searchText.selectAll();
deleteOnClick = true;
searchText.setOnKeyPressed(new EventHandler() {
@Override
public void handle(final KeyEvent e) {
currentGUI.getButtons().getButton(Commands.NEXTRESULT).setEnabled(false);
currentGUI.getButtons().getButton(Commands.PREVIOUSRESULT).setEnabled(false);
if (e.getCode() == KeyCode.ENTER) {
if (!decode_pdf.isOpen()) {
currentGUI.showMessageDialog("File must be open before you can search.");
} else {
try {
isSearch = false;
searchTypeParameters = SearchType.DEFAULT;
if (wholeWordsOnlyBox.isSelected()) {
searchTypeParameters |= SearchType.WHOLE_WORDS_ONLY;
}
if (caseSensitiveBox.isSelected()) {
searchTypeParameters |= SearchType.CASE_SENSITIVE;
}
if (multiLineBox.isSelected()) {
searchTypeParameters |= SearchType.MUTLI_LINE_RESULTS;
}
if (highlightAll.isSelected()) {
searchTypeParameters |= SearchType.HIGHLIGHT_ALL_RESULTS;
}
if (useRegEx.isSelected()) {
searchTypeParameters |= SearchType.USE_REGULAR_EXPRESSIONS;
}
if (searchHighlightedOnly.isSelected()) {
searchTypeParameters |= SearchType.SEARCH_HIGHLIGHTS_ONLY;
}
final String textToFind = searchText.getText().trim();
if (searchType.getValue() == searchType.getItems().get(0)) { // find exact word or phrase
searchTerms = new String[]{textToFind};
} else { // match any of the words
searchTerms = textToFind.split(" ");
for (int i = 0; i < searchTerms.length; i++) {
searchTerms[i] = searchTerms[i].trim();
}
}
singlePageSearch = !searchAll.isSelected();
searchText();
((JavaFxGUI)currentGUI).getPdfDecoder().requestFocus();
} catch (final Exception e1) {
e1.printStackTrace();
}
}
}
}
});
searchText.focusedProperty().addListener(new ChangeListener()
{
@Override
public void changed(final ObservableValue extends Boolean> arg0, final Boolean oldPropertyValue, final Boolean newPropertyValue)
{
if (newPropertyValue && deleteOnClick) //focus gained
{
deleteOnClick = false;
searchText.setText("");
}
else if(searchText.getText().isEmpty()) //focus lost
{
searchText.setText(defaultMessage);
deleteOnClick = true;
}
}
});
if (style == SEARCH_EXTERNAL_WINDOW || style == SEARCH_TABBED_PANE) {
if(GUI.debugFX)
{
System.err.println("Implementation of tab bar not here yet for JavaFX");
}
/**
* Finalise the Stage, add items and scene.
*/
final BorderPane bp = new BorderPane();
contentVB = new VBox();
contentVB.getChildren().addAll(nav,resultsList, advancedPanel);
bp.setCenter(contentVB);
final Scene scene = new Scene(bp);
this.setScene(scene);
//
// if (style == SEARCH_EXTERNAL_WINDOW) {
// Code here which positions the External Window to the right
// next to the main viewer window.
// }
// searchAll.setFocusable(false);
//
// searchText.grabFocus();
} else {
//Whole Panel not used, take what is needed
currentGUI.setSearchText(searchText);
}
}
}
public VBox getContentVB(){
return contentVB;
}
@Override
public void removeSearchWindow(final boolean justHide) {
this.close();
if (isSetup && !justHide) {
if (listModel != null) {
listModel.clear();
}
itemFoundCount = 0;
isSearch = false;
}
//lose any highlights and force redraw with non-existent box
if (decode_pdf != null) {
decode_pdf.getTextLines().clearHighlights();
decode_pdf.repaintPane(commonValues.getCurrentPage());
}
}
/**
* Reset search text and menu bar buttons when opening new page
*/
@Override
public void resetSearchWindow(){
if(isSetup){
searchText.setText(defaultMessage);
deleteOnClick=true;
if(hasSearched){
// resultsList = null;
currentGUI.getButtons().getButton(Commands.NEXTRESULT).setEnabled(false);
currentGUI.getButtons().getButton(Commands.PREVIOUSRESULT).setEnabled(false);
hasSearched = false;
}
decode_pdf.requestFocus();
}
}
@Override
public GUISearchList getResults() {
return resultsList;
}
@Override
public GUISearchList getResults(final int page) {
usingMenuBarSearch = style==SEARCH_MENU_BAR;
if(page !=lastPage && usingMenuBarSearch){
try {
searchKey++;
if(searchKey>3000) {
searchKey = 0;
}
clearCurrentResults();
searchPage(page, searchKey, listModel);
} catch (final Exception e) {
e.printStackTrace();
}
}
return resultsList;
}
@Override
public Map getTextRectangles() {
return Collections.unmodifiableMap(textRectangles);
}
@Override
public int getViewStyle() {
return style;
}
@Override
public void setViewStyle(final int i) {
style = i;
}
@Override
public int getFirstPageWithResults() {
return firstPageWithResults;
}
@Override
public void setWholeWords(final boolean wholeWords) {
wholeWordsOnlyBox.setSelected(wholeWords);
}
@Override
public void setCaseSensitive(final boolean caseSensitive) {
caseSensitiveBox.setSelected(caseSensitive);
}
@Override
public void setMultiLine(final boolean multiLine) {
multiLineBox.setSelected(multiLine);
}
@Override
public void setSearchText(final String s) {
searchText.setText(s);
}
//@Override
// public void setSearchHighlightsOnly(boolean highlightOnly){
// searchHighlightedOnly.setSelected(highlightOnly);
//}
private void searchText() throws Exception{
//Flag is we are using menu bar search
usingMenuBarSearch = style == SEARCH_MENU_BAR;
//Alter searchKey so the update thread knows not to update
searchKey++;
//Reset last page searched flag.
lastPage=-1;
/*
* To prevent the chance of hitting the maximum value of searchKey
* we should reset long after a value large enough to guarantee
* any thread using a searchKey of 0 is closed.
*/
if(searchKey>3000) {
searchKey = 0;
}
//Cancel a search if currently exists
if(searchThread!=null && searchThread.isAlive()){
//Call for search to finish
endSearch = true;
searchThread.interrupt();
while (searchThread.isAlive()) {
//Wait for search to end
try {
Thread.sleep(5000);
} catch (Exception e) {
LogWriter.writeLog("Attempting to set propeties values " + e);
}
}
endSearch = false;
}
if(!usingMenuBarSearch && (searchTypeParameters & SearchType.SEARCH_HIGHLIGHTS_ONLY) == SearchType.SEARCH_HIGHLIGHTS_ONLY){
searchAreas = decode_pdf.getTextLines().getAllHighlights();
}else{
searchAreas = null;
}
clearCurrentResults();
searchThread = new Thread(searchRunner);
searchThread.start();
// Platform.runLater(searchThread);
}
private void clearCurrentResults(){
listModel.clear();
resultsList.getItems().clear();
textPages.clear();
textRectangles.clear();
itemFoundCount = 0;
decode_pdf.getTextLines().clearHighlights();
}
/**
* Performs the currently set up search on the given page
*
* @param page :: Page to be searched with the currently set term and
* settings
* @param currentKey :: The current search key, used to control results
* update when search ends
* @return True if search routine should continue
*/
private boolean searchPage(final int page, final int currentKey, final ObservableList resultListModel) throws Exception{
final PdfPageData currentPageData = decode_pdf.getPdfPageData();
final int x1 = currentPageData.getMediaBoxX(page);
final int x2 = currentPageData.getMediaBoxWidth(page) + x1;
final int y2 = currentPageData.getMediaBoxY(page);
final int y1 = currentPageData.getMediaBoxHeight(page) + y2;
return searchPage(page, x1, y1, x2, y2, currentKey, resultListModel);
}
/**
* Performs the currently set up search on the given page
* @param x1 the left x cord
* @param y1 the upper y cord
* @param x2 the right x cord
* @param y2 the lower y cord
* @param page :: Page to be searched with the currently set term and settings
* @param currentKey :: The current search key, used to control results update when search ends
* @param model :: [AWI] The list model to append the search results to
* @return True if search routine should continue
*/
private boolean searchPage(final int page, final int x1, final int y1, final int x2, final int y2, final int currentKey, final ObservableList resultListModel) throws Exception {
final PdfGroupingAlgorithms grouping;
final PdfPageData pageSize = decode_pdf.getPdfPageData();
if (page == commonValues.getCurrentPage()) {
grouping = decode_pdf.getGroupingObject();
} else {
decode_pdf.decodePageInBackground(page);
grouping = decode_pdf.getBackgroundGroupingObject();
}
// // set size
// int x1 = pageSize.getCropBoxX(page);
// int x2 = pageSize.getCropBoxWidth(page);
// int y1 = pageSize.getCropBoxY(page);
// int y2 = pageSize.getCropBoxHeight(page);
final SearchListener listener = new DefaultSearchListener();
// tell JPedal we want teasers
grouping.generateTeasers();
//allow us to add options
grouping.setIncludeHTML(false);
//Set search term in results list
resultsList.setSearchTerm(searchText.getText().trim());
final SortedMap highlightsWithTeasers = grouping.findTextWithinInAreaWithTeasers(x1, y1, x2, y2, pageSize.getRotation(page), page, searchTerms, searchTypeParameters, listener);
/**
* update data structures with results from this page
*/
if (!highlightsWithTeasers.isEmpty()) {
itemFoundCount += highlightsWithTeasers.size();
for (final Object o : highlightsWithTeasers.entrySet()) {
final Map.Entry e = (Map.Entry) o;
/*highlight is a rectangle or a rectangle[]*/
final Object highlight = e.getKey();
final String teaser = (String) e.getValue();
if(currentKey == searchKey){
resultListModel.add(teaser);
}
final Integer key = textRectangles.size();
textRectangles.put(key, highlight);
textPages.put(key, page);
}
}
lastPage = page;
//Ending search now
return !endSearch;
}
//Flag to control if we update search results during search or at the end
boolean updateListDuringSearch = true;
@Override
public void setUpdateListDuringSearch(final boolean updateListDuringSearch) {
this.updateListDuringSearch = updateListDuringSearch;
}
@Override
public void dispose(){
//Added as needed for swing. No code yet
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy