4 import java.awt.event.ActionEvent;
5 import java.awt.print.PrinterException;
6 import java.beans.PropertyChangeEvent;
7 import java.beans.PropertyVetoException;
8 import java.beans.VetoableChangeListener;
9 import java.io.IOException;
10 import java.io.StringReader;
13 import javax.swing.event.HyperlinkEvent;
14 import javax.swing.event.HyperlinkListener;
16 import net.sf.jabref.export.layout.Layout;
17 import net.sf.jabref.export.layout.LayoutHelper;
18 import net.sf.jabref.util.DocumentPrinter;
21 * Displays an BibtexEntry using the given layout format.
23 * @author $Author: mortenalver $
24 * @version $Revision: 2597 $ ($Date: 2007-08-01 20:23:38 +0200 (Mi, 01 Aug
28 public class PreviewPanel extends JPanel implements VetoableChangeListener {
31 * The bibtex entry currently shown
38 * If a database is set, the preview will attempt to resolve strings in the
39 * previewed entry using that database.
41 BibtexDatabase database;
47 public JEditorPane previewPane;
49 JScrollPane scrollPane;
56 * (may be null) Optionally used to resolve strings.
58 * (may be null) If given this entry is shown otherwise you have
59 * to call setEntry to make something visible.
61 * (may be null) If not given no toolbar is shown on the right
64 * (must be given) Used for resolving pdf directories for links.
66 * (must be given) Used for layout
68 public PreviewPanel(BibtexDatabase database, BibtexEntry entry,
69 BasePanel panel, MetaData metaData, String layoutFile) {
70 this(panel, metaData, layoutFile);
71 this.database = database;
78 * (may be null) If not given no toolbar is shown on the right
81 * (must be given) Used for resolving pdf directories for links.
83 * (must be given) Used for layout
85 public PreviewPanel(BasePanel panel, MetaData metaData, String layoutFile) {
86 super(new BorderLayout(), true);
89 this.metaData = metaData;
90 this.layoutFile = layoutFile;
91 this.previewPane = createPreviewPane();
93 // Set up scroll pane for preview pane
94 scrollPane = new JScrollPane(previewPane,
95 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
96 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
97 scrollPane.setBorder(null);
100 * If we have been given a panel and the preference option
101 * previewPrintButton is set, show the tool bar
104 && JabRefPreferences.getInstance().getBoolean("previewPrintButton")) {
105 add(createToolBar(), BorderLayout.LINE_START);
108 add(scrollPane, BorderLayout.CENTER);
111 class PrintAction extends AbstractAction {
113 public PrintAction() {
114 super(Globals.lang("Print Preview"), GUIGlobals.getImage("psSmall"));
115 putValue(SHORT_DESCRIPTION, Globals.lang("Print Preview"));
118 DocumentPrinter printerService;
120 public void actionPerformed(ActionEvent arg0) {
121 if (printerService == null)
122 printerService = new DocumentPrinter();
124 // Background this, as it takes a while.
128 printerService.print(entry.getCiteKey(), previewPane);
129 } catch (PrinterException e) {
131 // Inform the user... we don't know what to do.
132 JOptionPane.showMessageDialog(PreviewPanel.this,
133 Globals.lang("Could not print preview") + ".\n"
134 + e.getMessage(), Globals
135 .lang("Printing Entry Preview"),
136 JOptionPane.ERROR_MESSAGE);
145 public Action getPrintAction() {
146 if (printAction == null)
147 printAction = new PrintAction();
151 class CloseAction extends AbstractAction {
152 public CloseAction() {
153 super(Globals.lang("Close window"), GUIGlobals.getImage("close"));
154 putValue(SHORT_DESCRIPTION, Globals.lang("Close window"));
157 public void actionPerformed(ActionEvent e) {
158 panel.hideBottomComponent();
164 public Action getCloseAction() {
165 if (closeAction == null)
166 closeAction = new CloseAction();
170 JPopupMenu createPopupMenu() {
171 JPopupMenu menu = new JPopupMenu();
172 menu.add(getPrintAction());
177 JToolBar createToolBar() {
179 JToolBar tlb = new JToolBar(JToolBar.VERTICAL);
180 JabRefPreferences prefs = JabRefPreferences.getInstance();
181 Action printAction = getPrintAction();
182 Action closeAction = getCloseAction();
184 tlb.setMargin(new Insets(0, 0, 0, 2));
186 // The toolbar carries all the key bindings that are valid for the whole
188 ActionMap am = tlb.getActionMap();
189 InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
191 im.put(prefs.getKey("Close entry preview"), "close");
192 am.put("close", closeAction);
194 im.put(prefs.getKey("Print entry preview"), "print");
195 am.put("print", printAction);
197 tlb.setFloatable(false);
199 // Add actions (and thus buttons)
200 tlb.add(closeAction);
204 tlb.add(printAction);
206 Component[] comps = tlb.getComponents();
208 for (int i = 0; i < comps.length; i++)
209 ((JComponent) comps[i]).setOpaque(false);
214 JEditorPane createPreviewPane() {
215 JEditorPane previewPane = new JEditorPane() {
216 public Dimension getPreferredScrollableViewportSize() {
217 return getPreferredSize();
220 public void paintComponent(Graphics g) {
221 Graphics2D g2 = (Graphics2D) g;
223 .getRenderingHint(RenderingHints.KEY_ANTIALIASING);
224 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
225 RenderingHints.VALUE_ANTIALIAS_ON);
226 g2.setRenderingHint(RenderingHints.KEY_RENDERING,
227 RenderingHints.VALUE_RENDER_QUALITY);
228 super.paintComponent(g2);
229 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint);
232 previewPane.setMargin(new Insets(3, 3, 3, 3));
234 previewPane.setComponentPopupMenu(createPopupMenu());
236 previewPane.setEditable(false);
237 previewPane.setContentType("text/html");
238 previewPane.addHyperlinkListener(new HyperlinkListener() {
239 public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
240 if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
242 String address = hyperlinkEvent.getURL().toString();
243 Util.openExternalViewer(PreviewPanel.this.metaData,
245 } catch (IOException e) {
255 public void setDatabase(BibtexDatabase db) {
259 public void setMetaData(MetaData metaData) {
260 this.metaData = metaData;
263 public void readLayout(String layoutFormat) throws Exception {
264 layoutFile = layoutFormat;
268 public void readLayout() throws Exception {
269 StringReader sr = new StringReader(layoutFile.replaceAll("__NEWLINE__",
271 layout = new LayoutHelper(sr)
272 .getLayoutFromText(Globals.FORMATTER_PACKAGE);
275 public void setLayout(Layout layout) {
276 this.layout = layout;
279 public void setEntry(BibtexEntry newEntry) {
280 if (newEntry != entry) {
282 entry.removePropertyChangeListener(this);
283 newEntry.addPropertyChangeListener(this);
289 } catch (Exception ex) {
290 ex.printStackTrace();
294 public void update() {
296 StringBuffer sb = new StringBuffer();
298 sb.append(layout.doLayout(entry, database));
299 previewPane.setText(sb.toString());
300 previewPane.invalidate();
301 previewPane.revalidate();
304 final JScrollBar bar = scrollPane.getVerticalScrollBar();
305 SwingUtilities.invokeLater(new Runnable() {
312 public boolean hasEntry() {
313 return (entry != null);
317 * The PreviewPanel has registered itself as an event listener with the
318 * currently displayed BibtexEntry. If the entry changes, an event is
319 * received here, and we can update the preview immediately.
321 public void vetoableChange(PropertyChangeEvent evt)
322 throws PropertyVetoException {
323 // TODO updating here is not really necessary isn't it?
324 // Only if we are visible.