
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-2015 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 org.jpedal.utils.BrowserLauncher;
import java.awt.Rectangle;
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.Bounds;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.Labeled;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.Separator;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.control.ToolBar;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
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.Background;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.TextAlignment;
import javafx.scene.transform.Transform;
import javafx.stage.*;
import javafx.util.Duration;
import javax.imageio.ImageIO;
import org.jpedal.*;
import org.jpedal.display.*;
import org.jpedal.display.javafx.*;
import org.jpedal.examples.viewer.Commands;
import org.jpedal.examples.viewer.JavaFXRecentDocuments;
import org.jpedal.examples.viewer.RecentDocumentsFactory;
import org.jpedal.examples.viewer.Values;
import org.jpedal.examples.viewer.commands.OpenFile;
import org.jpedal.examples.viewer.commands.javafx.JavaFXOpenFile;
import org.jpedal.examples.viewer.gui.generic.GUIButtons;
import org.jpedal.examples.viewer.gui.generic.GUICombo;
import org.jpedal.examples.viewer.gui.generic.GUIMenuItems;
import org.jpedal.examples.viewer.gui.generic.GUIMouseHandler;
import org.jpedal.examples.viewer.gui.generic.GUISearchList;
import org.jpedal.examples.viewer.gui.generic.GUISearchWindow;
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.gui.popups.PrintPanelFX;
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.external.RenderChangeListener;
import org.jpedal.fonts.tt.TTGlyph;
import org.jpedal.gui.*;
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.*;
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 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;
/**user dir in which program can write*/
private String user_dir = System.getProperty( "user.dir" );
/**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;
/**Interactive display object - needs to be added to PdfDecoder*/
// private StatusBarFX statusBar=new StatusBarFX(new Color((235.0d/255.0d), (154.0d/255.0d), 0, 1));
private StatusBarFX downloadBar;
private boolean addSearchTab;
private boolean searchInMenu;
private TextField searchText;
private GUISearchList results;
private MenuBar options;
private boolean cursorOverPage;
private PrintPanelFX printPanel;
//
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);
}
@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());
}
/**
* setup display
*/
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);
/**
* setup display multiview display
*/
// if (isSingle) {
// desktopPane.setBackground(frame.getBackground());
// desktopPane.setVisible(true);
// if(frame instanceof JFrame)
// ((JFrame)frame).getContentPane().add(desktopPane, BorderLayout.CENTER);
// else
// frame.add(desktopPane, BorderLayout.CENTER);
//
// }
}
@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 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 >> 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;
}
/**
* display form data in popup
*
private class ShowFormDataListener implements ActionListener{
private String formName;
public ShowFormDataListener(String formName){
this.formName=formName;
}
public void actionPerformed(ActionEvent e) {
//will return Object or Object[] if multiple items of same name
Object[] values=decode_pdf.getFormRenderer().getCompData().getRawForm(formName);
int count=values.length;
JTabbedPane valueDisplay=new JTabbedPane();
for(int jj=0;jj() {
@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, final Object currentPrinter) {
if (debugFX) {
System.out.println("init");
}
updateTransitionType();
mouseHandler = new JavaFXMouseListener((PdfDecoderFX)decode_pdf, this, commonValues, currentCommands);
mouseHandler.setupMouse();
super.init(currentCommands);
/**
* Set up from properties
*/
try {
//Set whether to use hinting
propValue = properties.getValue("useHinting");
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();
//
/**
* 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();
/**
* Menu bar for using the majority of functions
*/
//menuItems.createMainMenu(true, currentCommandListener, isSingle, commonValues, currentCommands, fxButtons);
//createSwingMenu(true);
/**
* sets up all the toolbar items
*/
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.openFile"), "open.gif", Commands.OPENFILE, menuItems, this, currentCommandListener, pagesToolBar, navToolBar);
fxButtons.addButton(GUIFactory.BUTTONBAR, Messages.getMessage("PdfViewerToolbarTooltip.print"), "print.gif", Commands.PRINT, 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("PdfViewerToolbarScaling.text"), Messages.getMessage("PdfViewerToolbarTooltip.zoomin"), Commands.SCALING);
addCombo(Messages.getMessage("PdfViewerToolbarRotation.text"), 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);
//
/**add cursor location*/
initMultiBox();
/**
* navigation toolbar for moving between pages
*/
createNavbar();
// p.setButtonDefaults(defaultValues);
//
/**
* external/itext button option example adding new option to Export menu
* an icon is set wtih location on classpath
* "/org/jpedal/examples/viewer/res/newfunction.gif"
* Make sure it exists at location and is copied into jar if recompiled
*/
//currentGUI.addButton(currentGUI.BUTTONBAR,tooltip,"/org/jpedal/examples/viewer/res/newfunction.gif",Commands.NEWFUNCTION);
/**
* external/itext menu option example adding new option to Export menu
* Tooltip text can be externalised in Messages.getMessage("PdfViewerTooltip.NEWFUNCTION")
* and text added into files in res package
*/
if (searchFrame != null && searchFrame.getViewStyle() == GUISearchWindow.SEARCH_MENU_BAR && isSingle) {
searchInMenu(searchFrame);
}
/**status object on toolbar showing 0 -100 % completion */
initStatus();
// p.setDisplayDefaults(defaultValues);
//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");
}
//frame.invalidate();
//frame.validate();
//frame.repaint();
/////////////////////////////////////
//
/**
//
//
/**/
/**
* 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);
}
}
/**
* add the pdf display to show page
*/
setupPDFDisplayPane(width, height);
/**
* 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();
//@Simon temp
//initThumbnails();
//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);
}
//
/**
* 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");
}
/**
* expand size if not already at size
*/
//int currentSize=displayPane.getDividerLocation();
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) {
//
//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 = (double) (total - free) / (double) 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) {
//
if (LogWriter.isOutput()) {
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);
}
boolean needsReset = (displayView != Display.SINGLE_PAGE || lastDisplayView != Display.SINGLE_PAGE);
if (needsReset && (lastDisplayView == Display.FACING || displayView == Display.FACING)) {
needsReset = false;
}
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;
/**/
default:
//
break;
}
/**
* enable pageFlow mode and setup slightly different display configuration
*/
if (lastDisplayView == Display.PAGEFLOW && displayView != Display.PAGEFLOW) {
//@swing
/*
removeAll();
//forms needs null layout manager
this.setLayout(null);
((JScrollPane)getParent().getParent()).setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
((JScrollPane)getParent().getParent()).setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
javax.swing.Timer t = new javax.swing.Timer(1000,new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
t.setRepeats(false);
t.start();
/**/
}
/**
* 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.setPageParameters(scaling, pageNumber, decode_pdf.getDisplayRotation());
//@swing
// invalidate();
// updateUI();
decode_pdf.decodePage(pageNumber);
} catch (final Exception e) {
//tell user and log
if(LogWriter.isOutput()) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
//
}
} else if (displayView != Display.SINGLE_PAGE && displayView != Display.PAGEFLOW) {
scrollToPage(pageNumber);
}
}
//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");
}
if(properties.getValue("Imageopdisplay").equalsIgnoreCase("true")) {
qualityBox.setEnabled(value);
}
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.QUALITY:
return qualityBox;
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;
final double height;
//if (isSingle) {
width = pageContainer.getViewportBounds().getWidth() - inset - inset;
height = pageContainer.getViewportBounds().getHeight() - inset - inset;
//} else {
// width = desktopPane.getSelectedFrame().getWidth();
// height = desktopPane.getSelectedFrame().getHeight();
//}
/**
* update value and GUI
*/
if (decode_pdf != null) {
int index = getSelectedComboIndex(Commands.SCALING);
if (decode_pdf.getDisplayView() == Display.PAGEFLOW) {
//Ensure we only display in window mode
setSelectedComboIndex(Commands.SCALING, 0);
index = 0;
//Disable scaling option
scalingBox.setEnabled(false);
} else if (decode_pdf.getDisplayView() != Display.PAGEFLOW) {
//No long pageFlow. enable scaling option
scalingBox.setEnabled(true);
}
if (index == -1) {
String numberValue = (String) getSelectedComboItem(Commands.SCALING);
float zoom = -1;
if ((numberValue != null) && (!numberValue.isEmpty())) {
try {
zoom = Float.parseFloat(numberValue);
} catch (final Exception e) {
if(LogWriter.isOutput()) {
LogWriter.writeLog("Exception in getting zoom "+e);
}
zoom = -1;
//its got characters in it so get first valid number string
final int length = numberValue.length();
int ii = 0;
while (ii < length) {
final char c = numberValue.charAt(ii);
if (((c >= '0') && (c <= '9')) | (c == '.')) {
ii++;
} else {
break;
}
}
if (ii > 0) {
numberValue = numberValue.substring(0, ii);
}
//try again if we reset above
if (zoom == -1) {
try {
zoom = Float.parseFloat(numberValue);
} catch (final Exception e1) {
if(LogWriter.isOutput()) {
LogWriter.writeLog("Exception in getting zoom "+e1);
}
zoom = -1;
}
}
}
if (zoom > 1000) {
zoom = 1000;
}
}
//if nothing off either attempt, use window value
if (zoom == -1) {
//its not set so use To window value
index = defaultSelection;
setSelectedComboIndex(Commands.SCALING, index);
} else {
scaling = decode_pdf.getDPIFactory().adjustScaling(zoom / 100);
setSelectedComboItem(Commands.SCALING, String.valueOf(zoom));
}
}
int page = commonValues.getCurrentPage();
//Multipage tiff should be treated as a single page
if (commonValues.isMultiTiff()) {
page = 1;
}
//always check in facing mode with turnover on
if (index != -1 || decode_pdf.getDisplayView() == Display.SINGLE_PAGE || (decode_pdf.getDisplayView() == Display.FACING && decode_pdf.getPages().getBoolean(Display.BoolValue.TURNOVER_ON))) {
final PdfPageData pageData = decode_pdf.getPdfPageData();
int cw, ch, raw_rotation = 0;
if (decode_pdf.getDisplayView() == Display.FACING) {
raw_rotation = pageData.getRotation(page);
}
final boolean isRotated = (rotation + raw_rotation) % 180 == 90;
final PageOffsets offsets = (PageOffsets) decode_pdf.getExternalHandler(Options.CurrentOffset);
switch (decode_pdf.getDisplayView()) {
case Display.CONTINUOUS_FACING:
if (isRotated) {
cw = offsets.getMaxH() * 2;
ch = offsets.getMaxW();
} else {
cw = offsets.getMaxW() * 2;
ch = offsets.getMaxH();
}
break;
case Display.CONTINUOUS:
if (isRotated) {
cw = offsets.getMaxH();
ch = offsets.getMaxW();
} else {
cw = offsets.getMaxW();
ch = offsets.getMaxH();
}
break;
case Display.FACING:
int leftPage;
if (decode_pdf.getPages().getBoolean(Display.BoolValue.SEPARATE_COVER)) {
leftPage = (page / 2) * 2;
if (commonValues.getPageCount() == 2) {
leftPage = 1;
}
} else {
leftPage = (page);
if ((leftPage & 1) == 0) {
leftPage--;
}
}
if (leftPage == 0) {
leftPage++;
}
if (isRotated) {
cw = pageData.getCropBoxHeight(leftPage);
//if first or last page double the width, otherwise add other page width
if (leftPage + 1 > 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(page);
ch = pageData.getCropBoxWidth(page);
} else {
cw = pageData.getCropBoxWidth(page);
ch = pageData.getCropBoxHeight(page);
}
}
final double x_factor;
final double y_factor;
double window_factor;
x_factor = width / cw;
y_factor = height / ch;
if (x_factor < y_factor) {
window_factor = x_factor;
} else {
window_factor = y_factor;
}
if (cw == 0 || ch == 0) {
window_factor = 1;
}
if (index != -1) {
if (index < 3) { //handle scroll to width/height/window
if (index == 0) {//window
scaling = (float) window_factor;
} else if (index == 1)//height
{
scaling = (float) y_factor;
} else if (index == 2)//width
{
scaling = (float) x_factor;
}
} else {
scaling = decode_pdf.getDPIFactory().adjustScaling(scalingFloatValues[index]);
}
}
if (decode_pdf.getDisplayView() == Display.FACING) { //Enable turnover if both pages properly displayed
pageTurnScalingAppropriate = scaling <= window_factor;
}
// Avoid infinty
if(Float.isInfinite(scaling)){
scaling = 1f;
}
// upscale to the scaling and window_factor for rounding (so we can ignore excess precision)
final int upscale = 10000;
if(pageScroll != null){
if(decode_pdf.getDisplayView() == Display.SINGLE_PAGE && (Math.round(scaling * upscale) <= Math.round(window_factor * upscale) )){
pageContainer.setVbarPolicy(ScrollBarPolicy.NEVER);
pageContainer.setHbarPolicy(ScrollBarPolicy.NEVER);
pageScroll.setVisible(true);
// queue it up to run later (avoids excpetions being thrown)
Platform.runLater(new Runnable() {
@Override public void run() {
if(!center.getItems().contains(pageScroll)){
center.getItems().add(pageScroll);
}
}
});
}else{
pageContainer.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
pageContainer.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
pageScroll.setVisible(false);
// queue it up to run later (avoids excpetions being thrown)
Platform.runLater(new Runnable() {
@Override public void run() {
if(center.getItems().contains(pageScroll)){
center.getItems().remove(pageScroll);
}
}
});
}
}
}
decode_pdf.setPageParameters(scaling, page, rotation);
//Ensure the page is displayed in the correct rotation
setRotation();
}
adjustGroupToCenter();
//
}
@Override
public void snapScalingToDefaults(float newScaling) {
if(debugFX){
System.out.println("snapScalingToDefaults");
}
newScaling = decode_pdf.getDPIFactory().adjustScaling(newScaling /100);
final float width;
final float height;
//if(isSingle){
width = (float)pageContainer.getWidth()-inset-inset;
height = (float)pageContainer.getHeight()-inset-inset;
//}else{
// width=desktopPane.getWidth();
// height=desktopPane.getHeight();
//}
final PdfPageData pageData = decode_pdf.getPdfPageData();
int cw,ch,raw_rotation=0;
if (decode_pdf.getDisplayView()==Display.FACING) {
raw_rotation = pageData.getRotation(commonValues.getCurrentPage());
}
final boolean isRotated = (rotation+raw_rotation)%180==90;
final PageOffsets offsets = (PageOffsets)decode_pdf.getExternalHandler(Options.CurrentOffset);
switch(decode_pdf.getDisplayView()) {
case Display.CONTINUOUS_FACING:
if (isRotated) {
cw = offsets.getMaxH()*2;
ch = offsets.getMaxW();
}else{
cw = offsets.getMaxW()*2;
ch = offsets.getMaxH();
}
break;
case Display.CONTINUOUS:
if (isRotated) {
cw = offsets.getMaxH();
ch = offsets.getMaxW();
}else{
cw = offsets.getMaxW();
ch = offsets.getMaxH();
}
break;
case Display.FACING:
int leftPage;
if (decode_pdf.getPages().getBoolean(Display.BoolValue.SEPARATE_COVER)) {
leftPage = (commonValues.getCurrentPage()/2)*2;
if (commonValues.getPageCount() == 2) {
leftPage = 1;
}
} else {
leftPage = commonValues.getCurrentPage();
if ((leftPage & 1)==0) {
leftPage--;
}
}
if (isRotated) {
cw = pageData.getCropBoxHeight(leftPage);
//if first or last page double the width, otherwise add other page width
if (leftPage+1 > 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 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 yCord;
int xCord =0;
yCord = 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);
if(decode_pdf.getDisplayView()!=Display.SINGLE_PAGE){
// final double centerH = xCord + ((cw-pageContainer.getHvalue())/2);
// final double centerV = yCord + (ch-pageContainer.getVvalue())/2;
//
// int[] dim=decode_pdf.getMaxSizeWH();
// //
// System.out.println(">>"+centerH+ " "+centerV+" "+dim[0]+" "+dim[1]);
// pageContainer.setHvalue(centerH/dim[0]);
// pageContainer.setVvalue(centerV/dim[1]);
// final Bounds r = ((PdfDecoderFX)decode_pdf).getBoundsInLocal();
int pw=pageData.getScaledCropBoxWidth(page);
int ph=pageData.getScaledCropBoxHeight(page);
int pageCount=pageData.getPageCount();
// int[] pageW=multiDisplayOptions.getPageW();
// int[] pageH=multiDisplayOptions.getPageH();
//if(!(pw>r.getWidth() || ph>r.getHeight())){
//final ScrollPane customFXHandle= ((JavaFxGUI)decode_pdf.getExternalHandler(Options.MultiPageUpdate)).getPageContainer();
yCord=(int) (yCord+(ph*((float)page/(float)pageCount)));
//yCord=(int) (yCord-((customFXHandle.getLayoutBounds().getHeight()-ph)/2)+(ph*(((float)page)/39)));
// yCord=(int) (yCord-((customFXHandle.getLayoutBounds().getHeight()-ph)/2));
// yCord=(int) ((PdfDecoderFX)decode_pdf).getHeight();
// System.out.println("y="+yCord+" for page "+getPageNumber());
// System.out.println("y="+yCord+" page="+pageNumber+" "+Platform.isFxApplicationThread());
//s scrollRectToVisible(new Rectangle(0, yCord, (int) r.getWidth() - 1, (int) r.getHeight() - 1));
((PdfDecoderFX)decode_pdf).scrollRectToVisible(new Rectangle(0, yCord, pw - 1, ph - 1));
// }
}else{
final double centerH = xCord + ((cw-pageContainer.getHvalue())/2);
final double centerV = yCord + (ch-pageContainer.getVvalue())/2;
pageContainer.setHvalue(centerH);
pageContainer.setVvalue(centerV);
}
// decode_pdf.scrollRectToVisible(new Rectangle(0,(int) (yCord),(int)r.width-1,(int)r.height-1));
// decode_pdf.scrollRectToVisible(new Rectangle(0,(int) (yCord),(int)r.width-1,(int)r.height-1));
//System.out.println("After="+decode_pdf.getVisibleRect()+" "+decode_pdf.getPreferredSize());
//System.out.println("Scroll to page="+commonValues.getCurrentPage()+" "+yCord+" "+(yCord*scaling)+" "+scaling);
}
if(decode_pdf.getPageCount()>1) {
fxButtons.setPageLayoutButtonsEnabled(true);
}
}
//
/**
* put the outline data into a display panel which we can pop up
* for the user - outlines, thumbnails
*
private void createOutlinePanels() {
//boolean hasNavBars=false;
// set up first 10 thumbnails by default. Rest created as needed.
//add if statement or comment out this section to remove thumbnails
setupThumbnailPanel();
// add any outline
setBookmarks(false);
/**
* resize to show if there are nav bars
*
if(hasNavBars){
if(!thumbnails.isShownOnscreen()){
if( !commonValues.isContentExtractor())
navOptionsPanel.setVisible(true);
displayPane.setDividerLocation(divLocation);
//displayPane.invalidate();
//displayPane.repaint();
}
}
}/**/
@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, Messages.getMessage("PdfViewerPageLabel.text"), 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 reselectionListener = new EventHandler() {
@Override public void handle(final MouseEvent event) {
final String ref = ((JavaFXOutline.OutlineNode)((Labeled)event.getSource()).getUserData()).getObjectRef();
gotoPageByRef(ref);
}
};
((TreeView
© 2015 - 2025 Weber Informatics LLC | Privacy Policy