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 }