Source for org.jfree.report.modules.gui.swing.common.ReportProgressDialog

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: ReportProgressDialog.java 3525 2007-10-16 11:43:48Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.modules.gui.swing.common;
  33: 
  34: import java.awt.Dialog;
  35: import java.awt.Frame;
  36: import java.awt.GridBagConstraints;
  37: import java.awt.GridBagLayout;
  38: import java.awt.Insets;
  39: import java.awt.event.WindowAdapter;
  40: import java.awt.event.WindowEvent;
  41: import java.text.MessageFormat;
  42: import java.util.ResourceBundle;
  43: import javax.swing.JDialog;
  44: import javax.swing.JLabel;
  45: import javax.swing.JPanel;
  46: import javax.swing.JProgressBar;
  47: import javax.swing.SwingUtilities;
  48: import javax.swing.border.EmptyBorder;
  49: 
  50: import org.jfree.report.event.ReportProgressEvent;
  51: import org.jfree.report.event.ReportProgressListener;
  52: import org.jfree.report.modules.gui.common.GuiCommonModule;
  53: 
  54: 
  55: /**
  56:  * A progress monitor dialog component that visualizes the report processing progress. It
  57:  * will receive update events from the report processors and updates the UI according to
  58:  * the latest event data.
  59:  * <p/>
  60:  * The progress will be computed according to the currently processed table row. This
  61:  * approach provides relativly accurate data, but assumes that processing all bands
  62:  * consumes roughly the same time.
  63:  *
  64:  * @author Thomas Morgner
  65:  */
  66: public class ReportProgressDialog extends JDialog
  67: {
  68:   private static class ScreenUpdateRunnable implements Runnable
  69:   {
  70:     private int page;
  71:     private int activity;
  72:     private int currentRow;
  73: 
  74:     private ScreenUpdateRunnable (final int activity,
  75:                                  final int currentRow,
  76:                                  final int page)
  77:     {
  78:       this.activity = activity;
  79:       this.currentRow = currentRow;
  80:       this.page = page;
  81:     }
  82: 
  83:     public void run ()
  84:     {
  85:       // todo
  86:     }
  87:   }
  88: 
  89:   private class ReportProgressHandler implements ReportProgressListener
  90:   {
  91:     private ReportProgressHandler()
  92:     {
  93:     }
  94: 
  95:     public void reportProcessingStarted(final ReportProgressEvent event)
  96:     {
  97:       postUpdate(event);
  98:     }
  99: 
 100:     public void reportProcessingUpdate(final ReportProgressEvent event)
 101:     {
 102:       postUpdate(event);
 103:     }
 104: 
 105:     public void reportProcessingFinished(final ReportProgressEvent event)
 106:     {
 107:       postUpdate(event);
 108:     }
 109: 
 110:     private void postUpdate (final ReportProgressEvent event)
 111:     {
 112:       final ScreenUpdateRunnable runnable = new ScreenUpdateRunnable
 113:               (event.getActivity(), event.getRow(), event.getPage());
 114:       if (SwingUtilities.isEventDispatchThread())
 115:       {
 116:         runnable.run();
 117:       }
 118:       else
 119:       {
 120:         SwingUtilities.invokeLater(runnable);
 121:       }
 122:     }
 123:   }
 124: 
 125:   private static class ToFrontHandler extends WindowAdapter
 126:   {
 127:     private ToFrontHandler()
 128:     {
 129:     }
 130: 
 131:     /**
 132:      * Invoked when a window has been opened.
 133:      */
 134:     public void windowOpened (final WindowEvent e)
 135:     {
 136:       e.getWindow().toFront();
 137:     }
 138:   }
 139: 
 140:   /**
 141:    * A label that carries the global message that describes the current task.
 142:    */
 143:   private JLabel messageCarrier;
 144:   /**
 145:    * A label containing the report processing pass count.
 146:    */
 147:   private JLabel passCountMessage;
 148:   /**
 149:    * A label containing the current page.
 150:    */
 151:   private JLabel pageCountMessage;
 152:   /**
 153:    * A label containing the currently processed row.
 154:    */
 155:   private JLabel rowCountMessage;
 156:   /**
 157:    * The progress bar that is used to visualize the progress.
 158:    */
 159:   private JProgressBar progressBar;
 160:   /**
 161:    * The reuseable message format for the page label.
 162:    */
 163:   private MessageFormat pageMessageFormatter;
 164:   /**
 165:    * The reuseable message format for the rows label.
 166:    */
 167:   private MessageFormat rowsMessageFormatter;
 168:   /**
 169:    * The reuseable message format for the pass label.
 170:    */
 171:   private MessageFormat passMessageFormatter;
 172: 
 173:   /**
 174:    * The last page received.
 175:    */
 176:   private int lastPage;
 177:   /**
 178:    * The last pass values received.
 179:    */
 180:   private int lastPass;
 181:   /**
 182:    * The last max-row received.
 183:    */
 184:   private int lastMaxRow;
 185:   /**
 186:    * the cached value for the max-row value as integer.
 187:    */
 188:   private Integer lastMaxRowInteger;  // this values doesnt change much, so reduce GC work
 189:   /**
 190:    * a text which describes the layouting process.
 191:    */
 192:   private String layoutText;
 193:   /**
 194:    * a text that describes the export phase of the report processing.
 195:    */
 196:   private String outputText;
 197: 
 198: 
 199:   /**
 200:    * Localised resources.
 201:    */
 202:   private ResourceBundle resources;
 203: 
 204:   /**
 205:    * Creates a non-modal dialog without a title and with the specified Dialog owner.
 206:    *
 207:    * @param dialog the owner of the dialog
 208:    */
 209:   public ReportProgressDialog (final Dialog dialog)
 210:   {
 211:     super(dialog);
 212:     setLocale(dialog.getLocale());
 213:     initConstructor();
 214:   }
 215: 
 216:   /**
 217:    * Creates a non-modal dialog without a title and with the specified Frame owner.
 218:    *
 219:    * @param frame the owner of the dialog
 220:    */
 221:   public ReportProgressDialog (final Frame frame)
 222:   {
 223:     super(frame);
 224:     setLocale(frame.getLocale());
 225:     initConstructor();
 226:   }
 227: 
 228:   /**
 229:    * Creates a non-modal dialog without a title and without a specified Frame owner.  A
 230:    * shared, hidden frame will be set as the owner of the Dialog.
 231:    */
 232:   public ReportProgressDialog ()
 233:   {
 234:     initConstructor();
 235:   }
 236: 
 237:   /**
 238:    * Initializes the dialog (Non-GUI stuff).
 239:    */
 240:   private void initConstructor ()
 241:   {
 242:     resources = ResourceBundle.getBundle
 243:         (GuiCommonModule.RESOURCE_BASE_NAME, getLocale());
 244:     initialize();
 245:     addWindowListener(new ToFrontHandler());
 246: 
 247:     setOutputText(resources.getString("progress-dialog.perform-output"));
 248:     setLayoutText(resources.getString("progress-dialog.prepare-layout"));
 249: 
 250:     lastPass = -1;
 251:     lastMaxRow = -1;
 252:     lastPage = -1;
 253:   }
 254: 
 255:   /**
 256:    * Initializes the GUI components of this dialog.
 257:    */
 258:   private void initialize ()
 259:   {
 260:     final JPanel contentPane = new JPanel();
 261:     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
 262:     contentPane.setLayout(new GridBagLayout());
 263: 
 264:     pageMessageFormatter = new MessageFormat(resources.getString("progress-dialog.page-label"));
 265:     rowsMessageFormatter = new MessageFormat(resources.getString("progress-dialog.rows-label"));
 266:     passMessageFormatter = new MessageFormat(resources.getString("progress-dialog.pass-label"));
 267: 
 268:     messageCarrier = new JLabel(" ");
 269:     passCountMessage = new JLabel(" ");
 270:     rowCountMessage = new JLabel(" ");
 271:     pageCountMessage = new JLabel(" ");
 272:     progressBar = new JProgressBar();
 273: 
 274:     GridBagConstraints gbc = new GridBagConstraints();
 275:     gbc.gridx = 0;
 276:     gbc.gridy = 0;
 277:     gbc.gridwidth = 2;
 278:     gbc.fill = GridBagConstraints.HORIZONTAL;
 279:     gbc.weightx = 1;
 280:     gbc.anchor = GridBagConstraints.WEST;
 281:     gbc.insets = new Insets(3, 1, 5, 1);
 282:     gbc.ipadx = 200;
 283:     contentPane.add(messageCarrier, gbc);
 284: 
 285:     gbc = new GridBagConstraints();
 286:     gbc.gridx = 0;
 287:     gbc.gridy = 1;
 288:     gbc.gridwidth = 2;
 289:     gbc.anchor = GridBagConstraints.SOUTHWEST;
 290:     gbc.insets = new Insets(3, 1, 1, 1);
 291:     contentPane.add(passCountMessage, gbc);
 292: 
 293:     gbc = new GridBagConstraints();
 294:     gbc.gridx = 0;
 295:     gbc.gridy = 2;
 296:     gbc.gridwidth = 2;
 297:     gbc.anchor = GridBagConstraints.WEST;
 298:     gbc.fill = GridBagConstraints.HORIZONTAL;
 299:     gbc.weightx = 1;
 300:     gbc.insets = new Insets(3, 1, 1, 1);
 301:     contentPane.add(progressBar, gbc);
 302: 
 303:     gbc = new GridBagConstraints();
 304:     gbc.gridx = 0;
 305:     gbc.gridy = 3;
 306:     gbc.gridwidth = 1;
 307:     gbc.weighty = 1;
 308:     gbc.anchor = GridBagConstraints.NORTHWEST;
 309:     gbc.insets = new Insets(3, 1, 1, 1);
 310:     contentPane.add(pageCountMessage, gbc);
 311: 
 312:     gbc = new GridBagConstraints();
 313:     gbc.gridx = 1;
 314:     gbc.gridy = 3;
 315:     gbc.gridwidth = 1;
 316:     gbc.anchor = GridBagConstraints.NORTHWEST;
 317:     gbc.insets = new Insets(3, 10, 1, 1);
 318:     gbc.weightx = 1;
 319:     gbc.fill = GridBagConstraints.HORIZONTAL;
 320:     contentPane.add(rowCountMessage, gbc);
 321: 
 322:     setContentPane(contentPane);
 323:   }
 324: 
 325:   /**
 326:    * Returns the current message.
 327:    *
 328:    * @return the current global message.
 329:    */
 330:   public String getMessage ()
 331:   {
 332:     return messageCarrier.getText();
 333:   }
 334: 
 335:   /**
 336:    * Defines the current message.
 337:    *
 338:    * @param message the current global message.
 339:    */
 340:   public void setMessage (final String message)
 341:   {
 342:     messageCarrier.setText(message);
 343:   }
 344: 
 345:   /**
 346:    * Updates the page message label if the current page has changed.
 347:    *
 348:    * @param page the new page parameter.
 349:    */
 350:   protected void updatePageMessage (final int page)
 351:   {
 352:     if (lastPage != page)
 353:     {
 354:       final Object[] parameters = new Object[]{new Integer(page)};
 355:       pageCountMessage.setText(pageMessageFormatter.format(parameters));
 356:       lastPage = page;
 357:     }
 358:   }
 359: 
 360:   /**
 361:    * Updates the rows message label if either the rows or maxrows changed.
 362:    *
 363:    * @param rows    the currently processed rows.
 364:    * @param maxRows the maximum number of rows in the report.
 365:    */
 366:   protected void updateRowsMessage (final int rows, final int maxRows)
 367:   {
 368:     if (maxRows != lastMaxRow)
 369:     {
 370:       lastMaxRowInteger = new Integer(maxRows);
 371:       lastMaxRow = maxRows;
 372:     }
 373:     final Object[] parameters = new Object[]{
 374:       new Integer(rows),
 375:       lastMaxRowInteger
 376:     };
 377:     rowCountMessage.setText(rowsMessageFormatter.format(parameters));
 378:   }
 379: 
 380:   /**
 381:    * Updates the pass message label if either the pass or prepare state changed. The pass
 382:    * reflects the current processing level, one level for every function dependency
 383:    * level.
 384:    *
 385:    * @param pass    the current reporting pass.
 386:    * @param prepare true, if the current run is a prepare run, false otherwise.
 387:    */
 388:   protected void updatePassMessage (final int pass, final boolean prepare)
 389:   {
 390:     if (lastPass != pass)
 391:     {
 392:       lastPass = pass;
 393:       if (pass >= 0)
 394:       {
 395:         final Object[] parameters = new Object[]{new Integer(pass)};
 396:         passCountMessage.setText(passMessageFormatter.format(parameters));
 397:       }
 398:       else
 399:       {
 400:         final String message;
 401:         if (prepare)
 402:         {
 403:           message = getLayoutText();
 404:         }
 405:         else
 406:         {
 407:           message = getOutputText();
 408:         }
 409:         passCountMessage.setText(message);
 410:       }
 411:     }
 412:   }
 413: 
 414:   /**
 415:    * Returns the current pass message component.
 416:    *
 417:    * @return the pass message component.
 418:    */
 419:   protected final JLabel getPassCountMessage ()
 420:   {
 421:     return passCountMessage;
 422:   }
 423: 
 424:   /**
 425:    * Returns the current pagecount message component.
 426:    *
 427:    * @return the page message component.
 428:    */
 429:   protected final JLabel getPageCountMessage ()
 430:   {
 431:     return pageCountMessage;
 432:   }
 433: 
 434:   /**
 435:    * Returns the current row message component.
 436:    *
 437:    * @return the row message component.
 438:    */
 439:   protected final JLabel getRowCountMessage ()
 440:   {
 441:     return rowCountMessage;
 442:   }
 443: 
 444:   /**
 445:    * Returns the current pass message component.
 446:    *
 447:    * @return the pass message component.
 448:    */
 449:   protected final MessageFormat getPageMessageFormatter ()
 450:   {
 451:     return pageMessageFormatter;
 452:   }
 453: 
 454:   /**
 455:    * Returns the current pass message component.
 456:    *
 457:    * @return the pass message component.
 458:    */
 459:   protected final MessageFormat getRowsMessageFormatter ()
 460:   {
 461:     return rowsMessageFormatter;
 462:   }
 463: 
 464:   /**
 465:    * Returns the current pass message component.
 466:    *
 467:    * @return the pass message component.
 468:    */
 469:   protected final MessageFormat getPassMessageFormatter ()
 470:   {
 471:     return passMessageFormatter;
 472:   }
 473: 
 474:   /**
 475:    * Returns the output text message. This text describes the export phases of the report
 476:    * processing.
 477:    *
 478:    * @return the output phase description.
 479:    */
 480:   public String getOutputText ()
 481:   {
 482:     return outputText;
 483:   }
 484: 
 485:   /**
 486:    * Defines the output text message. This text describes the export phases of the report
 487:    * processing.
 488:    *
 489:    * @param outputText the output message.
 490:    */
 491:   public void setOutputText (final String outputText)
 492:   {
 493:     if (outputText == null)
 494:     {
 495:       throw new NullPointerException("OutputText must not be null.");
 496:     }
 497:     this.outputText = outputText;
 498:   }
 499: 
 500:   /**
 501:    * Returns the layout text. This text describes the prepare phases of the report
 502:    * processing.
 503:    *
 504:    * @return the layout text.
 505:    */
 506:   public String getLayoutText ()
 507:   {
 508:     return layoutText;
 509:   }
 510: 
 511:   /**
 512:    * Defines the layout text message. This text describes the prepare phases of the report
 513:    * processing.
 514:    *
 515:    * @param layoutText the layout message.
 516:    */
 517:   public void setLayoutText (final String layoutText)
 518:   {
 519:     if (layoutText == null)
 520:     {
 521:       throw new NullPointerException("LayoutText must not be null.");
 522:     }
 523:     this.layoutText = layoutText;
 524:   }
 525: 
 526:   protected boolean isSameMaxRow (final int row)
 527:   {
 528:     return lastMaxRow == row;
 529:   }
 530: 
 531: }