Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements empty pages filter #217

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions core/core-awt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@ public class PropertyConstants {

// property change event names

public final static String
public static final String
DOCUMENT_CURRENT_PAGE = "documentCurrentPage",

DOCUMENT_VIEW_ZOOM_CHANGE = "documentViewZoomChange",
DOCUMENT_VIEW_ROTATION_CHANGE = "documentViewRotationChange",
DOCUMENT_VIEW_REFRESH_CHANGE = "documentViewRefreshChange",
DOCUMENT_VIEW_TYPE_CHANGE = "documentViewTypeChange",
DOCUMENT_VIEW_PAGES_CHANGE = "documentViewPagesChange",

DOCUMENT_TOOL_PAN = "documentToolRotation",
DOCUMENT_TOOL_ZOOM_IN = "documentToolZoomIn",
DOCUMENT_TOOL_ZOOM_OUT = "documentToolZoomOut",
DOCUMENT_TOOL_ZOOM_IN = "documentToolZoomIn",
DOCUMENT_TOOL_ZOOM_OUT = "documentToolZoomOut",
// DOCUMENT_TOOL_DYNAMIC_ROTATION = "documentToolDynamicRotation",
// DOCUMENT_TOOL_DYNAMIC_ZOOM = "documentToolDynamicZoom",

Expand Down
1 change: 1 addition & 0 deletions licenses/filter_pages_icon.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://commons.wikimedia.org/wiki/File:OOjs_UI_icon_eye.svg
1 change: 1 addition & 0 deletions licenses/mail_icon.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://iconarchive.com/show/web-blog-icons-by-semlabs/mail2-send-icon.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import org.icepdf.core.search.DocumentSearchController;
import org.icepdf.core.util.*;
import org.icepdf.core.util.updater.WriteMode;
import org.icepdf.ri.common.filters.DocumentFilter;
import org.icepdf.ri.common.filters.DocumentFilterListener;
import org.icepdf.ri.common.filters.EmptyPagesFilter;
import org.icepdf.ri.common.preferences.PreferencesDialog;
import org.icepdf.ri.common.print.PrintHelper;
import org.icepdf.ri.common.print.PrintHelperFactory;
Expand Down Expand Up @@ -120,16 +123,13 @@
public class SwingController extends ComponentAdapter
implements org.icepdf.ri.common.views.Controller, ActionListener, FocusListener, ItemListener,
TreeSelectionListener, WindowListener, DropTargetListener,
PropertyChangeListener {
PropertyChangeListener, DocumentFilterListener {

protected static final Logger logger =
Logger.getLogger(SwingController.class.toString());

private static final boolean USE_JFILECHOOSER;

static {
USE_JFILECHOOSER = Defs.booleanProperty("org.icepdf.ri.viewer.jfilechooser", false);
}
private static final boolean USE_JFILECHOOSER = Defs.booleanProperty("org.icepdf.ri.viewer.jfilechooser", false);
private static final boolean IS_PREFILTER = Defs.booleanProperty("org.icepdf.ri.viewer.filters.prefilter", false);

private static final boolean IS_READONLY = Defs.booleanProperty("org.icepdf.ri.viewer.readonly", false);

Expand All @@ -143,6 +143,9 @@ public class SwingController extends ComponentAdapter

protected static final int MAX_SELECT_ALL_PAGE_COUNT = 250;

private static final DocumentFilter EMPTY_PAGES_FILTER = getEmptyPagesFilter();
private final Map<DocumentFilter, Boolean> filters;

private JMenuItem openFileMenuItem;
private JMenu recentFilesSubMenu;
private JMenuItem openURLMenuItem;
Expand Down Expand Up @@ -222,6 +225,7 @@ public class SwingController extends ComponentAdapter
private JToggleButton textSelectToolButton;
private JToggleButton zoomInToolButton;
private JToggleButton zoomDynamicToolButton;
private JToggleButton filterPagesButton;
private JToggleButton selectToolButton;
// main annotation toolbar
private AnnotationColorToggleButton highlightAnnotationToolButton;
Expand Down Expand Up @@ -320,6 +324,9 @@ public SwingController(ResourceBundle currentMessageBundle) {
SwingController.messageBundle = ResourceBundle.getBundle(
ViewerPropertiesManager.DEFAULT_MESSAGE_BUNDLE);
}
filters = new HashMap<>();
filters.put(EMPTY_PAGES_FILTER, true);
filters.keySet().forEach(df -> df.addListener(this));
}

/**
Expand Down Expand Up @@ -1393,6 +1400,39 @@ public void setZoomDynamicToolButton(JToggleButton btn) {
btn.addItemListener(this);
}

/**
* Called by SwingViewerBuilder, so that Controller can setup event handling
*
* @param btn button to assign
*/
public void setFilterPagesButton(JToggleButton btn) {
filterPagesButton = btn;
btn.addItemListener(this);
final JPopupMenu popupMenu = new JPopupMenu();
final JCheckBoxMenuItem emptyPagesMenuItem = getFilterMenuItem(messageBundle.getString(
"viewer.toolbar.tool.filterEmptyPages.label"), EMPTY_PAGES_FILTER);
emptyPagesMenuItem.setSelected(true);
popupMenu.add(emptyPagesMenuItem);
btn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3 && document != null && !isPdfCollection()) {
popupMenu.show(btn, e.getX(), e.getY());
}
}
});
}

