/*
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
// Originally contributed by:
// Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com,
// Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com,
// Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com
package org.apache.fop.render.awt.viewer;
// Java
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.text.DecimalFormat;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FOPException;
import org.apache.fop.render.awt.AWTRenderer;
/**
* AWT Viewer main window.
* Surrounds a PreviewPanel with a bunch of pretty buttons and controls.
*/
public class PreviewDialog extends JFrame {
/** The Translator for localization */
protected Translator translator;
/** The AWT renderer */
protected AWTRenderer renderer;
/** The FOUserAgent associated with this window */
protected FOUserAgent foUserAgent;
/** The JCombobox to rescale the rendered page view */
private JComboBox scale;
/** The JLabel for the process status bar */
private JLabel processStatus;
/** The JLabel information status bar */
private JLabel infoStatus;
/** The main display area */
private PreviewPanel previewPanel;
/** Formats the text in the scale combobox. */
private DecimalFormat percentFormat = new DecimalFormat("###0.0#");
/**
* Creates a new PreviewDialog that uses the given renderer.
* @param foUserAgent the user agent
*/
public PreviewDialog(FOUserAgent foUserAgent) {
renderer = (AWTRenderer) foUserAgent.getRendererOverride();
this.foUserAgent = foUserAgent;
translator = renderer.getTranslator();
//Commands aka Actions
Command printAction = new Command(translator.getString("Menu.Print"), "Print") {
public void doit() {
startPrinterJob(true);
}
};
Command firstPageAction = new Command(translator.getString("Menu.First.page"),
"firstpg") {
public void doit() {
goToFirstPage();
}
};
Command previousPageAction = new Command(translator.getString("Menu.Prev.page"),
"prevpg") {
public void doit() {
goToPreviousPage();
}
};
Command nextPageAction = new Command(translator.getString("Menu.Next.page"), "nextpg") {
public void doit() {
goToNextPage();
}
};
Command lastPageAction = new Command(translator.getString("Menu.Last.page"), "lastpg") {
public void doit() {
goToLastPage();
}
};
Command reloadAction = new Command(translator.getString("Menu.Reload"), "reload") {
public void doit() {
previewPanel.reload();
}
};
Command debugAction = new Command(translator.getString("Menu.Debug"), "debug") {
// TODO use Translator
public void doit() {
previewPanel.debug();
}
};
Command aboutAction = new Command(translator.getString("Menu.About"), "fopLogo") {
public void doit() {
startHelpAbout();
}
};
//set the system look&feel
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.err.println("Couldn't set system look & feel!");
}
setTitle("FOP: AWT-" + translator.getString("Title.Preview"));
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
//Sets size to be 61%x90% of the screen size
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
//Rather frivolous size - fits A4 page width in 1024x768 screen on my desktop
setSize(screen.width * 61 / 100, screen.height * 9 / 10);
//Page view stuff
previewPanel = new PreviewPanel(foUserAgent, renderer);
getContentPane().add(previewPanel, BorderLayout.CENTER);
//Scaling combobox
scale = new JComboBox();
scale.addItem(translator.getString("Menu.Fit.Window"));
scale.addItem(translator.getString("Menu.Fit.Width"));
scale.addItem("25%");
scale.addItem("50%");
scale.addItem("75%");
scale.addItem("100%");
scale.addItem("150%");
scale.addItem("200%");
scale.setMaximumSize(new Dimension(80, 24));
scale.setPreferredSize(new Dimension(80, 24));
scale.setSelectedItem("100%");
scale.setEditable(true);
scale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scaleActionPerformed(e);
}
});
//Menu
setJMenuBar(setupMenu());
// Toolbar
JToolBar toolBar = new JToolBar();
toolBar.add(printAction);
toolBar.add(reloadAction);
toolBar.addSeparator();
toolBar.add(firstPageAction);
toolBar.add(previousPageAction);
toolBar.add(nextPageAction);
toolBar.add(lastPageAction);
toolBar.addSeparator(new Dimension(20, 0));
toolBar.add(new JLabel(translator.getString("Menu.Zoom") + " "));
toolBar.add(scale);
toolBar.addSeparator();
toolBar.add(debugAction);
toolBar.addSeparator();
toolBar.add(aboutAction);
getContentPane().add(toolBar, BorderLayout.NORTH);
// Status bar
JPanel statusBar = new JPanel();
processStatus = new JLabel();
processStatus.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(0, 3, 0, 0)));
infoStatus = new JLabel();
infoStatus.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(0, 3, 0, 0)));
statusBar.setLayout(new GridBagLayout());
processStatus.setPreferredSize(new Dimension(200, 21));
processStatus.setMinimumSize(new Dimension(200, 21));
infoStatus.setPreferredSize(new Dimension(100, 21));
infoStatus.setMinimumSize(new Dimension(100, 21));
statusBar.add(processStatus,
new GridBagConstraints(0, 0, 1, 0, 2.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 3), 0, 0));
statusBar.add(infoStatus,
new GridBagConstraints(1, 0, 1, 0, 1.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0));
getContentPane().add(statusBar, BorderLayout.SOUTH);
}
/**
* Creates a new menubar to be shown in this window.
* @return the newly created menubar
*/
private JMenuBar setupMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu(translator.getString("Menu.File"));
menu.setMnemonic(KeyEvent.VK_F);
//Adds mostly the same actions, but without icons
menu.add(new Command(translator.getString("Menu.Print"), KeyEvent.VK_P) {
public void doit() {
startPrinterJob(true);
}
});
// inputHandler must be set to allow reloading
if (foUserAgent.getInputHandler() != null) {
menu.add(new Command(translator.getString("Menu.Reload"), KeyEvent.VK_R) {
public void doit() {
reload();
}
});
}
menu.addSeparator();
menu.add(new Command(translator.getString("Menu.Exit"), KeyEvent.VK_X) {
public void doit() {
dispose();
}
});
menuBar.add(menu);
menu = new JMenu(translator.getString("Menu.View"));
menu.setMnemonic(KeyEvent.VK_V);
menu.add(new Command(translator.getString("Menu.First.page"), KeyEvent.VK_F) {
public void doit() {
goToFirstPage();
}
});
menu.add(new Command(translator.getString("Menu.Prev.page"), KeyEvent.VK_P) {
public void doit() {
goToPreviousPage();
}
});
menu.add(new Command(translator.getString("Menu.Next.page"), KeyEvent.VK_N) {
public void doit() {
goToNextPage();
}
});
menu.add(new Command(translator.getString("Menu.Last.page"), KeyEvent.VK_L) {
public void doit() {
goToLastPage();
}
});
menu.add(new Command(translator.getString("Menu.Go.to.Page"), KeyEvent.VK_G) {
public void doit() {
showGoToPageDialog();
}
});
menu.addSeparator();
JMenu subMenu = new JMenu(translator.getString("Menu.Zoom"));
subMenu.setMnemonic(KeyEvent.VK_Z);
subMenu.add(new Command("25%", 0) {
public void doit() {
setScale(25.0);
}
});
subMenu.add(new Command("50%", 0) {
public void doit() {
setScale(50.0);
}
});
subMenu.add(new Command("75%", 0) {
public void doit() {
setScale(75.0);
}
});
subMenu.add(new Command("100%", 0) {
public void doit() {
setScale(100.0);
}
});
subMenu.add(new Command("150%", 0) {
public void doit() {
setScale(150.0);
}
});
subMenu.add(new Command("200%", 0) {
public void doit() {
setScale(200.0);
}
});
menu.add(subMenu);
menu.addSeparator();
menu.add(new Command(translator.getString("Menu.Default.zoom"), KeyEvent.VK_D) {
public void doit() {
setScale(100.0);
}
});
menu.add(new Command(translator.getString("Menu.Fit.Window"), KeyEvent.VK_F) {
public void doit() {
setScaleToFitWindow();
}
});
menu.add(new Command(translator.getString("Menu.Fit.Width"), KeyEvent.VK_W) {
public void doit() {
setScaleToFitWidth();
}
});
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem single = new JRadioButtonMenuItem(
new Command(translator.getString("Menu.Single"), KeyEvent.VK_S) {
public void doit() {
previewPanel.setDisplayMode(PreviewPanel.SINGLE);
}
});
JRadioButtonMenuItem cont = new JRadioButtonMenuItem(
new Command(translator.getString("Menu.Continuous"), KeyEvent.VK_C) {
public void doit() {
previewPanel.setDisplayMode(PreviewPanel.CONTINUOUS);
}
});
JRadioButtonMenuItem facing = new JRadioButtonMenuItem(
new Command(translator.getString("Menu.Facing"), 0) {
public void doit() {
previewPanel.setDisplayMode(PreviewPanel.CONT_FACING);
}
});
single.setSelected(true);
group.add(single);
group.add(cont);
group.add(facing);
menu.add(single);
menu.add(cont);
menu.add(facing);
menuBar.add(menu);
menu = new JMenu(translator.getString("Menu.Help"));
menu.setMnemonic(KeyEvent.VK_H);
menu.add(new Command(translator.getString("Menu.About"), KeyEvent.VK_A) {
public void doit() {
startHelpAbout();
}
});
menuBar.add(menu);
return menuBar;
}
public void reload() {
previewPanel.reload();
}
/**
* Changes the current visible page
* @param number the page number to go to
*/
public void goToPage(int number) {
if (number != previewPanel.getPage()) {
previewPanel.setPage(number);
setInfo();
}
}
/**
* Shows the previous page.
*/
public void goToPreviousPage() {
int page = previewPanel.getPage();
if (page > 0) {
goToPage(page - 1);
}
}
/**
* Shows the next page.
*/
public void goToNextPage() {
int page = previewPanel.getPage();
if (page < renderer.getNumberOfPages() - 1) {
goToPage(page + 1);
}
}
/** Shows the first page. */
public void goToFirstPage() {
goToPage(0);
}
/**
* Shows the last page.
*/
public void goToLastPage() {
goToPage(renderer.getNumberOfPages() - 1);
}
/** Shows the About box */
private void startHelpAbout() {
PreviewDialogAboutBox dlg = new PreviewDialogAboutBox(this, translator);
//Centers the box
Dimension dlgSize = dlg.getPreferredSize();
Dimension frmSize = getSize();
Point loc = getLocation();
dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
(frmSize.height - dlgSize.height) / 2 + loc.y);
dlg.setVisible(true);
}
/**
* Shows "go to page" dialog and then goes to the selected page
*/
private void showGoToPageDialog() {
int currentPage = previewPanel.getPage();
GoToPageDialog d = new GoToPageDialog(this,
translator.getString("Menu.Go.to.Page"), translator);
d.setLocation((int)getLocation().getX() + 50,
(int)getLocation().getY() + 50);
d.setVisible(true);
currentPage = d.getPageNumber();
if (currentPage < 1 || currentPage > renderer.getNumberOfPages()) {
return;
}
currentPage--;
goToPage(currentPage);
}
/** Scales page image */
public void setScale(double scaleFactor) {
// if (scaleFactor == 25.0) {
// scale.setSelectedIndex(0);
// } else if (scaleFactor == 50.0) {
// scale.setSelectedIndex(1);
// } else if (scaleFactor == 75.0) {
// scale.setSelectedIndex(2);
// } else if (scaleFactor == 100.0) {
// scale.setSelectedIndex(3);
// } else if (scaleFactor == 150.0) {
// scale.setSelectedIndex(4);
// } else if (scaleFactor == 200.0) {
// scale.setSelectedIndex(5);
// } else if (scaleFactor == 400.0) {
// scale.setSelectedIndex(6);
// } else {
scale.setSelectedItem(percentFormat.format(scaleFactor) + "%");
// }
previewPanel.setScaleFactor(scaleFactor / 100d);
}
public void setScaleToFitWindow() {
try {
setScale(previewPanel.getScaleToFitWindow() * 100);
} catch (FOPException fopEx) {
fopEx.printStackTrace();
}
}
public void setScaleToFitWidth() {
try {
setScale(previewPanel.getScaleToFitWidth() * 100);
} catch (FOPException fopEx) {
fopEx.printStackTrace();
}
}
private void scaleActionPerformed(ActionEvent e) {
try {
int index = scale.getSelectedIndex();
if (index == 0) {
setScale(previewPanel.getScaleToFitWindow() * 100);
} else if (index == 1) {
setScale(previewPanel.getScaleToFitWidth() * 100);
} else {
String item = (String)scale.getSelectedItem();
setScale(Double.parseDouble(item.substring(0, item.indexOf('%'))));
}
} catch (FOPException fopEx) {
fopEx.printStackTrace();
}
}
/** Prints the document */
public void startPrinterJob(boolean showDialog) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPageable(renderer);
if (!showDialog || pj.printDialog()) {
try {
pj.print();
} catch (PrinterException e) {
e.printStackTrace();
}
}
}
/**
* Sets message to be shown in the status bar in a thread safe way.
* @param message the message
*/
public void setStatus(String message) {
SwingUtilities.invokeLater(new ShowStatus(message));
}
/** This class is used to show status in a thread safe way. */
private class ShowStatus implements Runnable {
/** The message to display */
private String message;
/**
* Constructs ShowStatus thread
* @param message message to display
*/
public ShowStatus(String message) {
this.message = message;
}
public void run() {
processStatus.setText(message.toString());
}
}
/**
* Updates the message to be shown in the info bar in a thread safe way.
*/
public void setInfo() {
SwingUtilities.invokeLater(new ShowInfo());
}
/** This class is used to show info in a thread safe way. */
private class ShowInfo implements Runnable {
public void run() {
String message = translator.getString("Status.Page") + " "
+ (previewPanel.getPage() + 1) + " "
+ translator.getString("Status.of") + " "
+ (renderer.getNumberOfPages());
infoStatus.setText(message);
}
}
/**
* Opens standard Swing error dialog box and reports given exception details.
* @param e the Exception
*/
public void reportException(Exception e) {
String msg = translator.getString("Exception.Occured");
setStatus(msg);
JOptionPane.showMessageDialog(
getContentPane(),
"" + msg + ":
"
+ e.getClass().getName() + "
"
+ e.getMessage() + "",
translator.getString("Exception.Error"),
JOptionPane.ERROR_MESSAGE
);
}
}