001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     * ------------
026     * $Id: HtmlFileExportDialog.java 3525 2007-10-16 11:43:48Z tmorgner $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.report.modules.gui.swing.html;
033    
034    import java.awt.BorderLayout;
035    import java.awt.Dialog;
036    import java.awt.Frame;
037    import java.awt.GridBagConstraints;
038    import java.awt.GridBagLayout;
039    import java.awt.GridLayout;
040    import java.awt.Insets;
041    import java.awt.event.ActionEvent;
042    import java.awt.event.KeyEvent;
043    import java.io.File;
044    import java.text.MessageFormat;
045    import java.util.ResourceBundle;
046    import javax.swing.AbstractAction;
047    import javax.swing.Action;
048    import javax.swing.ButtonGroup;
049    import javax.swing.JButton;
050    import javax.swing.JComponent;
051    import javax.swing.JFileChooser;
052    import javax.swing.JLabel;
053    import javax.swing.JOptionPane;
054    import javax.swing.JPanel;
055    import javax.swing.JRadioButton;
056    import javax.swing.JTextField;
057    import javax.swing.KeyStroke;
058    
059    import org.jfree.base.config.ModifiableConfiguration;
060    import org.jfree.report.flow.ReportJob;
061    import org.jfree.report.modules.gui.common.DefaultIconTheme;
062    import org.jfree.report.modules.gui.common.GuiContext;
063    import org.jfree.report.modules.gui.swing.common.AbstractExportDialog;
064    import org.jfree.report.modules.gui.swing.common.JStatusBar;
065    import org.jfree.report.modules.gui.swing.common.localization.JLabelLocaleUpdateHandler;
066    import org.jfree.ui.FilesystemFilter;
067    import org.jfree.ui.action.ActionButton;
068    import org.jfree.util.Configuration;
069    import org.jfree.util.DefaultConfiguration;
070    import org.jfree.util.StringUtils;
071    
072    /**
073     * A dialog that is used to perform the printing of a report into an HTML file.
074     */
075    public class HtmlFileExportDialog extends AbstractExportDialog
076    {
077      private static final String HTML_FILE_EXTENSION = ".html";
078      private static final String HTM_FILE_EXTENSION = ".htm";
079    
080      /**
081       * An action to select the export target file.
082       */
083      private class ActionSelectTargetFile extends AbstractAction
084      {
085        /**
086         * Default constructor.
087         */
088        private ActionSelectTargetFile(final ResourceBundle resources)
089        {
090          putValue(Action.NAME, resources.getString("htmlexportdialog.select"));
091        }
092    
093        /**
094         * Receives notification that the action has occurred.
095         *
096         * @param e the action event.
097         */
098        public void actionPerformed(final ActionEvent e)
099        {
100          performSelectFile();
101        }
102    
103      }
104    
105      private JTextField filenameField;
106      private JFileChooser fileChooserHtml;
107      private JTextField dataDirField;
108      private JStatusBar statusBar;
109    
110      private JRadioButton rbPageableExport;
111      private JRadioButton rbStreamExport;
112      private JRadioButton rbFlowExport;
113    
114      /**
115       * Creates a non-modal dialog without a title and without a specified
116       * <code>Frame</code> owner.  A shared, hidden frame will be set as the owner
117       * of the dialog.
118       */
119      public HtmlFileExportDialog()
120      {
121        initializeComponents();
122      }
123    
124      /**
125       * Creates a non-modal dialog without a title with the specified
126       * <code>Frame</code> as its owner.  If <code>owner</code> is
127       * <code>null</code>, a shared, hidden frame will be set as the owner of the
128       * dialog.
129       *
130       * @param owner the <code>Frame</code> from which the dialog is displayed
131       */
132      public HtmlFileExportDialog(final Frame owner)
133      {
134        super(owner);
135        initializeComponents();
136      }
137    
138      /**
139       * Creates a non-modal dialog without a title with the specified
140       * <code>Dialog</code> as its owner.
141       *
142       * @param owner the non-null <code>Dialog</code> from which the dialog is
143       *              displayed
144       */
145      public HtmlFileExportDialog(final Dialog owner)
146      {
147        super(owner);
148        initializeComponents();
149      }
150    
151      public String getFilename()
152      {
153        return filenameField.getText();
154      }
155    
156      public void setFilename(final String filename)
157      {
158        this.filenameField.setText(filename);
159      }
160    
161      private void initializeComponents()
162      {
163        final JPanel contentPane = new JPanel();
164        contentPane.setLayout(new GridBagLayout());
165    
166        filenameField = new JTextField();
167        filenameField.setColumns(60);
168        dataDirField = new JTextField();
169        dataDirField.setColumns(60);
170        statusBar = new JStatusBar(new DefaultIconTheme());
171    
172        rbStreamExport = new JRadioButton(getResources().getString
173            ("htmlexportdialog.stream-export"));
174        rbStreamExport.setSelected(true);
175        rbFlowExport = new JRadioButton(getResources().getString
176            ("htmlexportdialog.flow-export"));
177        rbPageableExport = new JRadioButton(getResources().getString
178            ("htmlexportdialog.pageable-export"));
179    
180        final ButtonGroup bgExport = new ButtonGroup();
181        bgExport.add(rbStreamExport);
182        bgExport.add(rbFlowExport);
183        bgExport.add(rbPageableExport);
184    
185    
186        final JPanel exportTypeSelectionPanel = new JPanel();
187        exportTypeSelectionPanel.setLayout(new GridLayout(3, 1, 5, 5));
188        exportTypeSelectionPanel.add(rbStreamExport);
189        exportTypeSelectionPanel.add(rbFlowExport);
190        exportTypeSelectionPanel.add(rbPageableExport);
191    
192        final JLabel targetLabel =
193            new JLabel(getResources().getString("htmlexportdialog.filename"));
194        addPropertyChangeListener("locale", new JLabelLocaleUpdateHandler(targetLabel,
195            SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.filename"));
196    
197        final JLabel dataLabel =
198            new JLabel(getResources().getString("htmlexportdialog.datafilename"));
199        addPropertyChangeListener("locale", new JLabelLocaleUpdateHandler(dataLabel,
200            SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.datafilename"));
201    
202        final JLabel exportMethodLabel =
203            new JLabel(getResources().getString("htmlexportdialog.exportMethod"));
204        addPropertyChangeListener("locale", new JLabelLocaleUpdateHandler(exportMethodLabel,
205            SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.exportMethod"));
206    
207        GridBagConstraints gbc = new GridBagConstraints();
208        gbc.fill = GridBagConstraints.NONE;
209        gbc.anchor = GridBagConstraints.WEST;
210        gbc.gridx = 0;
211        gbc.gridy = 0;
212        gbc.insets = new Insets(1, 1, 1, 5);
213        contentPane.add(targetLabel, gbc);
214    
215        gbc = new GridBagConstraints();
216        gbc.fill = GridBagConstraints.NONE;
217        gbc.anchor = GridBagConstraints.WEST;
218        gbc.gridx = 0;
219        gbc.gridy = 1;
220        gbc.insets = new Insets(1, 1, 1, 5);
221        contentPane.add(dataLabel, gbc);
222    
223        gbc = new GridBagConstraints();
224        gbc.anchor = GridBagConstraints.WEST;
225        gbc.fill = GridBagConstraints.HORIZONTAL;
226        gbc.gridx = 1;
227        gbc.gridy = 0;
228        gbc.gridwidth = 1;
229        gbc.weightx = 1;
230        gbc.insets = new Insets(1, 1, 1, 1);
231        contentPane.add(filenameField, gbc);
232    
233        gbc = new GridBagConstraints();
234        gbc.anchor = GridBagConstraints.WEST;
235        gbc.fill = GridBagConstraints.HORIZONTAL;
236        gbc.gridx = 2;
237        gbc.gridy = 0;
238        final ActionSelectTargetFile selectTargetAction =
239            new ActionSelectTargetFile(getResources());
240        contentPane.add(new ActionButton(selectTargetAction), gbc);
241    
242        gbc = new GridBagConstraints();
243        gbc.anchor = GridBagConstraints.WEST;
244        gbc.fill = GridBagConstraints.HORIZONTAL;
245        gbc.gridx = 1;
246        gbc.gridy = 1;
247        gbc.gridwidth = 1;
248        gbc.weightx = 1;
249        gbc.insets = new Insets(1, 1, 1, 1);
250        contentPane.add(dataDirField, gbc);
251    
252        gbc = new GridBagConstraints();
253        gbc.anchor = GridBagConstraints.WEST;
254        gbc.fill = GridBagConstraints.HORIZONTAL;
255        gbc.gridx = 0;
256        gbc.gridy = 2;
257        contentPane.add(exportMethodLabel, gbc);
258    
259        gbc = new GridBagConstraints();
260        gbc.anchor = GridBagConstraints.WEST;
261        gbc.fill = GridBagConstraints.HORIZONTAL;
262        gbc.gridx = 1;
263        gbc.gridy = 2;
264        gbc.gridwidth = 1;
265        gbc.insets = new Insets(1, 1, 1, 1);
266        contentPane.add(exportTypeSelectionPanel, gbc);
267    
268    
269        final JButton btnCancel = new ActionButton(getCancelAction());
270        final JButton btnConfirm = new ActionButton(getConfirmAction());
271    
272        final JPanel buttonPanel = new JPanel();
273        buttonPanel.setLayout(new GridLayout());
274        buttonPanel.add(btnConfirm);
275        buttonPanel.add(btnCancel);
276        btnConfirm.setDefaultCapable(true);
277        buttonPanel.registerKeyboardAction(getConfirmAction(),
278            KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
279            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
280    
281        gbc = new GridBagConstraints();
282        gbc.fill = GridBagConstraints.NONE;
283        gbc.anchor = GridBagConstraints.EAST;
284        gbc.weightx = 1;
285        gbc.gridx = 0;
286        gbc.gridwidth = 3;
287        gbc.gridy = 15;
288        gbc.insets = new Insets(10, 0, 10, 0);
289        contentPane.add(buttonPanel, gbc);
290    
291    
292        final JPanel contentWithStatus = new JPanel();
293        contentWithStatus.setLayout(new BorderLayout());
294        contentWithStatus.add(contentPane, BorderLayout.CENTER);
295        contentWithStatus.add(statusBar, BorderLayout.SOUTH);
296    
297        setContentPane(contentWithStatus);
298    
299    
300        getFormValidator().registerTextField(dataDirField);
301        getFormValidator().registerTextField(filenameField);
302      }
303    
304    
305      public JStatusBar getStatusBar()
306      {
307        return statusBar;
308      }
309    
310      protected boolean performValidate()
311      {
312        getStatusBar().clear();
313    
314        final String filename = getFilename();
315        if (filename.trim().length() == 0)
316        {
317          getStatusBar().setStatus(JStatusBar.TYPE_ERROR,
318                  getResources().getString("htmlexportdialog.targetIsEmpty"));
319          return false;
320        }
321        final File f = new File(filename);
322        if (f.exists())
323        {
324          if (f.isFile() == false)
325          {
326            getStatusBar().setStatus(JStatusBar.TYPE_ERROR,
327                    getResources().getString("htmlexportdialog.targetIsNoFile"));
328            return false;
329          }
330          if (f.canWrite() == false)
331          {
332            getStatusBar().setStatus(JStatusBar.TYPE_ERROR,
333                    getResources().getString("htmlexportdialog.targetIsNotWritable"));
334            return false;
335          }
336    
337          final String message = MessageFormat.format(getResources().getString
338                  ("htmlexportdialog.targetExistsWarning"),
339                  new Object[]{filename});
340          getStatusBar().setStatus(JStatusBar.TYPE_WARNING, message);
341        }
342    
343    
344        final String text = dataDirField.getText();
345        if (text.length() > 0)
346        {
347          final File dataDir = new File(text).getAbsoluteFile();
348          if (dataDir.exists())
349          {
350            // dataDirectory does exist ... if no directory : fail
351            if (dataDir.isDirectory() == false)
352            {
353              getStatusBar().setStatus(JStatusBar.TYPE_ERROR,
354                      getResources().getString("htmlexportdialog.targetDataDirIsNoDirectory"));
355              return false;
356            }
357          }
358        }
359    
360        return true;
361      }
362    
363    
364      protected boolean performConfirm ()
365      {
366        final String filename = getFilename();
367        final File f = new File(filename).getAbsoluteFile();
368        if (f.exists())
369        {
370          final String key1 = "htmlexportdialog.targetOverwriteConfirmation";
371          final String key2 = "htmlexportdialog.targetOverwriteTitle";
372          if (JOptionPane.showConfirmDialog(this,
373                  MessageFormat.format(getResources().getString(key1),
374                          new Object[]{getFilename()}),
375                  getResources().getString(key2),
376                  JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)
377                  == JOptionPane.NO_OPTION)
378          {
379            return false;
380          }
381        }
382    
383        final String text = dataDirField.getText();
384        if (text.length() > 0)
385        {
386          final File dataDir = createDataDir(f.getParentFile(), text);
387          if (dataDir.exists() == false)
388          {
389            final String dataDirKey1 = "htmlexportdialog.targetCreateDataDirConfirmation";
390            final String dataDirKey2 = "htmlexportdialog.targetCreateDataDirTitle";
391            if (JOptionPane.showConfirmDialog(this,
392                    MessageFormat.format(getResources().getString(dataDirKey1),
393                            new Object[]{text}),
394                    getResources().getString(dataDirKey2),
395                    JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)
396                    == JOptionPane.NO_OPTION)
397            {
398              return false;
399            }
400          }
401        }
402        return true;
403      }
404    
405      private File createDataDir(final File targetFile, final String dataDirectory)
406      {
407        final File dataDirFile = new File(dataDirectory);
408        if (dataDirFile.isAbsolute())
409        {
410          return dataDirFile;
411        }
412    
413        return new File (targetFile.getParentFile(), dataDirectory);
414      }
415    
416      protected void initializeFromJob(final ReportJob job, final GuiContext guiContext)
417      {
418        statusBar.setIconTheme(guiContext.getIconTheme());
419      }
420    
421      protected String getConfigurationPrefix()
422      {
423        return "org.jfree.report.modules.gui.common.html.file.";
424      }
425    
426      protected Configuration grabDialogContents(final boolean full)
427      {
428        final ModifiableConfiguration conf = new DefaultConfiguration();
429        if (full)
430        {
431          conf.setConfigProperty
432              ("org.jfree.report.modules.gui.common.html.file.TargetFileName", filenameField.getText());
433          conf.setConfigProperty
434              ("org.jfree.report.modules.gui.common.html.file.DataDirectory", dataDirField.getText());
435        }
436        conf.setConfigProperty
437            ("org.jfree.report.modules.gui.common.html.file.ExportMethod", getExportMethod());
438    
439        return conf;
440      }
441    
442      protected void setDialogContents(final Configuration properties)
443      {
444        filenameField.setText(properties.getConfigProperty
445            ("org.jfree.report.modules.gui.common.html.file.TargetFileName", ""));
446        dataDirField.setText(properties.getConfigProperty
447            ("org.jfree.report.modules.gui.common.html.file.DataDirectory", ""));
448        setExportMethod(properties.getConfigProperty
449            ("org.jfree.report.modules.gui.common.html.file.ExportMethod", ""));
450      }
451    
452      protected String getConfigurationSuffix()
453      {
454        return "_htmlexport_file";
455      }
456    
457      public String getExportMethod()
458      {
459        if (rbPageableExport.isSelected())
460        {
461          return "pageable";
462        }
463        if (rbFlowExport.isSelected())
464        {
465          return "flow";
466        }
467        return "stream";
468      }
469    
470      public void setExportMethod (final String method)
471      {
472        if ("pageable".equals(method))
473        {
474          rbPageableExport.setSelected(true);
475        }
476        else if ("flow".equals(method))
477        {
478          rbFlowExport.setSelected(true);
479        }
480        else
481        {
482          rbStreamExport.setSelected(true);
483        }
484      }
485    
486      public void clear()
487      {
488        filenameField.setText("");
489        dataDirField.setText("");
490        rbStreamExport.setSelected(true);
491      }
492    
493      protected String getResourceBaseName()
494      {
495        return SwingHtmlModule.BUNDLE_NAME;
496      }
497    
498    
499      /**
500       * Selects a file to use as target for the report processing.
501       */
502      protected void performSelectFile()
503      {
504        final File file = new File(getFilename());
505    
506        if (fileChooserHtml == null)
507        {
508          fileChooserHtml = new JFileChooser();
509          fileChooserHtml.addChoosableFileFilter
510              (new FilesystemFilter(new String[]{HTML_FILE_EXTENSION, HTM_FILE_EXTENSION},
511                  getResources().getString("htmlexportdialog.html-documents"), true));
512          fileChooserHtml.setMultiSelectionEnabled(false);
513        }
514    
515        fileChooserHtml.setCurrentDirectory(file);
516        fileChooserHtml.setSelectedFile(file);
517        final int option = fileChooserHtml.showSaveDialog(this);
518        if (option == JFileChooser.APPROVE_OPTION)
519        {
520          final File selFile = fileChooserHtml.getSelectedFile();
521          String selFileName = selFile.getAbsolutePath();
522    
523          // Test if ends on html
524          if (StringUtils.endsWithIgnoreCase(selFileName, HTML_FILE_EXTENSION) == false)
525          {
526            selFileName = selFileName + HTML_FILE_EXTENSION;
527          }
528          setFilename(selFileName);
529        }
530      }
531    
532    }