diff --git a/pom.xml b/pom.xml
index cde38760..51917fe7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,11 @@
kernel
${itext.version}
+
+ com.itextpdf
+ search
+ ${itext.version}
+
org.dom4j
dom4j
@@ -309,18 +314,6 @@
sh.tak.appbundler
appbundle-maven-plugin
1.2.0
-
-
- org.codehaus.plexus
- plexus-archiver
- 3.6.0
-
-
- org.apache.velocity
- velocity-tools
- 2.0
-
-
package
@@ -329,6 +322,18 @@
+
+
+ org.apache.velocity
+ velocity-tools
+ 2.0
+
+
+ org.codehaus.plexus
+ plexus-archiver
+ 3.6.0
+
+
com.itextpdf.rups.RupsLauncher
Info.plist
@@ -340,4 +345,4 @@
-
\ No newline at end of file
+
diff --git a/src/main/java/com/itextpdf/rups/RupsConfiguration.java b/src/main/java/com/itextpdf/rups/RupsConfiguration.java
index 3cc23551..e7253c3d 100644
--- a/src/main/java/com/itextpdf/rups/RupsConfiguration.java
+++ b/src/main/java/com/itextpdf/rups/RupsConfiguration.java
@@ -74,21 +74,27 @@ public enum RupsConfiguration {
INSTANCE;
private static final String DEFAULT_CONFIG_PATH = "/config/default.properties";
+ private static final String ICON_CONFIG_PATH = "/config/icon.properties";
private static final String DEFAULT_HOME_VALUE = "home";
private static final String CLOSE_OPERATION_KEY = "ui.closeoperation";
private static final String DUPLICATE_OPEN_FILES_KEY = "rups.duplicatefiles";
private static final String HOME_FOLDER_KEY = "user.home";
private static final String LOCALE_KEY = "user.locale";
private static final String LOOK_AND_FEEL_KEY = "ui.lookandfeel";
+ private static final String ICON_KEY = "ui.lookandfeel";
private final Preferences systemPreferences;
private final Properties defaultProperties;
private final Properties temporaryProperties;
+ private final Properties iconProperties;
+
+
RupsConfiguration() {
this.defaultProperties = loadDefaultProperties();
this.temporaryProperties = new Properties();
this.systemPreferences = Preferences.userNodeForPackage(RupsConfiguration.class);
+ this.iconProperties = loadIconProperties();
initializeSystemDefaults(this.defaultProperties, this.systemPreferences);
}
@@ -307,6 +313,22 @@ private Properties loadDefaultProperties() {
return properties;
}
+ private Properties loadIconProperties() {
+ final InputStream resourceAsStream = RupsConfiguration.class.getResourceAsStream(ICON_CONFIG_PATH);
+ final Properties properties = new Properties();
+
+ if (resourceAsStream != null) {
+ try {
+ properties.load(resourceAsStream);
+ resourceAsStream.close();
+ } catch (IOException e) {
+ LoggerHelper.error(Language.ERROR_LOADING_ICON_DEFINITIONS.getString(), e, RupsConfiguration.class);
+ }
+ }
+
+ return properties;
+ }
+
private void initializeSystemDefaults(Properties defaultProperties, Preferences systemPreferences) {
try {
final String[] keys = systemPreferences.keys();
@@ -337,4 +359,8 @@ private String getValueFromSystemPreferences(String key, String defaultValue) {
private String getValueFromSystemPreferences(String key) {
return this.systemPreferences.get(key, this.defaultProperties.getProperty(key));
}
-}
+
+ public String getIconFor(String key){
+ return this.iconProperties.getProperty(key, "default");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/itextpdf/rups/controller/IRupsController.java b/src/main/java/com/itextpdf/rups/controller/IRupsController.java
index 1c3949a9..78217717 100644
--- a/src/main/java/com/itextpdf/rups/controller/IRupsController.java
+++ b/src/main/java/com/itextpdf/rups/controller/IRupsController.java
@@ -42,6 +42,8 @@ This file is part of the iText (R) project.
*/
package com.itextpdf.rups.controller;
+import com.itextpdf.kernel.pdf.PdfObject;
+import com.itextpdf.search.ISearchHandler;
import com.itextpdf.rups.model.PdfFile;
import java.awt.Component;
diff --git a/src/main/java/com/itextpdf/rups/controller/RupsController.java b/src/main/java/com/itextpdf/rups/controller/RupsController.java
index 5a6a5103..a8e05990 100644
--- a/src/main/java/com/itextpdf/rups/controller/RupsController.java
+++ b/src/main/java/com/itextpdf/rups/controller/RupsController.java
@@ -43,6 +43,7 @@ This file is part of the iText (R) project.
package com.itextpdf.rups.controller;
import com.itextpdf.rups.RupsConfiguration;
+import com.itextpdf.search.ISearchHandler;
import com.itextpdf.rups.event.AllFilesClosedEvent;
import com.itextpdf.rups.event.OpenFileEvent;
import com.itextpdf.rups.event.RupsEvent;
@@ -77,6 +78,8 @@ public class RupsController extends Observable
public RupsController(Dimension dimension, RupsTabbedPane rupsTabbedPane) {
this.rupsTabbedPane = rupsTabbedPane;
+ //TODO: SearchHandler -> TabbedPane -> InstanceController, SearchHandler -> SearchBar.handler
+
this.dimension = dimension;
}
@@ -90,6 +93,10 @@ public Component getMasterComponent() {
return rupsTabbedPane.getJTabbedPane();
}
+ public ISearchHandler getSearchHandler(){
+ return rupsTabbedPane.getCurrentController().getSearchHandler();
+ }
+
@Override
public final void update(Observable o, Object arg) {
//Events that have come from non observable classes: ObjectLoader and FileChooserAction
@@ -127,6 +134,7 @@ public final void closeCurrentFile() {
}
}
+
@Override
public final PdfFile getCurrentFile() {
return this.rupsTabbedPane.getCurrentFile();
diff --git a/src/main/java/com/itextpdf/rups/controller/RupsInstanceController.java b/src/main/java/com/itextpdf/rups/controller/RupsInstanceController.java
index b4a2b3d7..fa9cdeac 100644
--- a/src/main/java/com/itextpdf/rups/controller/RupsInstanceController.java
+++ b/src/main/java/com/itextpdf/rups/controller/RupsInstanceController.java
@@ -46,6 +46,8 @@ This file is part of the iText (R) project.
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.utils.CompareTool;
+import com.itextpdf.search.ISearchHandler;
+import com.itextpdf.rups.controller.search.PdfSearchHandler;
import com.itextpdf.rups.event.CloseDocumentEvent;
import com.itextpdf.rups.event.PostCompareEvent;
import com.itextpdf.rups.event.RupsEvent;
@@ -57,6 +59,8 @@ This file is part of the iText (R) project.
import com.itextpdf.rups.view.Console;
import com.itextpdf.rups.view.Language;
import com.itextpdf.rups.view.PageSelectionListener;
+import com.itextpdf.rups.view.RupsPanel;
+import com.itextpdf.rups.view.RupsSearchBar;
import com.itextpdf.rups.view.contextmenu.ConsoleContextMenu;
import com.itextpdf.rups.view.contextmenu.ContextMenuMouseListener;
import com.itextpdf.rups.view.itext.treenodes.PdfObjectTreeNode;
@@ -105,6 +109,9 @@ public class RupsInstanceController extends Observable
*/
private final PdfReaderController readerController;
+ private final ISearchHandler searchHandler;
+
+ private RupsSearchBar searchBar;
/**
* Contains all other components: the page panel, the outline tree, etc.
*/
@@ -134,6 +141,13 @@ public RupsInstanceController(Dimension dimension, JPanel owner) {
readerController = new PdfReaderController(this, this);
addObserver(readerController);
+ searchHandler = new PdfSearchHandler();
+ searchBar = RupsSearchBar.getSearchBar(readerController.pdfTree);
+
+ //TODO: Find a neater way of identifying document section in focus.
+ readerController.getPdfTree().addTreeSelectionListener((TreeSelectionListener) searchHandler);
+ searchBar.setSearchHandler(((RupsPanel) owner).getRupsSearchHandler());
+
// creating the master component
masterComponent = new JSplitPane();
masterComponent.setOrientation(JSplitPane.VERTICAL_SPLIT);
@@ -158,6 +172,7 @@ public RupsInstanceController(Dimension dimension, JPanel owner) {
info.add(readerController.getObjectPanel(), JSplitPane.LEFT);
final JTabbedPane editorPane = readerController.getEditorTabs();
final JScrollPane cons = new JScrollPane(console.getTextArea());
+
console.getTextArea().addMouseListener(
new ContextMenuMouseListener(ConsoleContextMenu.getPopupMenu(console.getTextArea()),
console.getTextArea()));
@@ -362,6 +377,10 @@ public void valueChanged(TreeSelectionEvent evt) {
}
}
+ public ISearchHandler getSearchHandler() {
+ return searchHandler;
+ }
+
// page navigation
@Override
diff --git a/src/main/java/com/itextpdf/rups/controller/search/PdfSearchHandler.java b/src/main/java/com/itextpdf/rups/controller/search/PdfSearchHandler.java
new file mode 100644
index 00000000..6143d73e
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/controller/search/PdfSearchHandler.java
@@ -0,0 +1,75 @@
+package com.itextpdf.rups.controller.search;
+
+import com.itextpdf.kernel.pdf.PdfDocument;
+import com.itextpdf.kernel.pdf.PdfIndirectReference;
+import com.itextpdf.kernel.pdf.PdfObject;
+import com.itextpdf.search.model.ESearchScope;
+import com.itextpdf.search.model.ISearchFilter;
+import com.itextpdf.search.model.ISearchResult;
+import com.itextpdf.search.model.SearchContext;
+
+import javax.swing.event.TreeSelectionEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+public class PdfSearchHandler extends RupsSearchHandler {
+
+ Map> contexts;
+
+ PdfIndirectReference currentTarget;
+
+ public PdfSearchHandler(){
+ super();
+ contexts = new HashMap<>();
+ }
+
+
+ @Override
+ public ISearchResult find(SearchContext searchContext, ISearchFilter filter) {
+ if((null == filter || (null == searchContext.getSearchScope())))
+ return null; //TODO: Replace this.
+
+ switch(searchContext.getSearchScope()) {
+ case ALL_DOCUMENTS:
+ break;
+ case DOCUMENT:
+ PdfDocument testdoc = searchContext.getTarget().getIndirectReference().getDocument();
+ break;
+ default:
+ case SELECTION:
+ PdfObject testobj = searchContext.getTarget().getIndirectReference().getRefersTo(true);
+ }
+ return null;
+ }
+
+ public ISearchFilter getNewFilter() {
+ return new PdfStreamSearchFilter();
+ }
+
+ @Override
+ public SearchContext getNewContext(ESearchScope itemScope){
+ SearchContext newContext = super.getNewContext();
+ newContext.setTarget(getCurrentTarget());
+ Map scopeContexts = contexts.getOrDefault(currentTarget, new HashMap());
+ scopeContexts.put(itemScope, newContext);
+ contexts.put(getCurrentTarget(), scopeContexts);
+ return getContext(currentTarget, ESearchScope.SELECTION);
+
+ }
+
+ @Override
+ public SearchContext getContext(PdfIndirectReference currentTarget, ESearchScope selectedItem) {
+ Map scopeContexts = contexts.getOrDefault(currentTarget, new HashMap());
+ return scopeContexts.getOrDefault(currentTarget,getNewContext(selectedItem));
+ }
+
+ @Override
+ public PdfIndirectReference getCurrentTarget() {
+ return currentTarget;
+ }
+
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+
+ }
+}
diff --git a/src/main/java/com/itextpdf/rups/controller/search/PdfStreamSearchFilter.java b/src/main/java/com/itextpdf/rups/controller/search/PdfStreamSearchFilter.java
new file mode 100644
index 00000000..0d9d315e
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/controller/search/PdfStreamSearchFilter.java
@@ -0,0 +1,35 @@
+package com.itextpdf.rups.controller.search;
+
+import com.itextpdf.search.model.ESearchOptions;
+import com.itextpdf.search.model.ISearchFilter;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class PdfStreamSearchFilter implements ISearchFilter {
+ String query = "";
+ ESearchOptions[] options = {};
+ @Override
+ public boolean setQuery(String inputQuery) {
+ //TODO: Properly Validate input...
+ if(null != inputQuery)
+ this.query = inputQuery;
+ return (null !=query) && (query == inputQuery);
+ }
+
+ @Override
+ public boolean setOptions(ESearchOptions[] searchOptions) {
+ options = searchOptions;
+ return (null != options) && (options == searchOptions);
+ }
+
+ @Override
+ public String getQuery() {
+ return query;
+ }
+
+ @Override
+ public Collection getOptions() {
+ return Arrays.asList(options);
+ }
+}
diff --git a/src/main/java/com/itextpdf/rups/controller/search/RupsSearchHandler.java b/src/main/java/com/itextpdf/rups/controller/search/RupsSearchHandler.java
new file mode 100644
index 00000000..93e8ed51
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/controller/search/RupsSearchHandler.java
@@ -0,0 +1,57 @@
+package com.itextpdf.rups.controller.search;
+
+import com.itextpdf.kernel.pdf.PdfIndirectReference;
+import com.itextpdf.kernel.pdf.PdfObject;
+import com.itextpdf.rups.view.RupsPanel;
+import com.itextpdf.search.model.ESearchOptions;
+import com.itextpdf.search.model.ESearchScope;
+import com.itextpdf.search.model.ISearchFilter;
+import com.itextpdf.search.ISearchHandler;
+import com.itextpdf.search.model.ISearchResult;
+import com.itextpdf.search.model.SearchContext;
+import com.itextpdf.search.SearchHandler;
+
+import javax.swing.event.TreeSelectionListener;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+
+public abstract class RupsSearchHandler extends SearchHandler implements TreeSelectionListener {
+ private static ISearchHandler INSTANCE;
+
+ public RupsSearchHandler() {
+ if (null == INSTANCE) {
+ INSTANCE = this;
+ }
+
+ }
+
+ @Override
+ public ISearchResult find(SearchContext context, ISearchFilter filter) {
+ AtomicBoolean case_sensitive = new AtomicBoolean(false);
+ AtomicBoolean regex = new AtomicBoolean(false);
+ AtomicBoolean word = new AtomicBoolean(false);
+
+ filter.getOptions().forEach((ESearchOptions option) -> {
+ case_sensitive.set(case_sensitive.get() || option == ESearchOptions.CASE_SENSITIVE);
+ regex.set((!word.get()) && (regex.get() || option == ESearchOptions.REGEX));
+ word.set((!regex.get()) && (word.get() || option == ESearchOptions.REGEX));
+ });
+
+ if(regex.get()){
+ // Regex Evaluation
+ } else if (word.get()) {
+ // Whole Word Matches only
+ } else {
+ // Default Search
+ }
+ // new ThreadedSearch
+
+ return null;
+ }
+
+ public static ISearchHandler getInstance(RupsPanel rupsPanel) {
+ return INSTANCE;
+ }
+
+ public abstract SearchContext getNewContext(ESearchScope itemScope);
+}
diff --git a/src/main/java/com/itextpdf/rups/view/Language.java b/src/main/java/com/itextpdf/rups/view/Language.java
index 0a54ac42..3e748339 100644
--- a/src/main/java/com/itextpdf/rups/view/Language.java
+++ b/src/main/java/com/itextpdf/rups/view/Language.java
@@ -111,6 +111,7 @@ public enum Language {
ERROR_INITIALIZING_SETTINGS,
ERROR_KEY_IS_NOT_NAME,
ERROR_LOADING_DEFAULT_SETTINGS,
+ ERROR_LOADING_ICON_DEFINITIONS,
ERROR_LOADING_IMAGE,
ERROR_LOADING_XFA,
ERROR_LOOK_AND_FEEL,
diff --git a/src/main/java/com/itextpdf/rups/view/RupsMenuBar.java b/src/main/java/com/itextpdf/rups/view/RupsMenuBar.java
index fe87b95f..94a190db 100644
--- a/src/main/java/com/itextpdf/rups/view/RupsMenuBar.java
+++ b/src/main/java/com/itextpdf/rups/view/RupsMenuBar.java
@@ -52,16 +52,13 @@ This file is part of the iText (R) project.
import com.itextpdf.rups.io.OpenInViewerAction;
import com.itextpdf.rups.io.filters.PdfFilter;
+import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
-import javax.swing.Box;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.KeyStroke;
+import javax.swing.*;
public class RupsMenuBar extends JMenuBar implements Observer {
/**
@@ -93,6 +90,8 @@ public class RupsMenuBar extends JMenuBar implements Observer {
*/
private final PreferencesWindow preferencesWindow;
+ private final RupsSearchBar searchBar;
+
/**
* Creates a JMenuBar.
*/
@@ -109,6 +108,9 @@ public RupsMenuBar(RupsController controller) {
new FileCompareAction(controller, PdfFilter.INSTANCE, controller.getMasterComponent());
final JMenu file = new JMenu(Language.MENU_BAR_FILE.getString());
+
+ searchBar = new RupsSearchBar();
+
addItem(file, Language.MENU_BAR_OPEN.getString(), fileOpenAction,
KeyStroke.getKeyStroke('O', InputEvent.CTRL_DOWN_MASK));
addItem(file, Language.MENU_BAR_CLOSE.getString(), new FileCloseAction(controller),
@@ -129,6 +131,15 @@ public RupsMenuBar(RupsController controller) {
preferencesWindow.show(controller.getMasterComponent());
}
);
+ addItem(edit, "Find", e -> {
+ Window masterComponent = SwingUtilities.getWindowAncestor((JComponent)controller.getMasterComponent());
+ Component target = masterComponent.getFocusOwner();
+ if(target instanceof JComponent) {
+ searchBar.setSearchHandler(controller.getSearchHandler());
+ searchBar.setTarget((JComponent) target);
+ }
+ },
+ KeyStroke.getKeyStroke('F', InputEvent.CTRL_DOWN_MASK));
add(edit);
add(Box.createGlue());
diff --git a/src/main/java/com/itextpdf/rups/view/RupsPanel.java b/src/main/java/com/itextpdf/rups/view/RupsPanel.java
index 91a3a3c0..a625b187 100644
--- a/src/main/java/com/itextpdf/rups/view/RupsPanel.java
+++ b/src/main/java/com/itextpdf/rups/view/RupsPanel.java
@@ -43,6 +43,7 @@ This file is part of the iText (R) project.
package com.itextpdf.rups.view;
import com.itextpdf.rups.controller.RupsInstanceController;
+import com.itextpdf.rups.controller.search.RupsSearchHandler;
import com.itextpdf.rups.model.PdfFile;
import java.awt.BorderLayout;
@@ -55,6 +56,7 @@ This file is part of the iText (R) project.
public class RupsPanel extends JPanel {
private RupsInstanceController rupsInstanceController;
+ private RupsSearchHandler rupsSearchHandler;
public RupsPanel() {
setLayout(new BorderLayout());
@@ -71,4 +73,12 @@ public PdfFile getPdfFile() {
public RupsInstanceController getRupsInstanceController() {
return this.rupsInstanceController;
}
+
+ public void setSearchContext(RupsSearchHandler instance) {
+ this.rupsSearchHandler = instance;
+ }
+
+ public RupsSearchHandler getRupsSearchHandler() {
+ return rupsSearchHandler;
+ }
}
diff --git a/src/main/java/com/itextpdf/rups/view/RupsSearchBar.java b/src/main/java/com/itextpdf/rups/view/RupsSearchBar.java
new file mode 100644
index 00000000..7bae7e86
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/view/RupsSearchBar.java
@@ -0,0 +1,278 @@
+package com.itextpdf.rups.view;
+
+import com.itextpdf.kernel.pdf.PdfIndirectReference;
+import com.itextpdf.rups.RupsConfiguration;
+import com.itextpdf.search.model.ESearchOptions;
+import com.itextpdf.search.model.ESearchScope;
+import com.itextpdf.search.model.ISearchFilter;
+import com.itextpdf.search.ISearchHandler;
+import com.itextpdf.search.model.SearchContext;
+import com.itextpdf.rups.view.icons.IconDropdownRenderer;
+import com.itextpdf.rups.view.icons.IconFetcher;
+
+import javax.swing.*;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RupsSearchBar extends JDialog /*implements TreeSelectionListener */{
+
+ //TODO:
+ // Move tree listener to search bar.
+ // Track SearchInstance instances rather than search bar instances
+ // -> re-fill in the search bar details from instance when a node is re-selected
+ // Make search handler more atomic
+
+ static private RupsSearchBar INSTANCE;
+ private JComboBox scopeDropdown = new JComboBox<>();
+ private AncestorListener ancestorListener;
+ private FocusListener focusListener;
+ private KeyListener keyListener;
+
+ JComponent targetComponent;
+ PdfIndirectReference targetObject;
+ JTextField searchBox;
+ JButton caseSensitivity;
+ JRadioButton wordSearch;
+ JRadioButton regexSearch;
+ ISearchHandler searchHandler;
+
+ private int width;
+ private int height;
+
+ public RupsSearchBar(){
+// super(SwingUtilities.getWindowAncestor(component));
+ super();
+
+// this.targetComponent = component;
+ //TODO: Move < Instance>> pairing to either an internal Map or to the controller
+ this.setUndecorated(true);
+ this.setupListeners();
+ this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+ this.setLayout(new BorderLayout());
+ this.setAlwaysOnTop(true);
+ JPanel searchControls = new JPanel();
+ searchControls.setLayout(new BorderLayout());
+
+ JPanel searchOptions = new JPanel();
+ searchOptions.setLayout(new FlowLayout());
+
+ JScrollPane searchResults = new JScrollPane();
+ JTextField search = new JTextField("");
+ search.setName("SearchInput");
+ this.searchBox = search;
+
+ searchControls.add(searchBox, BorderLayout.WEST);
+
+ JButton caseSwitch = new JButton(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.options.case_sensitivity")));
+ caseSwitch.setName("CaseSensitive");
+ caseSwitch.setToolTipText(ESearchOptions.CASE_SENSITIVE.getTooltip());
+ caseSensitivity = caseSwitch;
+
+ searchOptions.add(caseSensitivity);
+
+ JRadioButtonMenuItem wordOrRegex = new JRadioButtonMenuItem();
+
+ JRadioButton word = new JRadioButton(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.options.word")));
+ word.setName("Word");
+ word.setToolTipText(ESearchOptions.WORD.getTooltip());
+ wordSearch = word;
+
+ JRadioButton regex = new JRadioButton(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.options.regex")));
+ regex.setName("Regex");
+ regex.setToolTipText(ESearchOptions.REGEX.getTooltip());
+ regexSearch = regex;
+
+ searchOptions.add(wordSearch);
+ searchOptions.add(regexSearch);
+
+// scopeDropdown.setIcon(IconFetcher.getIcon("magnifier.png"));
+
+ JLabel localScope = new JLabel();
+ localScope.setIcon(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.scope.selection")));
+ localScope.setToolTipText(ESearchScope.SELECTION.getTooltip());
+ localScope.setVisible(true);
+ scopeDropdown.addItem(ESearchScope.SELECTION);
+
+ JLabel documentScope = new JLabel();
+ documentScope.setIcon(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.scope.document")));
+ documentScope.setToolTipText(ESearchScope.DOCUMENT.getTooltip());
+ documentScope.setVisible(true);
+ scopeDropdown.addItem(ESearchScope.DOCUMENT);
+
+ JLabel allDocumentsScope = new JLabel();
+ allDocumentsScope.setIcon(IconFetcher.getIcon(RupsConfiguration.INSTANCE.getIconFor("rups.search.scope.all_documents")));
+ allDocumentsScope.setToolTipText(ESearchScope.ALL_DOCUMENTS.getTooltip());
+ allDocumentsScope.setVisible(true);
+ scopeDropdown.addItem(ESearchScope.ALL_DOCUMENTS);
+
+ scopeDropdown.setSelectedIndex(0);
+
+ scopeDropdown.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ scopeDropdown.setToolTipText(((ESearchScope)scopeDropdown.getSelectedItem()).getTooltip());
+ }
+ });
+
+ scopeDropdown.setToolTipText(((ESearchScope) scopeDropdown.getSelectedItem()).getTooltip());
+
+ scopeDropdown.setRenderer(new IconDropdownRenderer());
+
+ searchOptions.add(scopeDropdown);
+
+ searchControls.add(searchOptions, BorderLayout.EAST);
+ this.add(searchControls,BorderLayout.NORTH);
+ this.add(searchResults,BorderLayout.CENTER);
+
+
+ this.searchBox.addKeyListener(keyListener);
+
+ }
+
+ private void setupListeners() {
+ // Key Listener
+ this.keyListener = new KeyListener() {
+ @Override
+ public void keyTyped(KeyEvent e) {
+ if (e.getKeyChar() != KeyEvent.VK_ENTER)
+ return;
+// searchHandler.setSearchTarget(,(ESearchScope) INSTANCES.get(target).scopeDropdown.getSelectedItem());
+ SearchContext currentContext = searchHandler.getContext(searchHandler.getCurrentTarget(), (ESearchScope) scopeDropdown.getSelectedItem());
+ ISearchFilter query = currentContext.getNewFilter();
+ query.setQuery(searchBox.getText());
+
+ List searchOptions = new ArrayList();
+ if (caseSensitivity.isSelected())
+ searchOptions.add(ESearchOptions.CASE_SENSITIVE);
+ if (wordSearch.getModel().isSelected())
+ searchOptions.add(ESearchOptions.WORD);
+ if (regexSearch.getModel().isSelected())
+ searchOptions.add(ESearchOptions.REGEX);
+ ESearchOptions[] resultingOptions = new ESearchOptions[searchOptions.size()];
+ searchOptions.toArray(resultingOptions);
+ query.setOptions(resultingOptions);
+// (ESearchScope) scopeDropdown.getSelectedItem())
+
+ //TODO - Fix this being Null.
+ targetObject = searchHandler.getCurrentTarget().getIndirectReference();
+
+ searchHandler.find(currentContext, query);
+ System.out.println("Rups SearchInstance Handler");
+ System.out.println(query.toString());
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {}
+
+ @Override
+ public void keyReleased(KeyEvent e) {}
+ };
+
+ // Focus Listener
+ this.focusListener = new FocusListener() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ System.out.println("Target Focus Gained.");
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ System.out.println("Target Focus Lost.");
+// INSTANCES.get(target).hideSearchBar(true);
+ }
+ };
+
+ // Ancestor Listener
+ this.ancestorListener = new AncestorListener() {
+ @Override
+ public void ancestorAdded(AncestorEvent event) {}
+
+ @Override
+ public void ancestorRemoved(AncestorEvent event) {
+ setTarget(null); // clean up old listeners but don't assign new ones
+ }
+
+ @Override
+ public void ancestorMoved(AncestorEvent event) {
+ setWindowPosition();
+ }
+ };
+ }
+
+ public void setTarget(JComponent newTarget) {
+ if (newTarget != this.targetComponent) {
+ if (this.targetComponent != null) {
+ this.targetComponent.removeAncestorListener(this.ancestorListener);
+ this.targetComponent.removeFocusListener(this.focusListener);
+ }
+ //TODO: remove listeners from old target
+ // Update the listeners to the new target
+ // Add the listeners to the new target
+ this.targetComponent = newTarget;
+// newTarget.getTopLevelAncestor();
+ }
+
+ if (this.targetComponent == null)
+ return;
+
+ this.targetComponent.addAncestorListener(ancestorListener);
+
+ this.targetComponent.addFocusListener(this.focusListener);
+
+// setWindowPosition();
+
+ this.width = /*500;//*/this.targetComponent.getSize().width;
+ this.height = 24;/*500;//*///searchBox.getHeight();
+ int fontWidth = searchBox.getFont().getSize();
+// int fontWidth = 18;
+ int buttonWidth = caseSensitivity.getWidth();
+ int colNum = (width - (3 * buttonWidth))/ fontWidth;
+ System.out.print("Column #: ");
+ System.out.println(colNum);
+ searchBox.setColumns(colNum);
+ searchBox.setLocation(1,0);
+ setWindowPosition();
+ INSTANCE.hideSearchBar(false);
+ }
+
+ private void setWindowPosition() {
+ Point targetLocation = targetComponent.getLocation();
+ SwingUtilities.convertPointToScreen(targetLocation, targetComponent);
+ setLocation(targetLocation);
+ setBounds(new Rectangle(targetLocation.x,targetLocation.y, width, height));
+ }
+
+ private void hideSearchBar(boolean hide){
+ setVisible(!hide);
+ setEnabled(!hide);
+ }
+
+ public static RupsSearchBar getSearchBar(JComponent component){
+ if(INSTANCE == null)
+ INSTANCE = new RupsSearchBar();
+ INSTANCE.setTarget(component);
+ return INSTANCE;
+ //TODO: Bring to Foreground.
+ //TODO: Hide on losing focus.
+ }
+
+// @Override
+// public void valueChanged(TreeSelectionEvent e) {
+// this.targetObject = ((PdfObjectTreeNode) e.getNewLeadSelectionPath().getLastPathComponent()).getPdfObject().getIndirectReference();
+// }
+ //TODO let SearchHandler determine focused object.
+
+ public void setSearchHandler(ISearchHandler searchHandler) {
+ this.searchHandler = searchHandler;
+ }
+}
diff --git a/src/main/java/com/itextpdf/rups/view/RupsTabbedPane.java b/src/main/java/com/itextpdf/rups/view/RupsTabbedPane.java
index b0525ecd..1ab6acaa 100644
--- a/src/main/java/com/itextpdf/rups/view/RupsTabbedPane.java
+++ b/src/main/java/com/itextpdf/rups/view/RupsTabbedPane.java
@@ -42,7 +42,10 @@ This file is part of the iText (R) project.
*/
package com.itextpdf.rups.view;
+import com.itextpdf.kernel.pdf.PdfObject;
import com.itextpdf.rups.controller.RupsInstanceController;
+import com.itextpdf.search.ISearchHandler;
+import com.itextpdf.rups.controller.search.RupsSearchHandler;
import com.itextpdf.rups.model.PdfFile;
import java.awt.Component;
@@ -76,9 +79,12 @@ public void openNewFile(File file, Dimension dimension, boolean readonly) {
this.jTabbedPane.removeTabAt(this.jTabbedPane.getSelectedIndex());
}
+ // TODO: Handle the propagation of SearchControllers out from this class...
+
RupsPanel rupsPanel = new RupsPanel();
RupsInstanceController rupsInstanceController = new RupsInstanceController(dimension, rupsPanel);
rupsPanel.setRupsInstanceController(rupsInstanceController);
+ rupsPanel.setSearchContext((RupsSearchHandler) RupsSearchHandler.getInstance(rupsPanel));
rupsInstanceController.loadFile(file, readonly);
this.jTabbedPane.addTab(file.getName(), null, rupsPanel);
this.jTabbedPane.setSelectedComponent(rupsPanel);
@@ -88,6 +94,7 @@ public void openNewFile(File file, Dimension dimension, boolean readonly) {
public boolean closeCurrentFile() {
boolean isLastTab = this.jTabbedPane.getTabCount() == 1;
+ //TODO: Remove any associated SearchBar Instances
this.jTabbedPane.removeTabAt(this.jTabbedPane.getSelectedIndex());
if (this.jTabbedPane.getTabCount() == 0) {
@@ -107,6 +114,10 @@ public void saveCurrentFile(File file) {
RupsPanel currentRupsPanel = (RupsPanel) this.jTabbedPane.getSelectedComponent();
currentRupsPanel.getRupsInstanceController().saveFile(file);
}
+ public RupsInstanceController getCurrentController() {
+ RupsPanel currentRupsPanel = (RupsPanel) this.jTabbedPane.getSelectedComponent();
+ return currentRupsPanel.getRupsInstanceController();
+ }
public Component getJTabbedPane() {
return this.jTabbedPane;
diff --git a/src/main/java/com/itextpdf/rups/view/icons/IconDropdownRenderer.java b/src/main/java/com/itextpdf/rups/view/icons/IconDropdownRenderer.java
new file mode 100644
index 00000000..665ef1f7
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/view/icons/IconDropdownRenderer.java
@@ -0,0 +1,22 @@
+package com.itextpdf.rups.view.icons;
+
+import com.itextpdf.rups.RupsConfiguration;
+import com.itextpdf.search.model.PropertyEnum;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class IconDropdownRenderer extends JLabel implements ListCellRenderer {
+ @Override
+ public Component getListCellRendererComponent(JList extends PropertyEnum> list, PropertyEnum object, int index, boolean isSelected, boolean cellHasFocus) {
+ String type = object.getType();
+ String value = object.toString().toLowerCase();
+ String iconString = RupsConfiguration.INSTANCE.getIconFor(String.format("rups.%s.%1s",type,value));
+ Icon icon = IconFetcher.getIcon(iconString);
+ this.setIcon(icon);
+ this.setToolTipText(object.getTooltip());// TODO: Implement Locales.
+ this.setSize(icon.getIconWidth(),icon.getIconHeight());
+ this.setVisible(true);
+ return this;
+ }
+}
diff --git a/src/main/java/com/itextpdf/rups/view/itext/PdfObjectPanel.java b/src/main/java/com/itextpdf/rups/view/itext/PdfObjectPanel.java
index 21f4e467..880f6194 100644
--- a/src/main/java/com/itextpdf/rups/view/itext/PdfObjectPanel.java
+++ b/src/main/java/com/itextpdf/rups/view/itext/PdfObjectPanel.java
@@ -55,6 +55,7 @@ This file is part of the iText (R) project.
import com.itextpdf.rups.event.RupsEvent;
import com.itextpdf.rups.model.PdfSyntaxParser;
import com.itextpdf.rups.view.Language;
+import com.itextpdf.rups.view.RupsSearchBar;
import com.itextpdf.rups.view.icons.IconFetcher;
import com.itextpdf.rups.view.itext.treenodes.PdfObjectTreeNode;
import com.itextpdf.rups.view.models.AbstractPdfObjectPanelTableModel;
@@ -114,6 +115,7 @@ public class PdfObjectPanel extends Observable implements Observer {
*/
public PdfObjectPanel() {
// layout
+
panel.setLayout(layout);
// dictionary / array / stream
diff --git a/src/main/java/com/itextpdf/rups/view/itext/contentstream/ContentStreamSearchUtils.java b/src/main/java/com/itextpdf/rups/view/itext/contentstream/ContentStreamSearchUtils.java
new file mode 100644
index 00000000..ab4153eb
--- /dev/null
+++ b/src/main/java/com/itextpdf/rups/view/itext/contentstream/ContentStreamSearchUtils.java
@@ -0,0 +1,55 @@
+/*
+ This file is part of the iText (R) project.
+ Copyright (c) 1998-2022 iText Group NV
+ Authors: iText Software.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License version 3
+ as published by the Free Software Foundation with the addition of the
+ following permission added to Section 15 as permitted in Section 7(a):
+ FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
+ ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
+ OF THIRD PARTY RIGHTS
+
+ This program 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 Affero General Public License for more details.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program; if not, see http://www.gnu.org/licenses or write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA, 02110-1301 USA, or download the license from the following URL:
+ http://itextpdf.com/terms-of-use/
+
+ The interactive user interfaces in modified source and object code versions
+ of this program must display Appropriate Legal Notices, as required under
+ Section 5 of the GNU Affero General Public License.
+
+ In accordance with Section 7(b) of the GNU Affero General Public License,
+ a covered work must retain the producer line in every PDF that is created
+ or manipulated using iText.
+
+ You can be released from the requirements of the license by purchasing
+ a commercial license. Buying such a license is mandatory as soon as you
+ develop commercial activities involving the iText software without
+ disclosing the source code of your own applications.
+ These activities include: offering paid services to customers as an ASP,
+ serving PDFs on the fly in a web application, shipping iText with a closed
+ source product.
+
+ For more information, please contact iText Software Corp. at this
+ address: sales@itextpdf.com
+ */
+package com.itextpdf.rups.view.itext.contentstream;
+
+import com.itextpdf.search.model.ISearchFilter;
+import com.itextpdf.search.model.ISearchResult;
+
+import java.io.ByteArrayInputStream;
+
+final class ContentStreamSearchUtils {
+ static ISearchResult find(ByteArrayInputStream stream, ISearchFilter filter){
+
+ return null;
+ }
+}
diff --git a/src/main/resources/bundles/rups-lang.properties b/src/main/resources/bundles/rups-lang.properties
index 9fd4a5be..3e1d28a3 100644
--- a/src/main/resources/bundles/rups-lang.properties
+++ b/src/main/resources/bundles/rups-lang.properties
@@ -61,6 +61,7 @@ ERROR_INDEX_NOT_INTEGER=The typed index isn't integer.
ERROR_INITIALIZING_SETTINGS=Error initializing settings.
ERROR_KEY_IS_NOT_NAME=Key value isn't value Name object.
ERROR_LOADING_DEFAULT_SETTINGS=Error loading default settings.
+ERROR_LOADING_ICON_DEFINITIONS=Error loading icon definitions.
ERROR_LOADING_IMAGE=Image can't be loaded.
ERROR_LOADING_XFA=Can't load XFA.
ERROR_LOOK_AND_FEEL=Error setting the look and feel.
@@ -170,6 +171,10 @@ SAVE_TO_FILE=Save to File
SAVE_TO_STREAM=Save to Stream
SAVE_UNSAVED_CHANGES=You have unchanged changes! Are you sure you want to discard them?
+SEARCH_SCOPE_SELECTION=Current Object
+SEARCH_SCOPE_DOCUMENT=Whole Document
+SEARCH_SCOPE_ALL_DOCUMENTS=All Opened Documents
+
SELECT_ALL=Select All
STREAM=Stream
diff --git a/src/main/resources/bundles/rups-lang_en_US.properties b/src/main/resources/bundles/rups-lang_en_US.properties
index 3212b49f..e8c1a799 100644
--- a/src/main/resources/bundles/rups-lang_en_US.properties
+++ b/src/main/resources/bundles/rups-lang_en_US.properties
@@ -148,6 +148,10 @@ SAVE_SUCCESS=File Saved
SAVE_TO_FILE=Save to File
SAVE_TO_STREAM=Save to Stream
+SEARCH_SCOPE_SELECTION=Current Object
+SEARCH_SCOPE_DOCUMENT=Whole Document
+SEARCH_SCOPE_ALL_DOCUMENTS=All Opened Documents
+
SELECT_ALL=Select All
STREAM=Stream
diff --git a/src/main/resources/bundles/rups-lang_nl_NL.properties b/src/main/resources/bundles/rups-lang_nl_NL.properties
index b1b298e3..18438633 100644
--- a/src/main/resources/bundles/rups-lang_nl_NL.properties
+++ b/src/main/resources/bundles/rups-lang_nl_NL.properties
@@ -58,6 +58,7 @@ ERROR_INDEX_NOT_IN_RANGE=De index is niet in range.
ERROR_INDEX_NOT_INTEGER=De index is niet een getal.
ERROR_KEY_IS_NOT_NAME=Key value is niet een Name object.
ERROR_LOADING_DEFAULT_SETTINGS=Fout tijdens het inladen van de standaard instellingen.
+ERROR_LOADING_ICON_DEFINITIONS=Fout tijdens het inladen van de icon instellingen.
ERROR_LOADING_IMAGE=De afbeelding kan niet geladen worden.
ERROR_LOADING_XFA=Het XFA form kan niet geladen worden.
ERROR_LOOK_AND_FEEL=Fout opgetreden tijdens het aanpassen van de look and feel.
@@ -166,6 +167,10 @@ SAVE_TO_FILE=Opslaan Als
SAVE_TO_STREAM=Opslaan in de Stream
SAVE_UNSAVED_CHANGES=Er zijn veranderingen die niet opgeslaan zijn! Wilt u deze negeren?
+SEARCH_SCOPE_SELECTION=Deze Object
+SEARCH_SCOPE_DOCUMENT=Hele Document
+SEARCH_SCOPE_ALL_DOCUMENTS=Alle Documenten
+
SELECT_ALL=Selecteer Alles
STREAM=Stream
diff --git a/src/main/resources/com/itextpdf/rups/view/icons/case_sensitive.png b/src/main/resources/com/itextpdf/rups/view/icons/case_sensitive.png
new file mode 100644
index 00000000..8dcc2dbb
Binary files /dev/null and b/src/main/resources/com/itextpdf/rups/view/icons/case_sensitive.png differ
diff --git a/src/main/resources/com/itextpdf/rups/view/icons/no_icon.png b/src/main/resources/com/itextpdf/rups/view/icons/no_icon.png
new file mode 100644
index 00000000..c260e1d9
Binary files /dev/null and b/src/main/resources/com/itextpdf/rups/view/icons/no_icon.png differ
diff --git a/src/main/resources/com/itextpdf/rups/view/icons/regex.png b/src/main/resources/com/itextpdf/rups/view/icons/regex.png
new file mode 100644
index 00000000..bab7cc9b
Binary files /dev/null and b/src/main/resources/com/itextpdf/rups/view/icons/regex.png differ
diff --git a/src/main/resources/com/itextpdf/rups/view/icons/search.png b/src/main/resources/com/itextpdf/rups/view/icons/search.png
new file mode 100644
index 00000000..cf3d97f7
Binary files /dev/null and b/src/main/resources/com/itextpdf/rups/view/icons/search.png differ
diff --git a/src/main/resources/com/itextpdf/rups/view/icons/whole_word.png b/src/main/resources/com/itextpdf/rups/view/icons/whole_word.png
new file mode 100644
index 00000000..280fd442
Binary files /dev/null and b/src/main/resources/com/itextpdf/rups/view/icons/whole_word.png differ
diff --git a/src/main/resources/config/icon.properties b/src/main/resources/config/icon.properties
new file mode 100644
index 00000000..414c5210
--- /dev/null
+++ b/src/main/resources/config/icon.properties
@@ -0,0 +1,7 @@
+default=no_icon.png
+rups.search.options.case_sensitivity=case_sensitive.png
+rups.search.options.word=whole_word.png
+rups.search.options.regex=regex.png
+rups.search.scope.selection=xfa.png
+rups.search.scope.document=page.png
+rups.search.scope.all_documents=pages.png
\ No newline at end of file
diff --git a/src/test/java/com/itextpdf/rups/mock/MockedRupsController.java b/src/test/java/com/itextpdf/rups/mock/MockedRupsController.java
index 57349edb..3cdd3c77 100644
--- a/src/test/java/com/itextpdf/rups/mock/MockedRupsController.java
+++ b/src/test/java/com/itextpdf/rups/mock/MockedRupsController.java
@@ -43,6 +43,7 @@ This file is part of the iText (R) project.
package com.itextpdf.rups.mock;
import com.itextpdf.rups.controller.IRupsController;
+import com.itextpdf.search.ISearchHandler;
import com.itextpdf.rups.model.PdfFile;
import java.awt.Component;
@@ -81,6 +82,7 @@ public void closeCurrentFile() {
this.openCount--;
}
+
public int getOpenedCount() {
return this.openCount;
}