001    /* 
002     * Copyright (c) Holger Pfaff - http://pfaff.ws
003     *
004     * This software maybe used for any purpose provided the
005     * above copyright notice is retained. It is supplied as is.
006     * No warranty expressed or implied - Use at your own risk.
007     */
008    
009    import java.awt.*;
010    import java.awt.event.*;
011    import java.util.Enumeration;
012    
013    /**
014      * (#)DialogBox.java
015      * @author   Holger Pfaff
016      * @version  3.2 19-Mar-2004<br><br> 
017      *
018      * A Wrapper arount the AWT Dialog class. Standard dialogs are
019      * supplied as static member functions. Can be used without
020      * specifying a parent frame (creates its own parent)
021      *
022      * Attention: Dialog crashes on some Netscape 4.7x Version on
023      * Solaris in combination with LANG=en_US (or != C) and
024      * Dialog contains a TextField/TextArea (Problem is related
025      * to XInputMethods)
026      */
027    
028    public class DialogBox implements ActionListener, WindowListener {
029      
030      /**
031       * error image for standard dialogboxes
032       */
033            public static final  Image Err = Awt.loadImageFromArchive("Err.gif");
034    
035      /**
036       * warning image for standard dialogboxes
037       */
038            public static final  Image Wrn = Awt.loadImageFromArchive("Wrn.gif");;
039    
040      /**
041       * info image for standard dialogboxes
042       */
043            public static final  Image Inf = Awt.loadImageFromArchive("Inf.gif");;
044    
045      /**
046       * busy image for standard dialogboxes
047       */
048            public static final  Image Bsy = Awt.loadImageFromArchive("Bsy.gif");;
049            
050      /**
051       * OK string for standard dialogboxes (no i18n)
052       */
053            public static final String     OK  = "OK";
054    
055      /**
056       * Cancel string for standard dialogboxes (no i18n)
057       */
058            public static final String CANCEL  = "Cancel";
059    
060      /**
061       * Error string for standard dialogboxes (no i18n)
062       */
063            public static final String     ERR = "ERROR";
064    
065      /**
066       * Warning string for standard dialogboxes (no i18n)
067       */
068            public static final String     WRN = "Warning";
069    
070      /**
071       * Info string for standard dialogboxes (no i18n)
072       */
073            public static final String     INF = "Info";
074            
075      /**
076       * Event Listeners
077       */
078      private ActionListener     ali = null;
079      
080      /**
081       * dialog object
082       */
083      private Dialog             dia = null;
084    
085      /**
086       * parent frame
087       */
088      private Frame              frm = new Frame();
089    
090      /**
091       * main panel
092       */
093      private Panel              pan = null;
094    
095      /**
096       * button panel
097       */
098      private Awt                bpn = new BorderPanel(BorderPanel.RAISED);
099    
100      /**
101       * title for dialog frame (window manager)
102       */
103      private String             tit = "";
104    
105      /**
106       * return code for modal dialogs
107       */
108      private Object             ret = null;
109    
110      /**
111       * modal dialog ?
112       */
113            private boolean            mod = true;
114    
115      /**
116       * resizable dialog ?
117       */
118            private boolean            res = false;
119      
120      /**
121       * command (actionstring) that closes the dialog window
122       */
123      private String             cwc = null; 
124                                                      
125      /**
126       * Construct a new Dialog.
127       *
128       * @param   p   the content of this dialog.
129       * @param   t   title for dialog frame (window manager).
130       * @param   b   comma separated list of buttons.
131       */
132      public DialogBox(Panel p, String t, String b) {
133        bpn.setInsets(new Insets(0,1,1,1));
134        setPanel(p);
135        setTitle(t);
136        addButtons(b);
137            }
138      
139      /**
140       * Construct a new Dialog.
141       * This empty contructor is intended for custom dialogs.
142       * Use <code>setPanel</code> and <code>addButtons</code> to make this
143       * DialogBox useable.
144       *
145       */
146      public DialogBox() {
147      }
148    
149      /**
150       * Get parent frame.
151       */
152      public Frame getFrame() {
153        return frm;
154      }
155       
156      /**
157       * Get parent frame.
158       */
159      public Frame getParent() {
160        return frm;
161      }
162      
163      /**
164       * Set parent.
165       *
166       * @param   c   use this components parent frame.
167       */
168      public void setParent(Component c) {
169        while(c != null) {
170          if(c instanceof Frame) {
171            if(frm.equals((Frame) c) == false) {
172              frm = (Frame) c;
173              dia = null; 
174            }
175            break;
176          } else {
177            c = c.getParent();
178          }
179        }
180      }
181     
182      /**
183       * Get the main panel (content of this dialog).
184       */
185      public Panel getPanel() {
186        return pan;
187      }
188      
189      /**
190       * Set the main panel (content of this dialog).
191       *
192       * @param   p   use this panel for the dialogbox's content.
193       */
194      public void setPanel(Panel p) {
195        if(p != null) {
196          pan = p;
197        }
198      }
199    
200      /**
201       * Get the title of this dialog.
202       */
203      public String getTitle() {
204        return tit;
205      }
206      
207      /**
208       * Set the title of this dialog. Has no effect after <code>show()</code>
209       *
210       * @param   title   title string
211       */
212            public void setTitle(String t) {
213        if(t != null) {
214          tit = t;
215          if(dia != null) {
216             dia.setTitle(t);
217          }
218        }
219      }
220    
221      /**
222       * Get the modal behavior of this dialog.
223       */
224            public boolean isModal() {
225              return mod;
226            }
227      
228      /**
229       * Set the modal behavior of this dialog.
230       *
231       * @param   m   blocking or not ?
232       */
233            public void setModal(boolean m) {
234              mod = m;
235            }
236      
237      /**
238       * Dialog on screen ?
239       */
240      public boolean isShowing() {
241        return dia == null ? false : dia.isShowing();
242      }
243    
244      /**
245       * Set if Dialog is resizeable
246       *
247       * @param   r   resizeable or not ?
248       */
249      public void setResizable(boolean r) {
250        res = r;
251      }
252    
253      /**
254       * Dialog resizeable ?
255       */
256      public boolean getResizable() {
257        return res;
258      }
259    
260      /**
261       * Add ActionListener to this dialog
262       *
263       * @param   l    ActionListener to add
264       */
265            public void addActionListener(ActionListener l) {
266        ali = AWTEventMulticaster.add(ali, l);
267            }
268    
269      /**
270       * Remove ActionListener to this dialog
271       *
272       * @param   l    ActionListener to remove
273       */
274            public void removeActionListener(ActionListener l) {
275        ali = AWTEventMulticaster.remove(ali, l);
276            }
277    
278      /**
279       * Remove all ActionListener
280       */
281            public void removeActionListeners() {
282        ali = null;
283            }
284      
285      /**
286       * Notify all ActionListener
287       *
288       * @param   but    Index of button that was pressed
289       */
290      public void notifyActionListeners(int but) {
291        Knob b = getButton(but);
292        if(b != null) {
293          notifyActionListeners(new ActionEvent(b, but, b.getActionCommand()));
294        }
295      }
296      
297      /**
298       * Notify all ActionListener
299       *
300       * @param   e    ActionEvent
301       */
302      private synchronized void notifyActionListeners(ActionEvent e) {
303        if(ali != null) {
304          ali.actionPerformed(e);
305        }
306      }
307    
308      /**
309       * Get the close window command of this dialog.
310       */
311      public String getCloseWindowCommand() { 
312        return cwc;
313      }
314      
315      /**
316       * Set the close window command of this dialog. The action
317       * with this string causes the dialog to disappear.
318       * Default null means close on any dialog button
319       *
320       * @param   c   the closing string
321       */
322      public void setCloseWindowCommand(String c) {
323        cwc = c;
324      }
325            
326      /**
327       * Add a dialog button to this box.
328       *
329       * @param   l   the label to show
330       * @param   c   the action command for this button. 
331       *              See <code>setCloseWindowCommand</code>.
332       */
333      public void addButton(String l, String c) {
334        Knob b = new Knob(l);
335        b.setActionCommand(c);
336        b.addActionListener(this);
337        bpn.add(b);
338      }
339      
340      /**
341       * Add a dialog button to this box. Label = action command
342       *
343       * @param   l   the label and action command
344       */
345      public void addButton(String l) {
346        addButton(l, l);
347      }
348      
349      /**
350       * Add a dialog buttons to this box. Label = action command
351       *
352       * @param   l   comma separated list of labels and action commands
353       */
354      public void addButtons(String l) {
355        if(l != null) {
356          for(StringSplitter sp = new StringSplitter(l, ","); sp.hasMoreTokens(); ) {
357            addButton(sp.nextToken());
358          }
359        }
360      }
361    
362      /**
363       * Get the button object for a specific dialog button.
364       * The index depends on the order the buttons were added.
365       *
366       * @param   i   which button ?
367       */
368      public Knob getButton(int i) {
369              if(i < bpn.getComponentCount()) {
370                return (Knob) bpn.getComponent(i);
371                    } else {
372          return null;
373        }
374      }
375      
376      /**
377       * Utility method to en-/disable a dialog button.
378       *
379       * @param   i   which button ?
380       * @param   e   active ?
381       */
382            public void setButtonEnabled(int i, boolean e) {
383              if(i < bpn.getComponentCount()) {
384                getButton(i).setEnabled(e);
385        }
386            }
387      
388      /**
389       * Utility method to change the action string  for a dialog button.
390       *
391       * @param   i   which button ?
392       * @param   a   new action
393       */
394            public void setButtonAction(int i, String a) {
395              if(i < bpn.getComponentCount()) {
396                getButton(i).setActionCommand(a);
397        }
398            }
399    
400      /**
401       * Implement the Action listener interface.
402       * Dispose this dialog depending on closeWindowCommand.
403       */
404      public void actionPerformed(ActionEvent e) {
405        notifyActionListeners(e);
406        if(cwc == null ||
407           cwc.equals(e.getActionCommand())) {
408           ret = e.getActionCommand();
409           dia.setVisible(false);
410        }
411      }
412      
413      /**
414       * Implement the Window listener interface.
415       * Dispose this dialog depending on event and closeWindowCommand.
416       */
417      public void windowClosing(WindowEvent e) {
418        dia.setVisible(false);
419      }
420      
421      /**
422       * Implement the Window listener interface.
423       * Dispose this dialog depending on event and closeWindowCommand.
424       */
425      public void windowIconified(WindowEvent e) { 
426        dia.setVisible(false);
427      }
428      
429      /**
430       * Implement the Window listener interface.
431       */
432      public void windowDeiconified(WindowEvent e) {
433      }
434      
435      /**
436       * Implement the Window listener interface.
437       */
438      public void windowOpened(WindowEvent e) {
439      }
440      
441      /**
442       * Implement the Window listener interface.
443       */
444      public void windowActivated(WindowEvent e) {
445      }
446      
447      /**
448       * Implement the Window listener interface.
449       */
450      public void windowDeactivated(WindowEvent e) {
451      }
452      
453      /**
454       * Implement the Window listener interface.
455       */
456      public void windowClosed(WindowEvent e) {
457      }
458    
459      /**
460       * Shows this dialog. Block if dialog is modal.
461       */
462      public Object show() {
463        return show(frm, false);
464      }
465      
466      /**
467       * Shows this dialog. Block if dialog is modal.
468       *
469       * @param   bep   seems handy for error dialogs.
470       */
471      public Object show(boolean bep) {
472        return show(frm, bep);
473      }
474      
475      /**
476       * Shows this dialog. Block if dialog is modal.
477       *
478       * @param   p   use this components parent frame.
479       */
480      public Object show(Component p) {
481        return show(p, false);
482      }
483      
484      /**
485       * Shows this dialog. Block if dialog is modal.
486       *
487       * @param   parent   use this components parent frame.
488       * @param   beep   seems handy for error dialogs.
489       */
490      public Object show(Component p, boolean bep) {
491        if(pan == null) {
492          return null;
493        }
494        if(p == null) {
495          p = frm;
496        }
497        if(bep == true) {
498           Toolkit.getDefaultToolkit().beep();
499        }
500        setParent(p);
501        if(dia == null) {
502          dia = new Dialog(frm);
503          dia.setLayout(new BorderLayout());
504          dia.addWindowListener(this);
505          dia.setFont(p.getFont());
506          dia.setBackground(p.getBackground());
507          dia.setForeground(p.getForeground());
508          if(bpn instanceof Awt) ((Awt) bpn).setBGIfNull(p);
509          if(pan instanceof Awt) ((Awt) pan).setBGIfNull(p);
510        } else if(dia.isShowing()) {
511          return null;
512        }
513        ret = "";
514        dia.setModal(mod);
515        dia.setTitle(tit);
516        dia.setResizable(res);
517        dia.requestFocus();
518        pack();
519        dia.setVisible(true);
520        return ret;
521      }
522      
523      /**
524       * Make it nice looking
525       */
526      public void pack() {
527        dia.removeAll();
528        dia.add(BorderLayout.CENTER, pan);
529        dia.add(BorderLayout.SOUTH,  bpn);
530        dia.pack();
531                    Awt.centerWindow(dia);
532      }
533      
534      /**
535       * Destroys this dialog
536       *
537       * @param   retCode   return this to the calling method
538       */
539            public void dispose(Object retCode) {
540              if(dia == null) {
541          return;
542        }
543              ret = retCode;
544        dia.setVisible(false);
545            }
546      
547      /**
548       * Static utility method to create a standard Dialog with optional image
549       *
550       * @param   tit   title string
551       * @param   msg   message to show
552       * @param   but   comma separated list of dialog buttons
553       * @param   img   optional image to show on left hand side
554       */
555      public static DialogBox standardDialog(String tit, String msg, String but, Image img) {
556                    final DialogBox dia = new DialogBox(new BorderPanel(BorderPanel.RAISED), tit, but);
557        dia.getPanel().setLayout(new FlowLayout(FlowLayout.CENTER, 20, 20));
558        if(img != null) {
559          dia.getPanel().add(new ImageCanvas(img));
560        }
561        if(msg != null) {
562          dia.getPanel().add(new Caption(msg));
563        }
564        return dia;
565      }
566      
567      /**
568       * Static utility method to create a standard error dialog
569       *
570       * @param   obj   the object to show in the error dialog
571       */
572      public static DialogBox errorDialog(String msg) {
573        return standardDialog(ERR, msg, OK, Err);
574            }
575    
576      /**
577       * Static utility method to create a standard warning dialog.
578       *
579       * @param   msg   the warning message
580       */
581      public static DialogBox warnDialog(String msg) {
582        return standardDialog(WRN, msg, OK, Wrn);
583      }
584      
585      /**
586       * Static utility method to create a standard info dialog.
587       *
588       * @param   msg   the info message
589       */
590      public static DialogBox infoDialog(String msg) {
591        return standardDialog(INF, msg, OK, Inf);
592      }
593      
594      /**
595       * Static utility method to create a standard busy dialog.
596       *
597       * @param   msg   the info message
598       */
599      public static DialogBox busyDialog(String msg) {
600        return standardDialog(INF, msg, CANCEL, Bsy);
601      }
602    };