org.jpedal.examples.viewer.gui.JavaFxGUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
An Open Source JavaFX PDF Viewer
/*
* ===========================================
* 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
*
* ---------------
* JavaFxGUI.java
* ---------------
*/
package org.jpedal.examples.viewer.gui;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.*;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.Transition;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.*;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.TextAlignment;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
import javax.imageio.ImageIO;
import org.jpedal.FileAccess;
import org.jpedal.PdfDecoderFX;
import org.jpedal.PdfDecoderInt;
import org.jpedal.display.Display;
import org.jpedal.display.GUIModes;
import org.jpedal.display.GUIThumbnailPanel;
import org.jpedal.display.PageOffsets;
import org.jpedal.display.javafx.PageFlowDisplayFX;
import org.jpedal.display.javafx.SingleDisplayFX;
import org.jpedal.examples.viewer.*;
import org.jpedal.examples.viewer.commands.OpenFile;
import org.jpedal.examples.viewer.commands.javafx.JavaFXOpenFile;
import org.jpedal.examples.viewer.gui.generic.*;
import org.jpedal.examples.viewer.gui.javafx.*;
import org.jpedal.examples.viewer.gui.javafx.FXViewerTransitions.TransitionDirection;
import org.jpedal.examples.viewer.gui.javafx.FXViewerTransitions.TransitionType;
import org.jpedal.examples.viewer.gui.javafx.dialog.FXInputDialog;
import org.jpedal.examples.viewer.gui.javafx.dialog.FXMessageDialog;
import org.jpedal.examples.viewer.gui.javafx.dialog.FXOptionDialog;
import org.jpedal.examples.viewer.paper.PaperSizes;
import org.jpedal.examples.viewer.utils.PropertiesFile;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.external.Options;
import org.jpedal.fonts.tt.TTGlyph;
import org.jpedal.gui.GUIFactory;
import org.jpedal.io.StatusBarFX;
import org.jpedal.objects.PdfPageData;
import org.jpedal.objects.acroforms.AcroRenderer;
import org.jpedal.objects.acroforms.actions.ActionHandler;
import org.jpedal.objects.layers.PdfLayerList;
import org.jpedal.objects.raw.FormObject;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.parser.DecoderOptions;
import org.jpedal.render.DynamicVectorRenderer;
import org.jpedal.utils.BrowserLauncher;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Messages;
import org.w3c.dom.Node;
/**
*
Description: GUI functions in Viewer implemented in JavaFX
*/
@SuppressWarnings("MagicConstant")
public class JavaFxGUI extends GUI implements GUIFactory {
private RefreshLayout viewListener;
private static final int bottomPaneHeight = 40;
protected final JavaFXButtons fxButtons;
//GUICursor object that holds everything todo with Cursor for SwingGUI
private final SwingCursor guiCursor = new SwingCursor();
//all mouse actions
private GUIMouseHandler mouseHandler;
private Timeline memoryMonitor;
//flag for marks new thumbnail preview
private boolean debugThumbnail;
private boolean sideTabBarOpenByDefault;
private String startSelectedTab = "Pages";
//use new GUI layout
public static String windowTitle;
private boolean hasListener;
private boolean isSetup;
private int lastTabSelected = -1;
private boolean tabsExpanded;
private PaperSizes paperSizes;
/*
* Multibox for new GUI Layout Component to contain memory, cursor and
* loading bars IMPORTANT : the width of the multibox needs to be the same
* size as the width of pagesToolBar to ensure that it is centered on the
* page.
*/
private HBox multiboxfx;
private FXProgressBarWithText memoryBarFX;
//visual display of current cursor co-ords on page
private TextField coordsFX;
//Track whether both pages are properly displayed
private static final boolean pageTurnScalingAppropriate = true;
//holds back/forward buttons at bottom of page
private HBox navButtons;
//displayed on left to hold thumbnails, bookmarks
private TabPane navOptionsPanel;
//tell user on first form change it can be saved
private static final boolean firstTimeFormMessage = true;
//flag to disable functions
private boolean isSingle = true;
private Label pageCounter1;
public TextField pageCounter2;
private Label pageCounter3;
private final JavaFXSignaturesPanel signaturesPanel;
private final JavaFXLayersPanel layersPanel;
//stop user forcing open tab before any pages loaded
private boolean tabsNotInitialised = true;
//private boolean thumbnailsInitialised;
private boolean hasPageChanged;
private ToolBar navToolBar;
private ToolBar pagesToolBar;
//The main JavaFX Stage
private final Stage stage;
//The main JavaFX Scene
private Scene scene;
//BorderPane lays out children in top, left, right, bottom, and center positions.
private final BorderPane root;
private static final int dropshadowDepth = 40;
private Group group;
// Scrollpane to contain the PDF page
private ScrollPane pageContainer;
private SplitPane center;
private final VBox topPane;
private StatusBarFX downloadBar;
private boolean searchInMenu;
private TextField searchText;
private GUISearchList results;
private MenuBar options;
private boolean cursorOverPage;
private TransitionType transitionType = TransitionType.None;
// Scrolls between pages when the pdf is not zoomed in
private ScrollBar pageScroll;
private ChangeListener fxChangeListener;
public JavaFxGUI(final Stage stage, final PdfDecoderInt decode_pdf, final Values commonValues, final GUIThumbnailPanel thumbnails, final PropertiesFile properties) {
super(decode_pdf, commonValues, thumbnails, properties);
isJavaFX = true;
if (debugFX) {
System.out.println("JavaFxGUI");
}
this.stage = stage;
root = new BorderPane();
topPane = new VBox();
pageCounter2 = new TextField();
navButtons = new HBox();
fxButtons = new JavaFXButtons();
pageCounter3 = new Label();
navToolBar = new ToolBar();
pagesToolBar = new ToolBar();
tree = new JavaFXOutline();
layersPanel = new JavaFXLayersPanel();
signaturesPanel = new JavaFXSignaturesPanel();
setLookAndFeel();
setupDisplay();
}
/*
For the following methods getThumbnailScrollBar, setThumbnailScrollBarVisibility and setThumbnailScrollBarValue:
These methods have not been implemented yet as they do not have the equivalent to SwingGUI.thumbscroll
implemented in FX.
*/
@Override
public Object getThumbnailScrollBar() {
if (debugFX) {
System.out.println("getThumbnailScrollBar - Implemented");
}
return pageScroll;
}
@Override
public void setThumbnailScrollBarVisibility(final boolean isVisible) {
if (debugFX) {
System.out.println("setThumbnailScrollBarVisibility - Implemented");
}
pageScroll.setVisible(isVisible);
//#making invisible still shows the gap so iam padding negative to hide it
if(isVisible){
pageScroll.setStyle("-fx-padding:0px");
}else{
pageScroll.setStyle("-fx-padding:-10px");
}
}
@Override
public void setThumbnailScrollBarValue(final int pageNum) {
if (debugFX) {
System.out.println("setThumbnailScrollBarValue - Implemented");
}
pageScroll.setValue(pageNum);
}
/**
* set the look and feel for the GUI components to be the default for the
* system it is running on
*/
private void setLookAndFeel() {
if (debugFX) {
System.out.println("setLookAndFeel - Not yet implemented in JavaFX");
}
/*
* JavaFX has not look and feel option, 2.2 has a theme called Caspian
* (the default theme) only. FX8 has Moderna and Caspian, which can be
* set in the class which overrides Application with
* setUserAgentStylesheet(url)
*
* We can also define our own rules on top of this with:
* root.getStylesheets().clear();
* root.getStylesheets().add("stylesheetlocation"); Also see:
* http://blog.idrsolutions.com/2014/04/use-external-css-files-javafx/
*/
root.getStylesheets().clear();
root.getStylesheets().add(getClass().getResource("/org/jpedal/examples/viewer/res/css/JavaFXForms.css").toExternalForm());
root.getStylesheets().add(getClass().getResource("/org/jpedal/examples/viewer/res/css/JavaFXPages.css").toExternalForm());
}
private void setupDisplay() {
if (debugFX) {
System.out.println("setupDisplay - Not yet implemented in JavaFX");
}
setDisplayView(Display.SINGLE_PAGE, Display.DISPLAY_CENTERED);
//pass in SwingGUI so we can call via callback
decode_pdf.addExternalHandler(this, Options.GUIContainer);
menuItems = new JavaFXMenuItems(properties);
}
@Override
public SplitPane getDisplayPane() {
return center;
}
@Override
public Object getMultiViewerFrames() {
if (debugFX) {
System.out.println("getMultiViewerFrames");
}
//return desktopPane;
return null;
}
@Override
public String getPropertiesFileLocation() {
if (debugFX) {
System.out.println("getPropertiesFileLocation");
}
return properties.getConfigFile();
}
@Override
public String getBookmark(final String bookmark) {
if (debugFX) {
System.out.println("getBookmark");
}
return tree.getPage(bookmark);
}
@Override
public void reinitialiseTabs(final boolean showVisible) {
if (debugFX) {
System.out.println("reinitialiseTabs");
}
//not needed
if (commonValues.getModeOfOperation() == Values.RUNNING_PLUGIN) {
return;
}
if (properties.getValue("ShowSidetabbar").equalsIgnoreCase("true")) {
if (!isSingle) {
return;
}
if (!showVisible && !properties.getValue("consistentTabBar").equalsIgnoreCase("true")) {
if (sideTabBarOpenByDefault) {
setSplitDividerLocation(expandedSize);
tabsExpanded = true;
} else {
setSplitDividerLocation(collapsedSize);
tabsExpanded = false;
}
}
lastTabSelected = -1;
if (!commonValues.isPDF()) {
navOptionsPanel.setVisible(false);
} else {
navOptionsPanel.setVisible(true);
/*
* add/remove optional tabs
*/
if (!decode_pdf.hasOutline()) {
int outlineTab = -1;
if (DecoderOptions.isRunningOnMac) {
//String tabName="";
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
if (navOptionsPanel.getTabs().get(jj).getText().equals(bookmarksTitle)) {
outlineTab = jj;
}
}
} else {
//String tabName="";
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
//@Simon recode to use VTextIcon
if (navOptionsPanel.getTabs().get(jj).getText().equals(bookmarksTitle)) {
outlineTab = jj;
}
}
}
if (outlineTab != -1) {
navOptionsPanel.getTabs().remove(outlineTab);
}
} else if (properties.getValue("Bookmarkstab").equalsIgnoreCase("true")) {
int outlineTab = -1;
if (DecoderOptions.isRunningOnMac) {
//String tabName="";
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
if (navOptionsPanel.getTabs().get(jj).getText().equals(bookmarksTitle)) {
outlineTab = jj;
}
}
if (outlineTab == -1) // navOptionsPanel.addTab(bookmarksTitle,(SwingOutline) tree);
//@Simon Change to add JavaFXOutline tab
{
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, (Tab) tree);
}
} else {
//String tabName="";
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
//@Simon recode to use VTextIcon
if (navOptionsPanel.getTabs().get(jj).getText().equals(bookmarksTitle)) {
outlineTab = jj;
}
}
if (outlineTab == -1) {
//@Simon Recode
// VTextIcon textIcon2 = new VTextIcon(navOptionsPanel, bookmarksTitle, VTextIcon.ROTATE_LEFT);
// navOptionsPanel.addTab(null, textIcon2, (SwingOutline) tree);
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, (Tab) tree);
}
}
}
/*
* handle signatures pane
*/
final AcroRenderer currentFormRenderer = decode_pdf.getFormRenderer();
Iterator signatureObjects = null;
if (currentFormRenderer != null) {
signatureObjects = currentFormRenderer.getSignatureObjects();
}
if (signatureObjects != null) {
signaturesPanel.reinitialise(decode_pdf, signatureObjects);
checkTabShown(signaturesTitle);
} else {
removeTab(signaturesTitle);
}
/*
* add a control Panel to enable/disable layers
*/
//layers object
layersObject = (PdfLayerList) decode_pdf.getJPedalObject(PdfDictionary.Layer);
if (layersObject != null && layersObject.getLayersCount() > 0) { //some files have empty Layers objects
checkTabShown(layersTitle);
layersPanel.reinitialise(layersObject, decode_pdf, null, commonValues.getCurrentPage());
} else {
removeTab(layersTitle);
}
setBookmarks(false);
}
if (tabsNotInitialised) {
//@Simon selected index
for (int i = 0; i != navOptionsPanel.getTabs().size(); i++) {
if (DecoderOptions.isRunningOnMac) {
if (navOptionsPanel.getTabs().get(i).getText().equals(startSelectedTab)) {
navOptionsPanel.getSelectionModel().select(i);
break;
}
} else {
if (navOptionsPanel.getTabs().get(i).getGraphic().toString().equals(startSelectedTab)) {
navOptionsPanel.getSelectionModel().select(i);
break;
}
}
}
}
}
}
private void checkTabShown(final String title) {
if (debugFX) {
System.out.println("checkTabShown");
}
int outlineTab = -1;
if (DecoderOptions.isRunningOnMac) {
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
if (navOptionsPanel.getTabs().get(jj).getText().equals(title)) {
outlineTab = jj;
}
}
if (outlineTab == -1) {
if (title.equals(signaturesTitle) && properties.getValue("Signaturestab").equalsIgnoreCase("true")) {
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, signaturesPanel);
} else if (title.equals(layersTitle) && properties.getValue("Layerstab").equalsIgnoreCase("true")) {
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, layersPanel);
}
}
} else {
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
//@Simon to getIcon
if (navOptionsPanel.getTabs().get(jj).getText().equals(title)) {
outlineTab = jj;
}
}
if (outlineTab == -1) {
if (title.equals(signaturesTitle) && properties.getValue("Signaturestab").equalsIgnoreCase("true")) { //stop spurious display of Sig tab
//@Simon Signatures panel
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, signaturesPanel);
} else if (title.equals(layersTitle) && properties.getValue("Layerstab").equalsIgnoreCase("true")) {
navOptionsPanel.getTabs().add(navOptionsPanel.getTabs().size() - 1, layersPanel);
}
}
}
}
private void removeTab(final String title) {
if (debugFX) {
System.out.println("removeTab");
}
int outlineTab = -1;
if (DecoderOptions.isRunningOnMac) {
//String tabName="";
//see if there is an outlines tab
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
if (navOptionsPanel.getTabs().get(jj).getText().equals(title)) {
outlineTab = jj;
}
}
} else {
//String tabName="";
//see if there is an outlines tab
// @Simon to getIcon
for (int jj = 0; jj < navOptionsPanel.getTabs().size(); jj++) {
if (navOptionsPanel.getTabs().get(jj).getText().equals(title)) {
outlineTab = jj;
}
}
}
if (outlineTab != -1) // navOptionsPanel.remove(outlineTab);
{
navOptionsPanel.getTabs().remove(outlineTab);
}
}
@Override
public void stopThumbnails() {
if (debugFX) {
System.out.println("stopThumbnails");
}
if (!isSingle) {
return;
}
if (thumbnails.isShownOnscreen()) {
thumbnails.terminateDrawing();
thumbnails.removeAllListeners();
}
}
@Override
public void reinitThumbnails() {
if (debugFX) {
System.out.println("reinitThumbnails");
}
isSetup = false;
}
/**
* reset the navigation bar so that it appears closed
*/
@Override
public void resetNavBar() {
if (debugFX) {
System.out.println("resetNavBar");
}
if (!isSingle) {
return;
}
if (!properties.getValue("consistentTabBar").equalsIgnoreCase("true")) {
setSplitDividerLocation(collapsedSize);
tabsExpanded = false;
tabsNotInitialised = true;
}
//also reset layers
// layersPanel.resetLayers();
//disable page view buttons until we know we have multiple pages
fxButtons.setPageLayoutButtonsEnabled(false);
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#setNoPagesDecoded()
*
* Called when new file opened so we set flags here
*/
@Override
public void setNoPagesDecoded() {
if (debugFX) {
System.out.println("setNoPagesDecoded");
}
bookmarksGenerated = false;
resetNavBar();
}
@Override
public void setDisplayMode(final Integer mode) {
if (debugFX) {
System.out.println("setDisplayMode");
}
if (mode.equals(GUIFactory.MULTIPAGE)) {
isSingle = false;
}
}
@Override
public boolean isSingle() {
if (debugFX) {
System.out.println("isSingle");
}
return isSingle;
}
@Override
public Object getThumbnailPanel() {
if (debugFX) {
System.out.println("getThumbnailPanel");
}
return thumbnails;
}
@Override
public Object getOutlinePanel() {
if (debugFX) {
System.out.println("getOutlinePanel");
}
return tree;
}
/**
* Can't get the scrollbar from a scroll pane, other methods should be
* implemented to circumvent this when needed
*/
@Override
public Object getVerticalScrollBar() {
if (debugFX) {
System.out.println("getVerticalScrollBar");
}
// Altered function due to above comments, return thumbscroll only when shown
if (pageScroll.isVisible()) {
return pageScroll;
} else {
return null;
}
}
/*
*Allows user to embed viewer into own application�
*/
@Override
public void setRootContainer(final Object rawValue) {
if (rawValue == null) {
throw new RuntimeException("Null containers not allowed.");
}
final Parent parentPane = (Parent) rawValue;
//We add the Viewer to the parent pane depending on its type.
if (parentPane instanceof Pane) {
((Pane) parentPane).getChildren().add(root);
} else if (parentPane instanceof ScrollPane) {
((ScrollPane) parentPane).setContent(root);
}
//Load width and height from properties file
int width = Integer.parseInt(properties.getValue("startViewerWidth"));
int height = Integer.parseInt(properties.getValue("startViewerHeight"));
//Used to prevent infinite scroll issue as a preferred size has been set
final Rectangle2D d = Screen.getPrimary().getVisualBounds();
if (width < 0) {
width = (int) (d.getWidth() / 2);
if (width < 700) {
width = 700;
}
properties.setValue("startViewerWidth", String.valueOf(width));
}
if (height < 0) {
height = (int) (d.getHeight() / 2);
properties.setValue("startViewerHeight", String.valueOf(height));
}
//allow user to alter size
final String customWindowSize = System.getProperty("org.jpedal.startWindowSize");
if (customWindowSize != null) {
final StringTokenizer values = new StringTokenizer(customWindowSize, "x");
System.out.println(values.countTokens());
if (values.countTokens() != 2) {
throw new RuntimeException("Unable to use value for org.jpedal.startWindowSize=" + customWindowSize + "\nValue should be in format org.jpedal.startWindowSize=200x300");
}
//try {
//width = Integer.parseInt(values.nextToken().trim());
//height = Integer.parseInt(values.nextToken().trim());
// } catch (Exception ee) {
// throw new RuntimeException("Unable to use value for org.jpedal.startWindowSize=" + customWindowSize + "\nValue should be in format org.jpedal.startWindowSize=200x300");
// }
}
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#resetRotationBox()
*/
@Override
public void resetRotationBox() {
if (debugFX) {
System.out.println("resetRotationBox");
}
final PdfPageData currentPageData = decode_pdf.getPdfPageData();
//>>> DON'T UNCOMMENT THIS LINE, causes major rotation issues, only useful for debuging <<<
if (decode_pdf.getDisplayView() == Display.SINGLE_PAGE) {
rotation = currentPageData.getRotation(commonValues.getCurrentPage());
}
//else
//rotation=0;
if (getSelectedComboIndex(Commands.ROTATION) != (rotation / 90)) {
setSelectedComboIndex(Commands.ROTATION, (rotation / 90));
} else if (!Values.isProcessing()) {
// ((PdfDecoder)decode_pdf).repaint();
}
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#getProperties()
*/
@Override
public PropertiesFile getProperties() {
return properties;
}
/**
* Set Search Bar to be in the Left hand Tabbed pane
*/
@Override
public void searchInTab(final GUISearchWindow searchFrame) {
if (debugFX) {
System.out.println("searchInTab");
}
this.searchFrame = searchFrame;
this.searchFrame.init(decode_pdf, commonValues);
if (DecoderOptions.isRunningOnMac) {
if (thumbnails.isShownOnscreen()) {
//@Simon Search tab
// navOptionsPanel.addTab("Search",searchFrame.getContentPanel());
}
} else {
//@Simon search tab
// VTextIcon textIcon2 = new VTextIcon(navOptionsPanel, "Search", VTextIcon.ROTATE_LEFT);
// navOptionsPanel.addTab(null, textIcon2, searchFrame.getContentPanel());
}
}
/**
* Adds Drop-Down Search Menu Options to the In-Menu Search Field.
* @return
*/
private MenuBar createMenuBarSearchOptions() {
//Setup Search In Menu Options.
final CheckMenuItem cb1 = new CheckMenuItem(Messages.getMessage("PdfViewerSearch.WholeWords"));
final CheckMenuItem cb2 = new CheckMenuItem(Messages.getMessage("PdfViewerSearch.CaseSense"));
final CheckMenuItem cb3 = new CheckMenuItem(Messages.getMessage("PdfViewerSearch.MultiLine"));
//Add Search 0ptions listeners.
cb1.selectedProperty().addListener(new ChangeListener() {
@Override
public void changed(final ObservableValue ov,
final Boolean old_val, final Boolean new_val) {
searchFrame.setWholeWords(cb1.isSelected());
}
});
cb2.selectedProperty().addListener(new ChangeListener() {
@Override
public void changed(final ObservableValue ov,
final Boolean old_val, final Boolean new_val) {
searchFrame.setCaseSensitive(cb2.isSelected());
}
});
cb3.selectedProperty().addListener(new ChangeListener() {
@Override
public void changed(final ObservableValue ov,
final Boolean old_val, final Boolean new_val) {
searchFrame.setMultiLine(cb3.isSelected());
}
});
//Setup Menu Apply Image, and Add Items.
final Menu menu = new Menu();
final Image image = new Image(guiCursor.getURLForImage("menuSearchOptions.png").toString());
menu.setGraphic(new ImageView(image));
menu.getItems().addAll(cb1, cb2, cb3);
//Setup Menu Bar and Add Menu.
options = new MenuBar();
options.setBackground(Background.EMPTY);
options.setFocusTraversable(false);
options.setTooltip(new Tooltip(Messages.getMessage("PdfViewerSearch.Options")));
options.getMenus().add(menu);
return options;
}
/*
* Set Search Bar to be in the Top Button Bar
*/
private void searchInMenu(final GUISearchWindow searchFrame) {
this.searchFrame = searchFrame;
searchInMenu = true;
searchFrame.find(decode_pdf, commonValues);
fxButtons.getTopButtons().getItems().add(searchText);
fxButtons.getTopButtons().getItems().add(createMenuBarSearchOptions());
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerSearch.Previous"), "search_previous.gif", Commands.PREVIOUSRESULT, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerSearch.Next"), "search_next.gif", Commands.NEXTRESULT, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
fxButtons.getButton(Commands.NEXTRESULT).setEnabled(false);
fxButtons.getButton(Commands.PREVIOUSRESULT).setEnabled(false);
fxButtons.getButton(Commands.NEXTRESULT).setVisible(true);
fxButtons.getButton(Commands.PREVIOUSRESULT).setVisible(true);
}
@Override
public void setPropertiesFileLocation(final String file) {
properties.loadProperties(file);
}
@Override
public Commands getCommand() {
return currentCommands;
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#init(java.lang.String[], org.jpedal.examples.viewer.Commands, org.jpedal.examples.viewer.utils.Printer)
*/
@Override
public void init(final Commands currentCommands) {
if (debugFX) {
System.out.println("init");
}
updateTransitionType();
mouseHandler = new JavaFXMouseListener((PdfDecoderFX) decode_pdf, this, commonValues, currentCommands);
mouseHandler.setupMouse();
//single listener to execute all commands
currentCommandListener = new CommandListenerFX(currentCommands);
super.init(currentCommands);
//Set up from properties
try {
//Set whether to use hinting
String propValue = properties.getValue("useHinting");
String propValue2 = System.getProperty("org.jpedal.useTTFontHinting");
//check JVM flag first
if (propValue2 != null) {
//check if properties file conflicts
if (!propValue.isEmpty() && !propValue2.equalsIgnoreCase(propValue.toLowerCase())) {
showMessageDialog(Messages.getMessage("PdfCustomGui.hintingFlagFileConflict"));
}
TTGlyph.useHinting = propValue2.equalsIgnoreCase("true");
//check properties file
} else {
TTGlyph.useHinting = !propValue.isEmpty() && propValue.equalsIgnoreCase("true");
}
//Set icon location
propValue = properties.getValue("iconLocation");
if (!propValue.isEmpty() && GUI.debugFX) {
System.out.println("guiCursor is not set to JavaFXCursor in method init() in class JavaFxGUI.java");
}
//guiCursor.setIconLocation(propValue);
} catch (final Exception e) {
e.printStackTrace();
}
//setup combo boxes
setupComboBoxes();
if(LogWriter.isRunningFromIDE || org.jpedal.DevFlags.GUITESTINGINPROGRESS){
nameElements();
}
//Initialise the Swing Buttons *
fxButtons.init(isSingle);
//create a menu bar and add to display
createTopMenuBar();
//create other tool bars and add to display
createOtherToolBars();
//set colours on display boxes and add listener to page number
setupBottomToolBarItems();
//sets up all the toolbar items
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.openFile"), "open.gif", Commands.OPENFILE, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
if (searchFrame != null && (searchFrame.getViewStyle() == GUISearchWindow.SEARCH_EXTERNAL_WINDOW || (searchFrame.getViewStyle() == GUISearchWindow.SEARCH_MENU_BAR && !isSingle))) {
searchFrame.setViewStyle(GUISearchWindow.SEARCH_EXTERNAL_WINDOW);
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.search"), "find.gif", Commands.FIND, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
}
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.properties"), "properties.gif", Commands.DOCINFO, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
if (commonValues.getModeOfOperation() == Values.RUNNING_PLUGIN) {
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.about"), "about.gif", Commands.ABOUT, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
}
//snapshot screen function
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.snapshot"), "snapshot.gif", Commands.SNAPSHOT, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
final Separator sep = new Separator();
sep.setPrefSize(5, 32);
//combo boxes on toolbar
addCombo(Messages.getMessage("PdfViewerToolbarTooltip.zoomin"), Commands.SCALING);
addCombo(Messages.getMessage("PdfViewerToolbarTooltip.rotation"), Commands.ROTATION);
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.mouseMode"), "mouse_select.png", Commands.MOUSEMODE, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
fxButtons.getTopButtons().getItems().add(sep);
if(includeExtraMenus && commonValues.getModeOfOperation() != Values.RUNNING_PLUGIN) {
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.help"), "help.png", Commands.HELP, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
}
//addButton(GUIFactory.BUTTONBAR,Messages.getMessage("PdfViewerToolbarTooltip.buy"),iconLocation+"buy.png",Commands.BUY);
if(includeExtraMenus && commonValues.getModeOfOperation() != Values.RUNNING_PLUGIN) {
fxButtons.addButton(GUIFactory.BUTTONBAR, "RSS", "rss.gif", Commands.RSS, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
}
//add cursor location
initMultiBox();
//navigation toolbar for moving between pages
createNavbar();
if (searchFrame != null && searchFrame.getViewStyle() == GUISearchWindow.SEARCH_MENU_BAR && isSingle) {
searchInMenu(searchFrame);
}
//status object on toolbar showing 0 -100 % completion
initStatus();
/*
* Ensure all gui sections are displayed correctly
* Issues found when removing some sections
*/
if (GUI.debugFX) {
System.out.println("Swing specific invalidate(), validate(), repaint() not implemented for JavaFX in JavaFxGUI");
}
/*
* set display to occupy half screen size and display, add listener and
* make sure appears in centre
*/
if (commonValues.getModeOfOperation() != Values.RUNNING_APPLET) {
//Load width and height from properties file
int width = Integer.parseInt(properties.getValue("startViewerWidth"));
int height = Integer.parseInt(properties.getValue("startViewerHeight"));
//Used to prevent infinite scroll issue as a preferred size has been set
//Used to prevent infinite scroll issue as a preferred size has been set
final Rectangle2D d = Screen.getPrimary().getVisualBounds();
if (width < 0) {
width = ((int) d.getWidth()) / 2;
if (width < minimumScreenWidth) {
width = minimumScreenWidth;
}
properties.setValue("startViewerWidth", String.valueOf(width));
}
if (height < 0) {
height = ((int) d.getHeight()) / 2;
properties.setValue("startViewerHeight", String.valueOf(height));
}
//allow user to alter size
final String customWindowSize = System.getProperty("org.jpedal.startWindowSize");
if (customWindowSize != null) {
final StringTokenizer values = new StringTokenizer(customWindowSize, "x");
System.out.println(values.countTokens());
if (values.countTokens() != 2) {
throw new RuntimeException("Unable to use value for org.jpedal.startWindowSize=" + customWindowSize + "\nValue should be in format org.jpedal.startWindowSize=200x300");
}
try {
width = Integer.parseInt(values.nextToken().trim());
height = Integer.parseInt(values.nextToken().trim());
} catch (final Exception ee) {
throw new RuntimeException("Unable to use value for org.jpedal.startWindowSize=" + customWindowSize + "\nValue should be in format org.jpedal.startWindowSize=200x300 " + ee);
}
}
setupPDFDisplayPane();
// add the pdf display left and right panes
setupBorderPanes();
createMainViewerWindow(width, height);
}
//Add Background color to the JavaFX panel to help break up view
setupCenterPanelBackground();
setupPDFBorder();
//Set side tab bar state at start up
if (sideTabBarOpenByDefault) {
setSplitDividerLocation(expandedSize);
tabsExpanded = true;
} else {
setSplitDividerLocation(collapsedSize);
tabsExpanded = false;
}
//Load properties
try {
GUIModifier.load(properties, this);
} catch (final Exception e) {
e.printStackTrace();
}
//DELETE This code block once all items are implemented.
//This code is here so the loading of properties does not override
//the disabling of unimplemented items in the FXViewer.
final int ALL = -10;
((JavaFXMenuItems) menuItems).disableUnimplementedItems(ALL, false);
fxButtons.disableUnimplementedItems(ALL);
}
private void nameElements() {
((JavaFXMenuItems) menuItems).getCurrentMenuFX().setId("menuBar");
pageCounter2.setId("pageCounter");
if (org.jpedal.DevFlags.GUITESTINGINPROGRESS) {
rotationBox.setName("rotationBox");
scalingBox.setName("scalingBox");
}
}
/**
* method being called from within init to create other tool bars to add to
* display
*/
@Override
protected void createOtherToolBars() {
if (GUI.debugFX) {
System.out.println("createOtherToolBars almost finished for JavaFX");
}
//This is where we setup the top most menu
menuItems.createMainMenu(true, currentCommandListener, isSingle, commonValues, currentCommands, fxButtons);
topPane.getChildren().add(((JavaFXMenuItems) menuItems).getCurrentMenuFX());
//This is where we add the Buttons for the top ToolBar
topPane.getChildren().add(fxButtons.getTopButtons());
}
private void handleTabbedPanes() {
if (tabsNotInitialised) {
return;
}
if (debugFX) {
System.out.println("handleTabbedPanes");
}
final int tabSelected;
tabSelected = navOptionsPanel.getSelectionModel().getSelectedIndex();
if (tabSelected == -1) {
return;
}
if (!tabsExpanded) {
//workout selected tab
final String tabName = navOptionsPanel.getTabs().get(tabSelected).getText();
// if(DecoderOptions.isRunningOnMac){
// tabName=navOptionsPanelFX.getTabs().get(tabSelected).getText();
// } else
// tabName=navOptionsPanelFX.getTabs().get(tabSelected).getGraphic().toString();
if (tabName != null && tabName.equals(pageTitle)) {
thumbnails.setIsDisplayedOnscreen(true);
} else {
thumbnails.setIsDisplayedOnscreen(false);
}
// Don't expand on dummy tab
if (!navOptionsPanel.getSelectionModel().getSelectedItem().isDisable()) {
setSplitDividerLocation(expandedSize);
tabsExpanded = true;
}
} else if (lastTabSelected == tabSelected && !hasPageChanged) {
setSplitDividerLocation(collapsedSize);
tabsExpanded = false;
thumbnails.setIsDisplayedOnscreen(false);
}
lastTabSelected = tabSelected;
hasPageChanged = false;
}
private void initMultiBox() {
multiboxfx = new HBox();
initCoordBox();
initMemoryBar();
initDownloadBar();
// Temp code to demonstrate functionality - move to JavaFXMouseListener when implmented
// Show coords
// ((PdfDecoderFX)decode_pdf).setOnMouseEntered(new EventHandler(){
// @Override
// public void handle(javafx.scene.input.MouseEvent t) {
// System.out.println(t.getX() + " " + t.getY());
// if(t.getX() < 0){
// t.consume();
// return;
// }
// cursorOverPage = true;
// memoryBarFX.setVisible(false);
// coordsFX.setVisible(true);
// setMultibox(new int[]{});
// }
// });
// Show memory bar
// ((PdfDecoderFX)decode_pdf).setOnMouseExited(new EventHandler(){
// @Override
// public void handle(javafx.scene.input.MouseEvent t) {
// cursorOverPage = false;
// memoryBarFX.setVisible(true);
// coordsFX.setVisible(false);
// setMultibox(new int[]{});
// }
// });
// ((PdfDecoderFX)decode_pdf).setOnMouseMoved(new EventHandler() {
// @Override
// public void handle(javafx.scene.input.MouseEvent t) {
// double maxX = (((PdfDecoderFX)decode_pdf).getBoundsInLocal().getMaxX()) + (dropshadowDepth /2);
// double maxY = (((PdfDecoderFX)decode_pdf).getBoundsInLocal().getMaxY()) + (dropshadowDepth /2);
// double minX = ((PdfDecoderFX)decode_pdf).getBoundsInLocal().getMinX() + (dropshadowDepth /2);
// double minY = ((PdfDecoderFX)decode_pdf).getBoundsInLocal().getMinY() + (dropshadowDepth /2);
//
// if(!cursorOverPage){
// if((t.getX() > minX && t.getX() <= maxX)
// && (t.getY() > minY && t.getY() <= maxY)){
// cursorOverPage = true;
// memoryBarFX.setVisible(false);
// coordsFX.setVisible(true);
// setMultibox(new int[]{});
// }
// }else{
// if((t.getX() < minX || t.getX() > maxX)
// || (t.getY() < minY || t.getY() >= maxY)){
// cursorOverPage = false;
// memoryBarFX.setVisible(true);
// coordsFX.setVisible(false);
// setMultibox(new int[]{});
// }
// }
// //(String.format("X: %d Y: %d", (int)(t.getX() - minX), (int)(t.getY() - minY)));
// }
// });
// multiboxfx.getChildren().add(memoryBarFX);
}
@Override
public void setMultibox(final int[] flags) {
//debug code for formclicktests
if (GUI.alwaysShowMouse) {
multiboxfx.getChildren().clear();
multiboxfx.getChildren().add(coordsFX);
return;
}
//deal with flags
if (flags.length > 1 && flags[0] == CURSOR) {
//if no change, return
if (cursorOverPage != (flags[1] == 1)) {
cursorOverPage = flags[1] == 1;
} else {
return;
}
}
//LOAD_PROGRESS:
// if (statusBar.isEnabled() && statusBar.isVisible() && !statusBar.isDone()) {
// multibox.removeAll();
// statusBar.getStatusObject().setSize(multibox.getSize());
// multibox.add(statusBar.getStatusObject(), BorderLayout.CENTER);
//
// multibox.repaint();
// return;
// }
//CURSOR:
if (cursorOverPage && decode_pdf.isOpen()) {
multiboxfx.getChildren().clear();
multiboxfx.getChildren().add(coordsFX);
return;
}
//DOWNLOAD_PROGRESS:
if (!downloadBar.isDisable() && downloadBar.isVisible() && !downloadBar.isDone() && (decode_pdf.isLoadingLinearizedPDF() || !decode_pdf.isOpen())) {
multiboxfx.getChildren().clear();
multiboxfx.getChildren().add(downloadBar.getStatusObject());
return;
}
//MEMORY:
if (memoryBarFX.isVisible()) {
multiboxfx.getChildren().clear();
multiboxfx.getChildren().add(memoryBarFX);
}
}
private void initDownloadBar() {
downloadBar = new StatusBarFX(new Color((185.0d / 255.0d), (209.0d / 255.0d), 0, 1));
downloadBar.getStatusObject().prefHeightProperty().bind(multiboxfx.heightProperty());
downloadBar.getStatusObject().prefWidthProperty().bind(multiboxfx.widthProperty());
downloadBar.setVisible(false);
}
private void initMemoryBar() {
memoryBarFX = new FXProgressBarWithText();
memoryBarFX.prefHeightProperty().bind(multiboxfx.heightProperty());
memoryBarFX.prefWidthProperty().bind(multiboxfx.widthProperty());
if (memoryMonitor == null) { //ensure only 1 instance
memoryMonitor = new Timeline(new KeyFrame(Duration.seconds(0.5), new EventHandler() {
@Override
public void handle(final ActionEvent event) {
final int free = (int) (Runtime.getRuntime().freeMemory() / (1024 * 1024));
final int total = (int) (Runtime.getRuntime().totalMemory() / (1024 * 1024));
final double used = (total - free) / total;
//this broke the image saving when it was run every time
if (finishedDecoding) {
finishedDecoding = false;
}
if (Platform.isFxApplicationThread()) {
memoryBarFX.setProgress(used);
memoryBarFX.setText((total - free) + "M of " + total + 'M');
} else {
// Needs to be done on the FX Thread
Platform.runLater(new Runnable() {
@Override
public void run() {
memoryBarFX.setProgress(used);
memoryBarFX.setText((total - free) + "M of " + total + 'M');
}
});
}
}
}));
memoryMonitor.setCycleCount(Timeline.INDEFINITE);
memoryMonitor.play();
}
}
/**
* Overrides method from GUI.java, see GUI.java for DOCS.
*/
@Override
protected void setViewerIcon() {
//Check if file location provided
final URL path = guiCursor.getURLForImage("icon.png");
if (stage != null && path != null) {
try {
//Converting Swing BufferedImage to FX WritableImage
final BufferedImage bi = ImageIO.read(path);
WritableImage fontIcon = new WritableImage(bi.getWidth(), bi.getHeight());
fontIcon = SwingFXUtils.toFXImage(bi, fontIcon);
stage.getIcons().add(fontIcon);
} catch (final Exception e) {
LogWriter.writeLog("Exception attempting to set Icon " + e);
}
}
}
private boolean setDisplayView2(final int displayView, final int orientation) {
DecoderOptions options = decode_pdf.getDecoderOptions();
Display pages = decode_pdf.getPages();
int lastDisplayView = decode_pdf.getDisplayView();
FileAccess fileAccess = (FileAccess) decode_pdf.getExternalHandler(Options.FileAccess);
int pageNumber = decode_pdf.getPageNumber();
ExternalHandlers externalHandlers = decode_pdf.getExternalHandler();
final PdfDecoderFX comp = (PdfDecoderFX) decode_pdf;
final Pane highlightsPane = comp.highlightsPane;
options.setPageAlignment(orientation);
if (pages != null) {
pages.stopGeneratingPage();
}
if (Platform.isFxApplicationThread()) {
if (highlightsPane != null && highlightsPane.getParent() != null) {
((Group) highlightsPane.getParent()).getChildren().remove(highlightsPane);
}
} else {
final Runnable doPaintComponent = new Runnable() {
@Override
public void run() {
if (highlightsPane != null && highlightsPane.getParent() != null) {
((Group) highlightsPane.getParent()).getChildren().remove(highlightsPane);
}
}
};
Platform.runLater(doPaintComponent);
}
final boolean hasChanged = displayView != lastDisplayView;
options.setDisplayView(displayView);
if (lastDisplayView != displayView && lastDisplayView == Display.PAGEFLOW) {
pages.dispose();
}
final Object customFXHandle = externalHandlers.getExternalHandler(Options.MultiPageUpdate);
switch (displayView) {
case Display.SINGLE_PAGE:
if (pages == null || hasChanged) {
final DynamicVectorRenderer currentDisplay = decode_pdf.getDynamicRenderer();
pages = new SingleDisplayFX(pageNumber, currentDisplay, comp, options);
}
break;
case Display.PAGEFLOW:
if (pages instanceof PageFlowDisplayFX) {
return hasChanged;
}
if (lastDisplayView != Display.SINGLE_PAGE) {
setDisplayView(Display.SINGLE_PAGE, 0);
setDisplayView(Display.PAGEFLOW, 0);
return hasChanged;
}
pages = new PageFlowDisplayFX((GUIFactory) customFXHandle, comp);
break;
}
/*
* setup once per page getting all page sizes and working out settings
* for views
*/
if (fileAccess.getOffset() == null) {
fileAccess.setOffset(new PageOffsets(decode_pdf.getPageCount(), decode_pdf.getPdfPageData()));
}
pages.setup(options.useHardwareAcceleration(), fileAccess.getOffset());
final DynamicVectorRenderer currentDisplay = decode_pdf.getDynamicRenderer();
if (decode_pdf.isOpen()) {
pages.init(scaling, decode_pdf.getDisplayRotation(), pageNumber, currentDisplay, true);
}
// force redraw
pages.forceRedraw();
pages.refreshDisplay();
//needs to be realigned (in longer term refactored out)
comp.pages = pages;
return hasChanged;
}
/**
* set view mode used in panel and redraw in new mode
* SINGLE_PAGE,CONTINUOUS,FACING,CONTINUOUS_FACING delay is the time in
* milli-seconds which scrolling can stop before background page drawing
* starts Multipage views not in OS releases
*/
@Override
public void setDisplayView(final int displayView, final int orientation) {
// remove listener if setup
if (viewListener != null) {
removeComponentListener(viewListener);
viewListener.dispose();
viewListener = null;
}
boolean hasChanged = setDisplayView2(displayView, orientation);
//move to correct page
final int pageNumber = decode_pdf.getPageNumber();
if (pageNumber > 0) {
if (hasChanged && displayView == Display.SINGLE_PAGE && decode_pdf.isOpen()) {
try {
decode_pdf.getPages().getYCordForPage(pageNumber, scaling);
decode_pdf.setPageParameters(scaling, pageNumber, decode_pdf.getDisplayRotation());
//@swing
// invalidate();
// updateUI();
decode_pdf.decodePage(pageNumber);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
} else if (displayView == Display.CONTINUOUS || displayView == Display.CONTINUOUS_FACING) {
try {
decode_pdf.getPages().getYCordForPage(pageNumber, scaling);
decode_pdf.setPageParameters(scaling, pageNumber, decode_pdf.getDisplayRotation());
decode_pdf.decodePage(pageNumber);
scrollToPage(pageNumber);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
//Only all search in certain modes
if (displayView != Display.SINGLE_PAGE
&& displayView != Display.CONTINUOUS
&& displayView != Display.CONTINUOUS_FACING) {
enableSearchItems(false);
} else {
enableSearchItems(true);
}
// add listener if one not already there
if (viewListener == null) {
viewListener = new RefreshLayout(decode_pdf);
addComponentListener(viewListener);
}
}
/**
* Overrides method from GUI.java, see GUI.java for DOCS.
*/
@Override
protected void setTitle(final String title) {
if (stage != null) {
stage.setTitle(title);
}
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#resetComboBoxes(boolean)
*/
@Override
public void resetComboBoxes(final boolean value) {
if (debugFX) {
System.out.println("resetComboBoxes");
}
scalingBox.setEnabled(value);
rotationBox.setEnabled(value);
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#getCombo(int)
*/
@Override
public GUICombo getCombo(final int ID) {
if (debugFX) {
System.out.println("getCombo");
}
switch (ID) {
case Commands.SCALING:
return scalingBox;
case Commands.ROTATION:
return rotationBox;
}
return null;
}
/**
* all scaling and rotation should go through this.
*/
@Override
public void scaleAndRotate() {
if (decode_pdf.getDisplayView() == Display.PAGEFLOW) {
decode_pdf.setPageParameters(scaling, commonValues.getCurrentPage(), rotation);
return;
}
//ignore if called too early
if (!decode_pdf.isOpen() && OpenFile.isPDf) {
return;
}
final double width = pageContainer.getViewportBounds().getWidth() * 0.95;
final double height = pageContainer.getViewportBounds().getHeight() * 0.95;
float tempScaling = 1.5f;
// if(sudaDebug){
// System.out.println("scaleAndRotate");
// System.out.println("\tScaling "+scaling);
// System.out.println("\tbar: "+pageContainer.getViewportBounds());
// System.out.println("\tGL: "+group.getBoundsInLocal());
// System.out.println("\tGP: "+group.getBoundsInParent());
// }
//update value and GUI
if (decode_pdf != null) {
for(int i=0;i commonValues.getPageCount() || leftPage == 1) {
cw *= 2;
} else {
cw += pageData.getCropBoxHeight(leftPage + 1);
}
ch = pageData.getCropBoxWidth(leftPage);
if (leftPage + 1 <= commonValues.getPageCount() && ch < pageData.getCropBoxWidth(leftPage + 1)) {
ch = pageData.getCropBoxWidth(leftPage + 1);
}
} else {
cw = pageData.getCropBoxWidth(leftPage);
//if first or last page double the width, otherwise add other page width
if (leftPage + 1 > commonValues.getPageCount()) {
cw *= 2;
} else {
cw += pageData.getCropBoxWidth(leftPage + 1);
}
ch = pageData.getCropBoxHeight(leftPage);
if (leftPage + 1 <= commonValues.getPageCount() && ch < pageData.getCropBoxHeight(leftPage + 1)) {
ch = pageData.getCropBoxHeight(leftPage + 1);
}
}
break;
default:
if (isRotated) {
cw = pageData.getCropBoxHeight(commonValues.getCurrentPage());
ch = pageData.getCropBoxWidth(commonValues.getCurrentPage());
} else {
cw = pageData.getCropBoxWidth(commonValues.getCurrentPage());
ch = pageData.getCropBoxHeight(commonValues.getCurrentPage());
}
}
float x_factor;
float y_factor;
final float window_factor;
x_factor = width / cw;
y_factor = height / ch;
if (x_factor < y_factor) {
window_factor = x_factor;
x_factor = -1;
} else {
window_factor = y_factor;
y_factor = -1;
}
if (getSelectedComboIndex(Commands.SCALING) != 0
&& ((newScaling < window_factor * 1.1 && newScaling > window_factor * 0.91)
|| ((window_factor > scaling && window_factor < newScaling) || (window_factor < scaling && window_factor > newScaling)))) {
setSelectedComboIndex(Commands.SCALING, 0);
scaling = window_factor;
} else if (y_factor != -1
&& getSelectedComboIndex(Commands.SCALING) != 1
&& ((newScaling < y_factor * 1.1 && newScaling > y_factor * 0.91)
|| ((y_factor > scaling && y_factor < newScaling) || (y_factor < scaling && y_factor > newScaling)))) {
setSelectedComboIndex(Commands.SCALING, 1);
scaling = y_factor;
} else if (x_factor != -1
&& getSelectedComboIndex(Commands.SCALING) != 2
&& ((newScaling < x_factor * 1.1 && newScaling > x_factor * 0.91)
|| ((x_factor > scaling && x_factor < newScaling) || (x_factor < scaling && x_factor > newScaling)))) {
setSelectedComboIndex(Commands.SCALING, 2);
scaling = x_factor;
} else {
setSelectedComboItem(Commands.SCALING, String.valueOf((int) decode_pdf.getDPIFactory().removeScaling(newScaling * 100)));
scaling = newScaling;
}
}
/* (non-Javadoc)
* @see org.jpedal.examples.viewer.gui.swing.GUIFactory#rotate()
*/
@Override
public void rotate() {
rotation = Integer.parseInt((String) getSelectedComboItem(Commands.ROTATION));
scaleAndRotate();
}
@Override
public void scrollToPage(final int page) {
if (debugFX) {
System.out.println("scrollToPage");
}
commonValues.setCurrentPage(page);
if (commonValues.getCurrentPage() > 0) {
//int xCord = 0;
int pageCount = decode_pdf.getPageCount();
double yCord;// = decode_pdf.getPages().getYCordForPage(page, scaling);
//$$$$$$$$$$$$$ call it and ignore please dont delete as it has affect in continuous mode
decode_pdf.getPages().getYCordForPage(page, scaling);
// if (decode_pdf.getDisplayView() != Display.SINGLE_PAGE) {
// xCord = 0;
//}
//System.out.println("Before="+decode_pdf.getVisibleRect()+" "+decode_pdf.getPreferredSize());
final PdfPageData pageData = decode_pdf.getPdfPageData();
//final int ch = (int) (pageData.getCropBoxHeight(page) * scaling);
//final int cw = (int) (pageData.getCropBoxWidth(page) * scaling);
double totalHeight = 0;
//int pw = pageData.getScaledCropBoxWidth(page);
//int ph = pageData.getScaledCropBoxHeight(page);
//double localH = pageContainer.getContent().getBoundsInLocal().getHeight();
//double localW = pageContainer.getContent().getBoundsInLocal().getWidth();
//double viewH = pageContainer.getViewportBounds().getHeight();
//double viewW = pageContainer.getViewportBounds().getWidth();
double vv;
switch (decode_pdf.getDisplayView()) {
case Display.SINGLE_PAGE:
break;
case Display.CONTINUOUS:
yCord = 0;
for (int i = 1; i < pageCount; i++) {
totalHeight+= pageData.getScaledCropBoxHeight(i);
}
for (int i = 1; i < page; i++) {
yCord+= pageData.getScaledCropBoxHeight(i);
}
vv = yCord/totalHeight;
pageContainer.setVvalue(vv);//
break;
case Display.CONTINUOUS_FACING:
yCord = 0;
for (int i = 1; i < pageCount; i+=2) {
totalHeight+= pageData.getScaledCropBoxHeight(i);
}
for (int i = 1; i < page; i+=2) {
yCord+= pageData.getScaledCropBoxHeight(i);
}
vv = yCord/totalHeight;
pageContainer.setVvalue(vv);//
break;
}
}
if (decode_pdf.getPageCount() > 1) {
fxButtons.setPageLayoutButtonsEnabled(true);
}
}
@Override
public void setupThumbnailPanel() {
if (debugFX) {
System.out.println("setupThumbnailPanel");
}
decode_pdf.addExternalHandler(thumbnails, Options.ThumbnailHandler);
if (isSetup) {
return;
}
isSetup = true;
if (thumbnails.isShownOnscreen()) {
//setup and add to display
thumbnails.setupThumbnails(decode_pdf.getPageCount(), null, decode_pdf.getPdfPageData());
//add listener so clicking on button changes to page - has to be in Viewer so it can update it
final Button[] buttons = (Button[]) thumbnails.getButtons();
for (int i = 0; i < commonValues.getPageCount(); i++) {
buttons[i].setOnAction(new JavaFXPageChanger(this, commonValues, i));
}
//add global listener
thumbnails.addComponentListener();
}
}
@Override
public void setBookmarks(final boolean alwaysGenerate) {
if (debugFX) {
System.out.println("setBookmarks");
//ignore if not opened
System.out.println("currentSize in setBookmarks() in JavaFXGUI requires JavaFX implementation");
}
// int currentSize=center.getDividerPosition();
//
// if((currentSize==startSize)&& !alwaysGenerate)
// return;
//ignore if already done and flag
if (bookmarksGenerated) {
return;
}
bookmarksGenerated = true;
final org.w3c.dom.Document doc = decode_pdf.getOutlineAsXML();
Node rootNode = null;
if (doc != null) {
rootNode = doc.getFirstChild();
}
if (rootNode != null) {
tree.reset(rootNode);
// Allows an already selected node to be clicked again
final EventHandler reselectionListener = new EventHandler() {
@Override
public void handle(final MouseEvent event) {
final String ref = ((JavaFXOutline.OutlineNode) ((javafx.scene.Node) event.getSource()).getUserData()).getObjectRef();
gotoPageByRef(ref);
}
};
((TreeView
© 2015 - 2024 Weber Informatics LLC | Privacy Policy