1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jdtaus.core.monitor.util;
22
23 import java.awt.Component;
24 import java.awt.Dialog;
25 import java.awt.Frame;
26 import java.awt.GraphicsEnvironment;
27 import java.awt.GridBagConstraints;
28 import java.awt.GridBagLayout;
29 import java.awt.HeadlessException;
30 import java.awt.Insets;
31 import java.awt.Window;
32 import java.awt.event.ActionEvent;
33 import java.awt.event.ActionListener;
34 import java.util.Arrays;
35 import java.util.Calendar;
36 import java.util.Date;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.Timer;
42 import java.util.TimerTask;
43 import javax.swing.BorderFactory;
44 import javax.swing.JButton;
45 import javax.swing.JDialog;
46 import javax.swing.JLabel;
47 import javax.swing.JOptionPane;
48 import javax.swing.JPanel;
49 import javax.swing.JProgressBar;
50 import javax.swing.SwingUtilities;
51 import javax.swing.UIManager;
52 import javax.swing.border.TitledBorder;
53 import org.jdtaus.core.container.ContainerFactory;
54 import org.jdtaus.core.logging.spi.Logger;
55 import org.jdtaus.core.monitor.Task;
56 import org.jdtaus.core.monitor.TaskEvent;
57 import org.jdtaus.core.monitor.TaskListener;
58 import org.jdtaus.core.text.Message;
59
60
61
62
63
64
65
66
67
68 public final class SwingProgressMonitor implements TaskListener
69 {
70
71
72
73
74
75
76
77
78
79
80 private Logger getLogger()
81 {
82 return (Logger) ContainerFactory.getContainer().
83 getDependency( this, "Logger" );
84
85 }
86
87
88
89
90
91
92 private Locale getLocale()
93 {
94 return (Locale) ContainerFactory.getContainer().
95 getDependency( this, "Locale" );
96
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 private java.lang.Integer getDefaultMinimumTaskDuration()
113 {
114 return (java.lang.Integer) ContainerFactory.getContainer().
115 getProperty( this, "defaultMinimumTaskDuration" );
116
117 }
118
119
120
121
122
123
124 private java.lang.Integer getDefaultMillisToPopup()
125 {
126 return (java.lang.Integer) ContainerFactory.getContainer().
127 getProperty( this, "defaultMillisToPopup" );
128
129 }
130
131
132
133
134
135
136 private java.lang.Integer getDefaultMillisToDecideToPopup()
137 {
138 return (java.lang.Integer) ContainerFactory.getContainer().
139 getProperty( this, "defaultMillisToDecideToPopup" );
140
141 }
142
143
144
145
146
147
148 private java.lang.Integer getDefaultColumns()
149 {
150 return (java.lang.Integer) ContainerFactory.getContainer().
151 getProperty( this, "defaultColumns" );
152
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public void onTaskEvent( final TaskEvent event )
173 {
174 if ( event != null )
175 {
176 switch ( event.getType() )
177 {
178 case TaskEvent.STARTED:
179 this.onTaskStarted( event );
180 break;
181
182 case TaskEvent.CHANGED_STATE:
183 this.onTaskChangedState( event );
184 break;
185
186 case TaskEvent.ENDED:
187 this.onTaskEnded( event );
188 break;
189
190 default:
191 getLogger().warn( this.getUnknownTaskEventTypeMessage(
192 this.getLocale(), new Integer( event.getType() ) ) );
193
194 }
195 }
196
197 updateProgressDialog();
198 }
199
200
201
202
203
204 private static final class MonitorState
205 {
206
207
208 final Task task;
209
210
211 final ProgressPanel panel;
212
213
214 ActionListener cancelListener;
215
216
217 long visibleMillis = Long.MIN_VALUE;
218
219
220
221
222
223
224
225
226 MonitorState( final Task task, final ProgressPanel panel )
227 {
228 super();
229 this.task = task;
230 this.panel = panel;
231 }
232
233 }
234
235
236 private Component parent;
237
238
239 private final Map tasks = new HashMap( 100 );
240
241
242 private ProgressDialog dialog;
243
244
245 private Integer millisToDecideToPopup;
246
247
248 private Integer millisToPopup;
249
250
251 private Integer minimumTaskDuration;
252
253
254 private Integer columns;
255
256
257
258
259
260 private long popupDecisionMillis = NO_POPUPDECISION;
261 private static final long NO_POPUPDECISION = Long.MIN_VALUE;
262
263
264 private final Timer timer = new Timer( true );
265
266
267
268
269
270
271
272
273
274
275
276 public SwingProgressMonitor( final Component parent )
277 {
278 this( parent, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE );
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295 public SwingProgressMonitor( final Component parent, final int millisToDecideToPopup, final int millisToPopup )
296 {
297 this( parent, millisToDecideToPopup, millisToPopup, Integer.MIN_VALUE, Integer.MIN_VALUE );
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 public SwingProgressMonitor( final Component parent, final int millisToDecideToPopup, final int millisToPopup,
319 final int minimumTaskDurationMillis )
320 {
321 this( parent, millisToDecideToPopup, millisToPopup, Integer.MIN_VALUE, Integer.MIN_VALUE );
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 public SwingProgressMonitor( final Component parent, final int millisToDecideToPopup, final int millisToPopup,
344 final int minimumTaskDurationMillis, final int columns )
345 {
346 if ( parent == null )
347 {
348 throw new NullPointerException( "parent" );
349 }
350
351 if ( GraphicsEnvironment.isHeadless() )
352 {
353 throw new HeadlessException();
354 }
355
356 if ( millisToDecideToPopup > 0 )
357 {
358 this.millisToDecideToPopup = new Integer( millisToDecideToPopup );
359 }
360 if ( millisToPopup > 0 )
361 {
362 this.millisToPopup = new Integer( millisToPopup );
363 }
364 if ( minimumTaskDurationMillis > 0 )
365 {
366 this.minimumTaskDuration = new Integer( minimumTaskDurationMillis );
367 }
368 if ( columns > 0 )
369 {
370 this.columns = new Integer( columns );
371 }
372
373 this.parent = parent;
374 }
375
376
377
378
379
380
381 public Component getParent()
382 {
383 return this.parent;
384 }
385
386
387
388
389
390
391
392
393 public void setParent( final Component parent )
394 {
395 if ( parent == null )
396 {
397 throw new NullPointerException( "parent" );
398 }
399
400 this.parent = parent;
401 }
402
403
404
405
406
407
408 public int getMillisToPopup()
409 {
410 if ( this.millisToPopup == null )
411 {
412 this.millisToPopup = this.getDefaultMillisToPopup();
413 }
414
415 return this.millisToPopup.intValue();
416 }
417
418
419
420
421
422
423 public int getMillisToDecideToPopup()
424 {
425 if ( this.millisToDecideToPopup == null )
426 {
427 this.millisToDecideToPopup = this.getDefaultMillisToDecideToPopup();
428 }
429
430 return this.millisToDecideToPopup.intValue();
431 }
432
433
434
435
436
437
438
439
440 public int getMinimumTaskDuration()
441 {
442 if ( this.minimumTaskDuration == null )
443 {
444 this.minimumTaskDuration = this.getDefaultMinimumTaskDuration();
445 }
446
447 return this.minimumTaskDuration.intValue();
448 }
449
450
451
452
453
454
455
456
457 public int getColumns()
458 {
459 if ( this.columns == null )
460 {
461 this.columns = this.getDefaultColumns();
462 }
463
464 return this.columns.intValue();
465 }
466
467
468
469
470
471
472 private ProgressDialog getDialog()
473 {
474 if ( this.dialog == null )
475 {
476 final Window window = this.getWindowForComponent( this.getParent() );
477
478 if ( window instanceof Frame )
479 {
480 this.dialog = new ProgressDialog( (Frame) window );
481 }
482 else if ( window instanceof Dialog )
483 {
484 this.dialog = new ProgressDialog( (Dialog) window );
485 }
486 }
487
488 return this.dialog;
489 }
490
491
492 private void closeDialog()
493 {
494 if ( this.dialog != null )
495 {
496 this.dialog.setVisible( false );
497 this.dialog.dispose();
498 this.dialog = null;
499 }
500 }
501
502
503
504
505
506
507
508
509
510
511
512
513
514 private Window getWindowForComponent( final Component parentComponent ) throws HeadlessException
515 {
516 Window window = JOptionPane.getRootFrame();
517
518 if ( parentComponent != null )
519 {
520 if ( parentComponent instanceof Frame || parentComponent instanceof Dialog )
521 {
522 window = (Window) parentComponent;
523 }
524 else
525 {
526 this.getWindowForComponent( parentComponent.getParent() );
527 }
528 }
529
530 return window;
531 }
532
533
534
535
536
537
538
539
540
541 private void onTaskStarted( final TaskEvent event )
542 {
543 if ( event == null )
544 {
545 throw new NullPointerException( "event" );
546 }
547 if ( event.getType() != TaskEvent.STARTED )
548 {
549 throw new IllegalArgumentException( Integer.toString( event.getType() ) );
550 }
551
552 synchronized ( this.tasks )
553 {
554 final MonitorState state =
555 new MonitorState( event.getTask(), new ProgressPanel( getColumns() ) );
556
557 state.cancelListener = new ActionListener()
558 {
559
560 public void actionPerformed( final ActionEvent e )
561 {
562 if ( !state.task.isCancelled() )
563 {
564 state.task.setCancelled( true );
565
566 SwingUtilities.invokeLater( new Runnable()
567 {
568
569 public void run()
570 {
571 state.panel.getCancelButton().setText( getTaskCancelledMessage( getLocale() ) );
572 state.panel.getCancelButton().setEnabled( false );
573 }
574
575 } );
576 }
577 }
578
579 };
580
581 if ( this.tasks.put( state.task, state ) != null )
582 {
583 throw new IllegalStateException( getTaskAlreadyStartedMessage(
584 getLocale(), state.task.getDescription().getText( getLocale() ),
585 new Date( state.task.getTimestamp() ) ) );
586
587 }
588
589 SwingUtilities.invokeLater( new Runnable()
590 {
591
592 public void run()
593 {
594 final TitledBorder border =
595 BorderFactory.createTitledBorder( state.task.getDescription().getText( getLocale() ) );
596
597 state.panel.setBorder( border );
598
599 if ( state.task.getProgressDescription() != null )
600 {
601 state.panel.getProgressDescriptionLabel().setText(
602 state.task.getProgressDescription().getText( getLocale() ) );
603
604 }
605 else
606 {
607 state.panel.getProgressDescriptionLabel().setVisible( false );
608 }
609
610 state.panel.getProgressBar().setIndeterminate( true );
611
612 if ( !state.task.isIndeterminate() )
613 {
614 state.panel.getProgressBar().setMinimum( state.task.getMinimum() );
615 state.panel.getProgressBar().setMaximum( state.task.getMaximum() );
616 state.panel.getProgressBar().setValue( state.task.getProgress() );
617 state.panel.getTimeLabel().setText( getComputingExpectedDurationMessage( getLocale() ) );
618 }
619 else
620 {
621 state.panel.getTimeLabel().setText( getIndeterminateDurationMessage( getLocale() ) );
622 }
623
624 state.panel.getCancelButton().setVisible( state.task.isCancelable() );
625 state.panel.getCancelButton().addActionListener( state.cancelListener );
626 state.panel.setVisible( false );
627 getDialog().add( state.panel );
628 }
629
630 } );
631 }
632 }
633
634
635
636
637
638
639
640
641
642 private void onTaskEnded( final TaskEvent event )
643 {
644 if ( event == null )
645 {
646 throw new NullPointerException( "event" );
647 }
648 if ( event.getType() != TaskEvent.ENDED )
649 {
650 throw new IllegalArgumentException( Integer.toString( event.getType() ) );
651 }
652
653 final Runnable taskEnded = new Runnable()
654 {
655
656 public void run()
657 {
658 synchronized ( tasks )
659 {
660 final MonitorState state = (MonitorState) tasks.remove( event.getTask() );
661
662 assert state != null : "Expected a started task.";
663
664 state.visibleMillis = Long.MIN_VALUE;
665
666 SwingUtilities.invokeLater( new Runnable()
667 {
668
669 public void run()
670 {
671 state.panel.getCancelButton().removeActionListener( state.cancelListener );
672 state.panel.setVisible( false );
673 getDialog().remove( state.panel );
674 updateProgressDialog();
675 }
676
677 } );
678 }
679 }
680
681 };
682
683 synchronized ( tasks )
684 {
685 final MonitorState state = (MonitorState) tasks.get( event.getTask() );
686
687 assert state != null : "Expected a started task.";
688
689 SwingUtilities.invokeLater( new Runnable()
690 {
691
692 public void run()
693 {
694 state.panel.getTimeLabel().setText( getTaskCompletedMessage( getLocale(), new Date() ) );
695 }
696
697 } );
698
699 if ( state.visibleMillis > 0L
700 && System.currentTimeMillis() - state.visibleMillis < getMinimumTaskDuration() )
701 {
702 try
703 {
704 timer.schedule( new TimerTask()
705 {
706
707 public void run()
708 {
709 taskEnded.run();
710 }
711
712 }, getMinimumTaskDuration() );
713 }
714 catch ( final IllegalStateException e )
715 {
716 getLogger().error( e );
717 taskEnded.run();
718 }
719 }
720 else
721 {
722 taskEnded.run();
723 }
724 }
725 }
726
727
728
729
730
731
732
733
734
735 private void onTaskChangedState( final TaskEvent event )
736 {
737 if ( event == null )
738 {
739 throw new NullPointerException( "event" );
740 }
741 if ( event.getType() != TaskEvent.CHANGED_STATE )
742 {
743 throw new IllegalArgumentException( Integer.toString( event.getType() ) );
744 }
745
746 synchronized ( tasks )
747 {
748 final MonitorState state = (MonitorState) tasks.get( event.getTask() );
749
750 assert state != null : "Expected a started task.";
751
752 final int progress;
753 final boolean indeterminate;
754 final Message progressDescription = state.task.getProgressDescription();
755
756 if ( !state.task.isIndeterminate() )
757 {
758 progress = state.task.getProgress();
759 indeterminate = false;
760 }
761 else
762 {
763 progress = Integer.MIN_VALUE;
764 indeterminate = true;
765 }
766
767 SwingUtilities.invokeLater( new Runnable()
768 {
769
770 public void run()
771 {
772 if ( !indeterminate )
773 {
774 state.panel.getProgressBar().setValue( progress );
775 }
776
777 if ( progressDescription != null )
778 {
779 final String oldText = state.panel.getProgressDescriptionLabel().getText();
780 final String newText = progressDescription.getText( getLocale() );
781
782 if ( oldText == null || !oldText.equals( newText ) )
783 {
784 state.panel.getProgressDescriptionLabel().setText( newText );
785
786 if ( !state.panel.getProgressDescriptionLabel().isVisible() )
787 {
788 state.panel.getProgressDescriptionLabel().setVisible( true );
789 }
790 }
791 }
792 else if ( state.panel.getProgressDescriptionLabel().isVisible() )
793 {
794 state.panel.getProgressDescriptionLabel().setVisible( false );
795 }
796 }
797
798 } );
799 }
800 }
801
802
803 private void updateProgressDialog()
804 {
805 synchronized ( this.tasks )
806 {
807 if ( this.tasks.size() > 0 )
808 {
809 final long now = System.currentTimeMillis();
810
811 if ( this.popupDecisionMillis == NO_POPUPDECISION )
812 {
813 this.popupDecisionMillis = now;
814 }
815 else if ( now - this.popupDecisionMillis > this.getMillisToDecideToPopup() )
816 {
817
818 for ( Iterator it = this.tasks.entrySet().iterator(); it.hasNext(); )
819 {
820 final Map.Entry entry = (Map.Entry) it.next();
821 final MonitorState state = (MonitorState) entry.getValue();
822
823 if ( !state.task.isIndeterminate() )
824 {
825 final long progressed = state.task.getProgress() - state.task.getMinimum();
826 final long predicted = ( now - state.task.getTimestamp() )
827 * ( state.task.getMaximum() - state.task.getMinimum() )
828 / ( progressed == 0L ? 1L : progressed );
829
830 final Calendar cal = Calendar.getInstance();
831 cal.setTimeInMillis( state.task.getTimestamp() + predicted );
832
833 if ( progressed > 0L )
834 {
835 SwingUtilities.invokeLater( new Runnable()
836 {
837
838 public void run()
839 {
840 state.panel.getTimeLabel().setText( getExpectedEndMessage(
841 getLocale(), cal.getTime() ) );
842
843 if ( state.panel.getProgressBar().isIndeterminate() )
844 {
845 state.panel.getProgressBar().setIndeterminate( false );
846 }
847 }
848
849 } );
850 }
851 }
852
853 if ( state.visibleMillis < 0L && now - state.task.getTimestamp() > this.getMillisToPopup() )
854 {
855 state.visibleMillis = System.currentTimeMillis();
856
857 SwingUtilities.invokeLater( new Runnable()
858 {
859
860 public void run()
861 {
862 state.panel.setVisible( true );
863 getDialog().pack();
864
865 if ( !getDialog().isVisible() )
866 {
867 getDialog().setLocationRelativeTo( getParent() );
868 getDialog().setVisible( true );
869 }
870 }
871
872 } );
873 }
874 }
875 }
876 }
877 else
878 {
879 SwingUtilities.invokeLater( new Runnable()
880 {
881
882 public void run()
883 {
884 closeDialog();
885 }
886
887 } );
888
889 this.popupDecisionMillis = NO_POPUPDECISION;
890 }
891 }
892 }
893
894
895 protected void finalize() throws Throwable
896 {
897 this.timer.cancel();
898 super.finalize();
899 }
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917 private String getUnknownTaskEventTypeMessage( final Locale locale,
918 final java.lang.Number unknownEventType )
919 {
920 return ContainerFactory.getContainer().
921 getMessage( this, "unknownTaskEventType", locale,
922 new Object[]
923 {
924 unknownEventType
925 });
926
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940 private String getTaskAlreadyStartedMessage( final Locale locale,
941 final java.lang.String taskDescription,
942 final java.util.Date startDate )
943 {
944 return ContainerFactory.getContainer().
945 getMessage( this, "taskAlreadyStarted", locale,
946 new Object[]
947 {
948 taskDescription,
949 startDate
950 });
951
952 }
953
954
955
956
957
958
959
960
961
962
963
964 private String getExpectedEndMessage( final Locale locale,
965 final java.util.Date expectedEnd )
966 {
967 return ContainerFactory.getContainer().
968 getMessage( this, "expectedEnd", locale,
969 new Object[]
970 {
971 expectedEnd
972 });
973
974 }
975
976
977
978
979
980
981
982
983
984
985 private String getComputingExpectedDurationMessage( final Locale locale )
986 {
987 return ContainerFactory.getContainer().
988 getMessage( this, "computingExpectedDuration", locale, null );
989
990 }
991
992
993
994
995
996
997
998
999
1000
1001 private String getIndeterminateDurationMessage( final Locale locale )
1002 {
1003 return ContainerFactory.getContainer().
1004 getMessage( this, "indeterminateDuration", locale, null );
1005
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018 private String getTaskCompletedMessage( final Locale locale,
1019 final java.util.Date completedDate )
1020 {
1021 return ContainerFactory.getContainer().
1022 getMessage( this, "taskCompleted", locale,
1023 new Object[]
1024 {
1025 completedDate
1026 });
1027
1028 }
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039 private String getTaskCancelledMessage( final Locale locale )
1040 {
1041 return ContainerFactory.getContainer().
1042 getMessage( this, "taskCancelled", locale, null );
1043
1044 }
1045
1046
1047
1048
1049 }
1050
1051
1052
1053
1054
1055
1056
1057 class ProgressPanel extends JPanel
1058 {
1059
1060
1061
1062 private static final long serialVersionUID = 7471966908616369847L;
1063
1064
1065 private final JLabel progressDescriptionLabel;
1066
1067
1068 private final JLabel timeLabel;
1069
1070
1071 private final JProgressBar progressBar;
1072
1073
1074 private final JButton cancelButton;
1075
1076
1077 ProgressPanel( final int columns )
1078 {
1079 final char[] chars = new char[ columns ];
1080 Arrays.fill( chars, 'W' );
1081
1082 this.timeLabel = new JLabel();
1083 this.timeLabel.setFont( this.timeLabel.getFont().deriveFont( this.timeLabel.getFont().getSize2D() - 2.0F ) );
1084 this.timeLabel.setText( String.valueOf( chars ) );
1085
1086 this.timeLabel.setPreferredSize( this.timeLabel.getPreferredSize() );
1087 this.timeLabel.setText( null );
1088 this.progressDescriptionLabel = new JLabel();
1089
1090 this.progressBar = new JProgressBar();
1091 this.cancelButton = new JButton();
1092 this.cancelButton.setText( UIManager.getString( "OptionPane.cancelButtonText" ) );
1093 this.setLayout( new GridBagLayout() );
1094
1095 GridBagConstraints c = new GridBagConstraints();
1096 c.gridwidth = GridBagConstraints.REMAINDER;
1097 c.anchor = GridBagConstraints.NORTHWEST;
1098 c.weightx = 1.0D;
1099 c.fill = GridBagConstraints.HORIZONTAL;
1100 c.insets = new Insets( 10, 25, 10, 25 );
1101 this.add( this.getProgressBar(), c );
1102
1103 c = new GridBagConstraints();
1104 c.gridwidth = GridBagConstraints.REMAINDER;
1105 c.anchor = GridBagConstraints.NORTHWEST;
1106 c.weightx = 1.0D;
1107 c.fill = GridBagConstraints.HORIZONTAL;
1108 c.insets = new Insets( 0, 25, 10, 25 );
1109 this.add( this.getProgressDescriptionLabel(), c );
1110
1111 c = new GridBagConstraints();
1112 c.gridwidth = GridBagConstraints.REMAINDER;
1113 c.anchor = GridBagConstraints.SOUTHEAST;
1114 c.weightx = 1.0D;
1115 c.insets = new Insets( 10, 25, 10, 25 );
1116 this.add( this.getCancelButton(), c );
1117
1118 c = new GridBagConstraints();
1119 c.gridwidth = GridBagConstraints.REMAINDER;
1120 c.weightx = 1.0D;
1121 c.weighty = 1.0D;
1122 c.anchor = GridBagConstraints.SOUTHWEST;
1123 c.insets = new Insets( 10, 25, 0, 25 );
1124 c.fill = GridBagConstraints.HORIZONTAL;
1125 this.add( this.getTimeLabel(), c );
1126 }
1127
1128 JLabel getProgressDescriptionLabel()
1129 {
1130 return this.progressDescriptionLabel;
1131 }
1132
1133 JLabel getTimeLabel()
1134 {
1135 return this.timeLabel;
1136 }
1137
1138 JProgressBar getProgressBar()
1139 {
1140 return this.progressBar;
1141 }
1142
1143 JButton getCancelButton()
1144 {
1145 return this.cancelButton;
1146 }
1147
1148
1149 }
1150
1151
1152
1153
1154
1155
1156
1157 class ProgressDialog extends JDialog
1158 {
1159
1160
1161
1162 private static final long serialVersionUID = -8959350486356163001L;
1163
1164
1165
1166
1167
1168
1169 ProgressDialog( final Frame owner )
1170 {
1171 super( owner, true );
1172 this.initializeDialog();
1173 }
1174
1175
1176
1177
1178
1179
1180 ProgressDialog( final Dialog owner )
1181 {
1182 super( owner, true );
1183 this.initializeDialog();
1184 }
1185
1186
1187 private void initializeDialog()
1188 {
1189 this.getContentPane().setLayout( new GridBagLayout() );
1190 this.setDefaultCloseOperation( DO_NOTHING_ON_CLOSE );
1191 this.setTitle( UIManager.getString( "ProgressMonitor.progressText" ) );
1192 }
1193
1194 void add( final ProgressPanel panel )
1195 {
1196 if ( panel == null )
1197 {
1198 throw new NullPointerException( "panel" );
1199 }
1200
1201 final GridBagConstraints c = new GridBagConstraints();
1202 c.gridwidth = GridBagConstraints.REMAINDER;
1203 c.anchor = GridBagConstraints.NORTHWEST;
1204 c.weightx = 1.0D;
1205 c.weighty = 1.0D;
1206 c.fill = GridBagConstraints.BOTH;
1207
1208 synchronized ( this.getTreeLock() )
1209 {
1210 this.getContentPane().add( panel, c );
1211 }
1212 }
1213
1214 void remove( final ProgressPanel panel )
1215 {
1216 if ( panel == null )
1217 {
1218 throw new NullPointerException( "panel" );
1219 }
1220
1221 synchronized ( this.getTreeLock() )
1222 {
1223 this.getContentPane().remove( panel );
1224 this.validate();
1225 }
1226 }
1227
1228
1229 }