private JCheckBoxMenuItem getFilterMenuItem(final String label, final DocumentFilter filter) {
final JCheckBoxMenuItem menuItem = new PersistentJCheckBoxMenuItem(label);
menuItem.addItemListener(e -> {
filters.put(filter, menuItem.isSelected());
setEnabled(filterPagesButton, document != null && !isPdfCollection() && areFiltersReady());
});
return menuItem;
}


/**
* Called by SwingViewerBuilder, so that Controller can setup event handling
*
Expand Down Expand Up @@ -1558,7 +1598,7 @@ public boolean isPdfCollection() {
if (filePairs != null) {
Library library = catalog.getLibrary();
// check to see if at least one file is a PDF.
for (int i = 0, max = filePairs.size(); i < max; i += 2) {
for (int i = 0, max = filePairs.size(); i < max; i = 2) {
// get the name and document for
// file name and file specification pairs.
String fileName = Utils.convertStringObject(library, (StringObject) filePairs.get(i));
Expand Down Expand Up @@ -1696,6 +1736,7 @@ protected void reflectStateInComponents() {
setEnabled(panToolButton, opened && !pdfCollection);
setEnabled(zoomInToolButton, opened && !pdfCollection);
setEnabled(zoomDynamicToolButton, opened && !pdfCollection);
setEnabled(filterPagesButton, opened && !pdfCollection && areFiltersReady());
setEnabled(textSelectToolButton, opened && canExtract && !pdfCollection);
setEnabled(selectToolButton, opened && canModify && !pdfCollection);
setEnabled(highlightAnnotationToolButton, opened && canModify && !pdfCollection && !IS_READONLY);
Expand Down Expand Up @@ -1741,6 +1782,10 @@ protected void reflectStateInComponents() {
}
}

private boolean areFiltersReady() {
return !IS_PREFILTER || getEnabledFilters().stream().allMatch(df -> df.isReady(document));
}

private boolean hasForms() {
return document != null &&
!(document.getCatalog().getInteractiveForm() == null ||
Expand Down Expand Up @@ -2901,7 +2946,6 @@ public void openDocument(byte[] data, int offset, int length, String description
}

public void commonNewDocumentHandling(String fileDescription) {

// utility pane visibility
boolean showUtilityPane = false;

Expand Down Expand Up @@ -3148,6 +3192,9 @@ public void commonNewDocumentHandling(String fileDescription) {
// set the go to page combo box in the mainToolbar
reflectStateInComponents();
updateDocumentView();
if (IS_PREFILTER) {
new Thread(() -> filters.keySet().forEach(f -> f.filterPages(document))).start();
}
}

/**
Expand Down Expand Up @@ -3198,6 +3245,7 @@ public void closeDocument() {

// free the document
if (document != null) {
filters.forEach((f, b) -> f.interrupt(document));
document.dispose();
document = null;
}
Expand Down Expand Up @@ -3337,6 +3385,7 @@ public void dispose() {
panToolButton = null;
zoomInToolButton = null;
zoomDynamicToolButton = null;
filterPagesButton = null;
textSelectToolButton = null;
selectToolButton = null;
highlightAnnotationToolButton = null;
Expand Down Expand Up @@ -3422,6 +3471,7 @@ public void dispose() {
viewModel = null;

windowManagementCallback = null;
filters.keySet().forEach(df -> df.removeListener(this));
}

/**
Expand Down Expand Up @@ -5100,6 +5150,13 @@ else if (source == panToolButton) {
tool = DocumentViewModelImpl.DISPLAY_TOOL_ZOOM_DYNAMIC;
setDocumentToolMode(DocumentViewModelImpl.DISPLAY_TOOL_ZOOM_DYNAMIC);
}
} else if (source == filterPagesButton) {
if (e.getStateChange() == ItemEvent.SELECTED) {
filterDocumentPages();
} else {
documentViewController.filterPageComponents(pvc -> true);
}
reflectSelectionInButton(filterPagesButton, filterPagesButton.isSelected());
} else if (source == textSelectToolButton) {
if (e.getStateChange() == ItemEvent.SELECTED) {
tool = DocumentViewModelImpl.DISPLAY_TOOL_TEXT_SELECTION;
Expand Down Expand Up @@ -5213,6 +5270,23 @@ else if (source == facingPageViewNonContinuousButton) {
}
}

protected void filterDocumentPages() {
final Set<Integer> filteredIndexes = documentViewController.getDocumentViewModel().getAllPageComponents()
.stream().map(AbstractPageViewComponent::getPageIndex).collect(Collectors.toSet());
logger.info("Filtering with " + getEnabledFilters().stream().map(Object::toString).collect(Collectors.joining(";")));
filters.forEach((df, enabled) -> {
if (enabled) {
final Set<Integer> keptIndexes = df.filterPages(document);
filteredIndexes.removeIf(i -> !keptIndexes.contains(i));
}
});
documentViewController.filterPageComponents(pvc -> filteredIndexes.contains(pvc.getPageIndex()));
}

protected Set<DocumentFilter> getEnabledFilters() {
return filters.entrySet().stream().filter(Map.Entry::getValue).map(Map.Entry::getKey).collect(Collectors.toSet());
}

private static boolean checkAnnotationButton(final Object source, final AnnotationColorToggleButton button,
final JToggleButton propertiesButton) {
return source == button || (button != null && source == button.getColorButton()) || source == propertiesButton;
Expand Down Expand Up @@ -5513,6 +5587,22 @@ protected final void addKeyAction(final JComponent component, final int keyCode,
actionMap.put(key, action);
}

@Override
public void documentFilterStarted(final DocumentFilter filter, final Document document) {
if (this.document == document) {
setEnabled(filterPagesButton, false);
}
}

@Override
public void documentFilterCompleted(final DocumentFilter filter, final Document document,
final Set<Integer> filteredPages) {
if (this.document == document) {
setEnabled(filterPagesButton, !isPdfCollection() && document != null && areFiltersReady());
}
}


@FunctionalInterface
protected interface ActionMethod {
void doAction();
Expand Down Expand Up @@ -5552,6 +5642,7 @@ public void keyTyped(KeyEvent e) {
currentPageNumberTextField.setText(modelValue);
}
}

}

/**
Expand Down Expand Up @@ -5745,7 +5836,7 @@ public void changeAnnotationsVisibility(final AnnotationFilter filter, final boo
pa.setOpen(false);
final int idx = pa.getPageIndex();
final AbstractAnnotationComponent comp = (AbstractAnnotationComponent) ((PageViewComponentImpl)
documentViewController.getDocumentViewModel().getPageComponents().get(idx)).getComponentFor(pa);
documentViewController.getDocumentViewModel().getAllPageComponents().get(idx)).getComponentFor(pa);
if (comp != null) {
comp.setVisible(false);
}
Expand Down Expand Up @@ -5778,7 +5869,7 @@ public void changeAnnotationsPrivacy(final AnnotationFilter filter, final boolea
pa.setModifiedDate(PDate.formatDateTime(new Date()));
}
final PageViewComponentImpl pvc = (PageViewComponentImpl)
documentViewController.getDocumentViewModel().getPageComponents().get(ma.getPageIndex());
documentViewController.getDocumentViewModel().getAllPageComponents().get(ma.getPageIndex());
final MarkupAnnotationComponent<?> comp = (MarkupAnnotationComponent<?>) pvc.getComponentFor(ma);
if (comp != null) {
if (comp.getPopupAnnotationComponent() != null) {
Expand All @@ -5802,4 +5893,10 @@ private void callOnFilteredAnnotations(final AnnotationFilter filter, final Cons
}
}
}

private static EmptyPagesFilter getEmptyPagesFilter() {
final double minRatio = Defs.doubleProperty("org.icepdf.ri.viewer.filters.empty.ratio", 0.005);
final int whiteFloor = Defs.intProperty("org.icepdf.ri.viewer.filters.empty.white.floor", 240);
return new EmptyPagesFilter(minRatio, whiteFloor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ public JToolBar buildCompleteToolBar(boolean embeddableComponent) {
if (propertiesManager.checkAndStoreBooleanProperty(ViewerPropertiesManager.PROPERTY_SHOW_TOOLBAR_TOOL))
addToToolBar(toolbar, buildToolToolBar());
if (propertiesManager.checkAndStoreBooleanProperty(ViewerPropertiesManager.PROPERTY_SHOW_TOOLBAR_ANNOTATION))
addToToolBar(toolbar, buildAnnotationlToolBar());
addToToolBar(toolbar, buildAnnotationToolBar());
if (propertiesManager.checkAndStoreBooleanProperty(ViewerPropertiesManager.PROPERTY_SHOW_TOOLBAR_FORMS))
addToToolBar(toolbar, buildFormsToolBar());
if (propertiesManager.checkAndStoreBooleanProperty(ViewerPropertiesManager.PROPERTY_SHOW_TOOLBAR_SEARCH))
Expand Down Expand Up @@ -1264,6 +1264,7 @@ public JToolBar buildUtilityToolBar(boolean embeddableComponent, ViewerPropertie
if (propertiesManager.checkAndStoreBooleanProperty(ViewerPropertiesManager.PROPERTY_SHOW_UTILITY_UPANE))
addToToolBar(toolbar, buildShowHideUtilityPaneButton());

addToToolBar(toolbar, buildFilterPagesButton());
// Don't bother with this toolbar if we don't have any visible buttons
if (toolbar.getComponentCount() == 0) {
return null;
Expand Down Expand Up @@ -1587,7 +1588,7 @@ public JToolBar buildToolToolBar() {
return toolbar;
}

public JToolBar buildAnnotationlToolBar() {
public JToolBar buildAnnotationToolBar() {
JToolBar toolbar = new JToolBar();
commonToolBarSetup(toolbar, false);
if (propertiesManager.checkAndStoreBooleanProperty(
Expand Down Expand Up @@ -2041,6 +2042,15 @@ public JToggleButton buildZoomOutToolButton() {
return btn;
}

public JToggleButton buildFilterPagesButton() {
JToggleButton btn = makeToolbarToggleButton(
messageBundle.getString("viewer.toolbar.tool.filterPages.label"),
messageBundle.getString("viewer.toolbar.tool.filterPages.tooltip"),
"filter_pages", iconSize, buttonFont);
if (viewerController != null && btn != null)
viewerController.setFilterPagesButton(btn);
return btn;
}

public JSplitPane buildUtilityAndDocumentSplitPane(boolean embeddableComponent) {
JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
Expand Down
Loading