You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PreviewDialog.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.render.awt.viewer;
  19. // Originally contributed by:
  20. // Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com,
  21. // Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com,
  22. // Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com
  23. // Java
  24. import java.awt.BorderLayout;
  25. import java.awt.Dimension;
  26. import java.awt.GridBagConstraints;
  27. import java.awt.GridBagLayout;
  28. import java.awt.Insets;
  29. import java.awt.Point;
  30. import java.awt.Toolkit;
  31. import java.awt.event.ActionEvent;
  32. import java.awt.event.ActionListener;
  33. import java.awt.event.KeyEvent;
  34. import java.awt.event.WindowAdapter;
  35. import java.awt.event.WindowEvent;
  36. import java.awt.print.PrinterException;
  37. import java.awt.print.PrinterJob;
  38. import java.text.DecimalFormat;
  39. import java.text.DecimalFormatSymbols;
  40. import java.util.Locale;
  41. import javax.swing.ActionMap;
  42. import javax.swing.BorderFactory;
  43. import javax.swing.ButtonGroup;
  44. import javax.swing.InputMap;
  45. import javax.swing.JComboBox;
  46. import javax.swing.JComponent;
  47. import javax.swing.JFrame;
  48. import javax.swing.JLabel;
  49. import javax.swing.JMenu;
  50. import javax.swing.JMenuBar;
  51. import javax.swing.JOptionPane;
  52. import javax.swing.JPanel;
  53. import javax.swing.JRadioButtonMenuItem;
  54. import javax.swing.JToolBar;
  55. import javax.swing.KeyStroke;
  56. import javax.swing.SwingUtilities;
  57. import org.apache.fop.apps.FOPException;
  58. import org.apache.fop.apps.FOUserAgent;
  59. import org.apache.fop.render.awt.AWTRenderer;
  60. /**
  61. * AWT Viewer main window.
  62. * Surrounds a PreviewPanel with a bunch of pretty buttons and controls.
  63. */
  64. public class PreviewDialog extends JFrame implements StatusListener {
  65. /** The Translator for localization */
  66. protected Translator translator;
  67. /** The AWT renderer */
  68. protected AWTRenderer renderer;
  69. /** The FOUserAgent associated with this window */
  70. protected FOUserAgent foUserAgent;
  71. /** The originally configured target resolution */
  72. protected float configuredTargetResolution;
  73. /**
  74. * Renderable instance that can be used to reload and re-render a document after
  75. * modifications.
  76. */
  77. protected Renderable renderable;
  78. /** The JCombobox to rescale the rendered page view */
  79. private JComboBox scale;
  80. /** The JLabel for the process status bar */
  81. private JLabel processStatus;
  82. /** The JLabel information status bar */
  83. private JLabel infoStatus;
  84. /** The main display area */
  85. private PreviewPanel previewPanel;
  86. /** Formats the text in the scale combobox. */
  87. private DecimalFormat percentFormat = new DecimalFormat("###0.0#",
  88. new DecimalFormatSymbols(Locale.ENGLISH));
  89. /**
  90. * Creates a new PreviewDialog that uses the given renderer.
  91. * @param foUserAgent the user agent
  92. * @param renderable the Renderable instance that is used to reload/re-render a document
  93. * after modifications.
  94. */
  95. public PreviewDialog(
  96. FOUserAgent foUserAgent, Renderable renderable) {
  97. renderer = (AWTRenderer) foUserAgent.getRendererOverride();
  98. this.foUserAgent = foUserAgent;
  99. this.configuredTargetResolution = this.foUserAgent.getTargetResolution();
  100. this.renderable = renderable;
  101. translator = new Translator();
  102. //Commands aka Actions
  103. Command printAction = new Command(translator.getString("Menu.Print"), "Print") {
  104. public void doit() {
  105. startPrinterJob(true);
  106. }
  107. };
  108. Command firstPageAction = new Command(translator.getString("Menu.First.page"),
  109. "firstpg") {
  110. public void doit() {
  111. goToFirstPage();
  112. }
  113. };
  114. Command previousPageAction = new Command(translator.getString("Menu.Prev.page"),
  115. "prevpg") {
  116. public void doit() {
  117. goToPreviousPage();
  118. }
  119. };
  120. Command nextPageAction = new Command(translator.getString("Menu.Next.page"), "nextpg") {
  121. public void doit() {
  122. goToNextPage();
  123. }
  124. };
  125. Command lastPageAction = new Command(translator.getString("Menu.Last.page"), "lastpg") {
  126. public void doit() {
  127. goToLastPage();
  128. }
  129. };
  130. Command reloadAction = new Command(translator.getString("Menu.Reload"), "reload") {
  131. public void doit() {
  132. previewPanel.reload();
  133. }
  134. };
  135. Command debugAction = new Command(translator.getString("Menu.Debug"), "debug") {
  136. // TODO use Translator
  137. public void doit() {
  138. previewPanel.debug();
  139. }
  140. };
  141. Command aboutAction = new Command(translator.getString("Menu.About"), "fopLogo") {
  142. public void doit() {
  143. startHelpAbout();
  144. }
  145. };
  146. setTitle("FOP: AWT-" + translator.getString("Title.Preview"));
  147. setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  148. //Sets size to be 61%x90% of the screen size
  149. Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
  150. // Needed due to bug in Sun's JVM 1.5 (6429775)
  151. pack();
  152. //Rather frivolous size - fits A4 page width in 1024x768 screen on my desktop
  153. setSize(screen.width * 61 / 100, screen.height * 9 / 10);
  154. //Page view stuff
  155. previewPanel = new PreviewPanel(foUserAgent, renderable, renderer);
  156. getContentPane().add(previewPanel, BorderLayout.CENTER);
  157. previewPanel.addPageChangeListener(new PageChangeListener() {
  158. public void pageChanged(PageChangeEvent pce) {
  159. new ShowInfo().run();
  160. }
  161. });
  162. // Keyboard shortcuts - pgup/pgdn
  163. InputMap im = previewPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
  164. ActionMap am = previewPanel.getActionMap();
  165. im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), "nextPage");
  166. im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), "prevPage");
  167. im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "firstPage");
  168. im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "lastPage");
  169. previewPanel.getActionMap().put("nextPage", nextPageAction);
  170. previewPanel.getActionMap().put("prevPage", previousPageAction);
  171. previewPanel.getActionMap().put("firstPage", firstPageAction);
  172. previewPanel.getActionMap().put("lastPage", lastPageAction);
  173. //Scaling combobox
  174. scale = new JComboBox();
  175. scale.addItem(translator.getString("Menu.Fit.Window"));
  176. scale.addItem(translator.getString("Menu.Fit.Width"));
  177. scale.addItem("25%");
  178. scale.addItem("50%");
  179. scale.addItem("75%");
  180. scale.addItem("100%");
  181. scale.addItem("150%");
  182. scale.addItem("200%");
  183. scale.setMaximumSize(new Dimension(80, 24));
  184. scale.setPreferredSize(new Dimension(80, 24));
  185. scale.setSelectedItem("100%");
  186. scale.setEditable(true);
  187. scale.addActionListener(new ActionListener() {
  188. public void actionPerformed(ActionEvent e) {
  189. scaleActionPerformed(e);
  190. }
  191. });
  192. //Menu
  193. setJMenuBar(setupMenu());
  194. // Toolbar
  195. JToolBar toolBar = new JToolBar();
  196. toolBar.add(printAction);
  197. toolBar.add(reloadAction);
  198. toolBar.addSeparator();
  199. toolBar.add(firstPageAction);
  200. toolBar.add(previousPageAction);
  201. toolBar.add(nextPageAction);
  202. toolBar.add(lastPageAction);
  203. toolBar.addSeparator(new Dimension(20, 0));
  204. toolBar.add(new JLabel(translator.getString("Menu.Zoom") + " "));
  205. toolBar.add(scale);
  206. toolBar.addSeparator();
  207. toolBar.add(debugAction);
  208. toolBar.addSeparator();
  209. toolBar.add(aboutAction);
  210. getContentPane().add(toolBar, BorderLayout.NORTH);
  211. // Status bar
  212. JPanel statusBar = new JPanel();
  213. processStatus = new JLabel();
  214. processStatus.setBorder(BorderFactory.createCompoundBorder(
  215. BorderFactory.createEtchedBorder(),
  216. BorderFactory.createEmptyBorder(0, 3, 0, 0)));
  217. infoStatus = new JLabel();
  218. infoStatus.setBorder(BorderFactory.createCompoundBorder(
  219. BorderFactory.createEtchedBorder(),
  220. BorderFactory.createEmptyBorder(0, 3, 0, 0)));
  221. statusBar.setLayout(new GridBagLayout());
  222. processStatus.setPreferredSize(new Dimension(200, 21));
  223. processStatus.setMinimumSize(new Dimension(200, 21));
  224. infoStatus.setPreferredSize(new Dimension(100, 21));
  225. infoStatus.setMinimumSize(new Dimension(100, 21));
  226. statusBar.add(processStatus,
  227. new GridBagConstraints(0, 0, 1, 0, 2.0, 0.0,
  228. GridBagConstraints.CENTER,
  229. GridBagConstraints.HORIZONTAL,
  230. new Insets(0, 0, 0, 3), 0, 0));
  231. statusBar.add(infoStatus,
  232. new GridBagConstraints(1, 0, 1, 0, 1.0, 0.0,
  233. GridBagConstraints.CENTER,
  234. GridBagConstraints.HORIZONTAL,
  235. new Insets(0, 0, 0, 0), 0, 0));
  236. getContentPane().add(statusBar, BorderLayout.SOUTH);
  237. }
  238. /**
  239. * Creates and initialize the AWT Viewer main window.
  240. * @param foUserAgent the FO user agent
  241. * @param renderable the target for the rendering
  242. * @param asMainWindow true if the window shall act as the main application window.
  243. * @return the newly initialized preview dialog
  244. */
  245. public static PreviewDialog createPreviewDialog(FOUserAgent foUserAgent,
  246. Renderable renderable, boolean asMainWindow) {
  247. PreviewDialog frame = new PreviewDialog(foUserAgent, renderable);
  248. if (asMainWindow) {
  249. frame.addWindowListener(new WindowAdapter() {
  250. public void windowClosed(WindowEvent we) {
  251. System.exit(0);
  252. }
  253. });
  254. }
  255. // Centers the window
  256. Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  257. Dimension frameSize = frame.getSize();
  258. if (frameSize.height > screenSize.height) {
  259. frameSize.height = screenSize.height;
  260. }
  261. if (frameSize.width > screenSize.width) {
  262. frameSize.width = screenSize.width;
  263. }
  264. frame.setLocation((screenSize.width - frameSize.width) / 2,
  265. (screenSize.height - frameSize.height) / 2);
  266. frame.setStatus(frame.translator.getString("Status.Build.FO.tree"));
  267. frame.setVisible(true);
  268. return frame;
  269. }
  270. /**
  271. * Creates a new PreviewDialog that uses the given renderer.
  272. * @param foUserAgent the user agent
  273. */
  274. public PreviewDialog(FOUserAgent foUserAgent) {
  275. this(foUserAgent, null);
  276. }
  277. /**
  278. * Creates a new menubar to be shown in this window.
  279. * @return the newly created menubar
  280. */
  281. private JMenuBar setupMenu() {
  282. JMenuBar menuBar = new JMenuBar();
  283. JMenu menu = new JMenu(translator.getString("Menu.File"));
  284. menu.setMnemonic(KeyEvent.VK_F);
  285. //Adds mostly the same actions, but without icons
  286. menu.add(new Command(translator.getString("Menu.Print"), KeyEvent.VK_P) {
  287. public void doit() {
  288. startPrinterJob(true);
  289. }
  290. });
  291. // inputHandler must be set to allow reloading
  292. if (renderable != null) {
  293. menu.add(new Command(translator.getString("Menu.Reload"), KeyEvent.VK_R) {
  294. public void doit() {
  295. reload();
  296. }
  297. });
  298. }
  299. menu.addSeparator();
  300. menu.add(new Command(translator.getString("Menu.Exit"), KeyEvent.VK_X) {
  301. public void doit() {
  302. dispose();
  303. }
  304. });
  305. menuBar.add(menu);
  306. menu = new JMenu(translator.getString("Menu.View"));
  307. menu.setMnemonic(KeyEvent.VK_V);
  308. menu.add(new Command(translator.getString("Menu.First.page"), KeyEvent.VK_F) {
  309. public void doit() {
  310. goToFirstPage();
  311. }
  312. });
  313. menu.add(new Command(translator.getString("Menu.Prev.page"), KeyEvent.VK_P) {
  314. public void doit() {
  315. goToPreviousPage();
  316. }
  317. });
  318. menu.add(new Command(translator.getString("Menu.Next.page"), KeyEvent.VK_N) {
  319. public void doit() {
  320. goToNextPage();
  321. }
  322. });
  323. menu.add(new Command(translator.getString("Menu.Last.page"), KeyEvent.VK_L) {
  324. public void doit() {
  325. goToLastPage();
  326. }
  327. });
  328. menu.add(new Command(translator.getString("Menu.Go.to.Page"), KeyEvent.VK_G) {
  329. public void doit() {
  330. showGoToPageDialog();
  331. }
  332. });
  333. menu.addSeparator();
  334. JMenu subMenu = new JMenu(translator.getString("Menu.Zoom"));
  335. subMenu.setMnemonic(KeyEvent.VK_Z);
  336. subMenu.add(new Command("25%", 0) {
  337. public void doit() {
  338. setScale(25.0);
  339. }
  340. });
  341. subMenu.add(new Command("50%", 0) {
  342. public void doit() {
  343. setScale(50.0);
  344. }
  345. });
  346. subMenu.add(new Command("75%", 0) {
  347. public void doit() {
  348. setScale(75.0);
  349. }
  350. });
  351. subMenu.add(new Command("100%", 0) {
  352. public void doit() {
  353. setScale(100.0);
  354. }
  355. });
  356. subMenu.add(new Command("150%", 0) {
  357. public void doit() {
  358. setScale(150.0);
  359. }
  360. });
  361. subMenu.add(new Command("200%", 0) {
  362. public void doit() {
  363. setScale(200.0);
  364. }
  365. });
  366. menu.add(subMenu);
  367. menu.addSeparator();
  368. menu.add(new Command(translator.getString("Menu.Default.zoom"), KeyEvent.VK_D) {
  369. public void doit() {
  370. setScale(100.0);
  371. }
  372. });
  373. menu.add(new Command(translator.getString("Menu.Fit.Window"), KeyEvent.VK_F) {
  374. public void doit() {
  375. setScaleToFitWindow();
  376. }
  377. });
  378. menu.add(new Command(translator.getString("Menu.Fit.Width"), KeyEvent.VK_W) {
  379. public void doit() {
  380. setScaleToFitWidth();
  381. }
  382. });
  383. menu.addSeparator();
  384. ButtonGroup group = new ButtonGroup();
  385. JRadioButtonMenuItem single = new JRadioButtonMenuItem(
  386. new Command(translator.getString("Menu.Single"), KeyEvent.VK_S) {
  387. public void doit() {
  388. previewPanel.setDisplayMode(PreviewPanel.SINGLE);
  389. }
  390. });
  391. JRadioButtonMenuItem cont = new JRadioButtonMenuItem(
  392. new Command(translator.getString("Menu.Continuous"), KeyEvent.VK_C) {
  393. public void doit() {
  394. previewPanel.setDisplayMode(PreviewPanel.CONTINUOUS);
  395. }
  396. });
  397. JRadioButtonMenuItem facing = new JRadioButtonMenuItem(
  398. new Command(translator.getString("Menu.Facing"), 0) {
  399. public void doit() {
  400. previewPanel.setDisplayMode(PreviewPanel.CONT_FACING);
  401. }
  402. });
  403. single.setSelected(true);
  404. group.add(single);
  405. group.add(cont);
  406. group.add(facing);
  407. menu.add(single);
  408. menu.add(cont);
  409. menu.add(facing);
  410. menuBar.add(menu);
  411. menu = new JMenu(translator.getString("Menu.Help"));
  412. menu.setMnemonic(KeyEvent.VK_H);
  413. menu.add(new Command(translator.getString("Menu.About"), KeyEvent.VK_A) {
  414. public void doit() {
  415. startHelpAbout();
  416. }
  417. });
  418. menuBar.add(menu);
  419. return menuBar;
  420. }
  421. /** {@inheritDoc} */
  422. public void notifyRendererStopped() {
  423. reload();
  424. }
  425. private void reload() {
  426. setStatus(translator.getString("Status.Show"));
  427. previewPanel.reload();
  428. }
  429. /**
  430. * Changes the current visible page
  431. * @param number the page number to go to
  432. */
  433. public void goToPage(int number) {
  434. if (number != previewPanel.getPage()) {
  435. previewPanel.setPage(number);
  436. notifyPageRendered();
  437. }
  438. }
  439. /**
  440. * Shows the previous page.
  441. */
  442. public void goToPreviousPage() {
  443. int page = previewPanel.getPage();
  444. if (page > 0) {
  445. goToPage(page - 1);
  446. }
  447. }
  448. /**
  449. * Shows the next page.
  450. */
  451. public void goToNextPage() {
  452. int page = previewPanel.getPage();
  453. if (page < renderer.getNumberOfPages() - 1) {
  454. goToPage(page + 1);
  455. }
  456. }
  457. /** Shows the first page. */
  458. public void goToFirstPage() {
  459. goToPage(0);
  460. }
  461. /**
  462. * Shows the last page.
  463. */
  464. public void goToLastPage() {
  465. goToPage(renderer.getNumberOfPages() - 1);
  466. }
  467. /** Shows the About box */
  468. private void startHelpAbout() {
  469. PreviewDialogAboutBox dlg = new PreviewDialogAboutBox(this, translator);
  470. //Centers the box
  471. Dimension dlgSize = dlg.getPreferredSize();
  472. Dimension frmSize = getSize();
  473. Point loc = getLocation();
  474. dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
  475. (frmSize.height - dlgSize.height) / 2 + loc.y);
  476. dlg.setVisible(true);
  477. }
  478. /**
  479. * Shows "go to page" dialog and then goes to the selected page
  480. */
  481. private void showGoToPageDialog() {
  482. int currentPage = previewPanel.getPage();
  483. GoToPageDialog d = new GoToPageDialog(this,
  484. translator.getString("Menu.Go.to.Page"), translator);
  485. d.setLocation((int)getLocation().getX() + 50,
  486. (int)getLocation().getY() + 50);
  487. d.setVisible(true);
  488. currentPage = d.getPageNumber();
  489. if (currentPage < 1 || currentPage > renderer.getNumberOfPages()) {
  490. return;
  491. }
  492. currentPage--;
  493. goToPage(currentPage);
  494. }
  495. /**
  496. * Scales page image.
  497. * @param scaleFactor the scale factor
  498. */
  499. public void setScale(double scaleFactor) {
  500. scale.setSelectedItem(percentFormat.format(scaleFactor) + "%");
  501. previewPanel.setScaleFactor(scaleFactor / 100d);
  502. }
  503. /**
  504. * Sets the scaling so the contents fit into the window.
  505. */
  506. public void setScaleToFitWindow() {
  507. try {
  508. setScale(previewPanel.getScaleToFitWindow() * 100);
  509. } catch (FOPException fopEx) {
  510. fopEx.printStackTrace();
  511. }
  512. }
  513. /**
  514. * Sets the scaling so the contents are spread over the whole width available.
  515. */
  516. public void setScaleToFitWidth() {
  517. try {
  518. setScale(previewPanel.getScaleToFitWidth() * 100);
  519. } catch (FOPException fopEx) {
  520. fopEx.printStackTrace();
  521. }
  522. }
  523. private void scaleActionPerformed(ActionEvent e) {
  524. int index = scale.getSelectedIndex();
  525. if (index == 0) {
  526. setScaleToFitWindow();
  527. } else if (index == 1) {
  528. setScaleToFitWidth();
  529. } else {
  530. String item = (String)scale.getSelectedItem();
  531. setScale(Double.parseDouble(item.substring(0, item.indexOf('%'))));
  532. }
  533. }
  534. /**
  535. * Prints the document.
  536. * @param showDialog true if show dialog
  537. */
  538. public void startPrinterJob(boolean showDialog) {
  539. //Restore originally configured target resolution
  540. float saveResolution = foUserAgent.getTargetResolution();
  541. foUserAgent.setTargetResolution(this.configuredTargetResolution);
  542. PrinterJob pj = PrinterJob.getPrinterJob();
  543. pj.setPageable(renderer);
  544. if (!showDialog || pj.printDialog()) {
  545. try {
  546. pj.print();
  547. } catch (PrinterException e) {
  548. e.printStackTrace();
  549. }
  550. }
  551. foUserAgent.setTargetResolution(saveResolution);
  552. }
  553. /**
  554. * Sets message to be shown in the status bar in a thread safe way.
  555. * @param message the message
  556. */
  557. public void setStatus(String message) {
  558. SwingUtilities.invokeLater(new ShowStatus(message));
  559. }
  560. /** This class is used to show status in a thread safe way. */
  561. private class ShowStatus implements Runnable {
  562. /** The message to display */
  563. private String message;
  564. /**
  565. * Constructs ShowStatus thread
  566. * @param message message to display
  567. */
  568. public ShowStatus(String message) {
  569. this.message = message;
  570. }
  571. public void run() {
  572. processStatus.setText(message);
  573. }
  574. }
  575. /**
  576. * Updates the message to be shown in the info bar in a thread safe way.
  577. */
  578. public void notifyPageRendered() {
  579. SwingUtilities.invokeLater(new ShowInfo());
  580. }
  581. /** This class is used to show info in a thread safe way. */
  582. private class ShowInfo implements Runnable {
  583. public void run() {
  584. String message = translator.getString("Status.Page") + " "
  585. + (previewPanel.getPage() + 1) + " "
  586. + translator.getString("Status.of") + " "
  587. + (renderer.getNumberOfPages());
  588. infoStatus.setText(message);
  589. }
  590. }
  591. /**
  592. * Opens standard Swing error dialog box and reports given exception details.
  593. * @param e the Exception
  594. */
  595. public void reportException(Exception e) {
  596. String msg = translator.getString("Exception.Occured");
  597. setStatus(msg);
  598. JOptionPane.showMessageDialog(
  599. getContentPane(),
  600. "<html><b>" + msg + ":</b><br>"
  601. + e.getClass().getName() + "<br>"
  602. + e.getMessage() + "</html>",
  603. translator.getString("Exception.Error"),
  604. JOptionPane.ERROR_MESSAGE
  605. );
  606. }
  607. }