001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library is distributed in the hope that it will be useful,
011   but WITHOUT ANY WARRANTY; without even the implied warranty of
012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: ComponentDialog.java,v $
023   Revision 1.16  2004/05/31 07:45:25  markl
024   added installDialogUI(), new form of setComment()
025
026   Revision 1.15  2004/03/16 06:43:39  markl
027   LocaleManager method change
028
029   Revision 1.14  2004/03/15 05:48:34  markl
030   moved accept/cancel logic from ComponentDialog to KDialog.
031
032   Revision 1.13  2004/01/23 00:06:06  markl
033   javadoc corrections
034
035   Revision 1.12  2003/04/30 04:35:02  markl
036   removed unnecessary pack() call.
037
038   Revision 1.11  2003/01/19 09:40:41  markl
039   Added doAccept() and doCancel() methods.
040
041   Revision 1.10  2001/03/20 00:54:54  markl
042   Fixed deprecated calls.
043
044   Revision 1.9  2001/03/12 09:56:55  markl
045   KLabel/KLabelArea changes.
046
047   Revision 1.8  2001/03/12 05:19:57  markl
048   Source code cleanup.
049
050   Revision 1.7  2000/12/18 23:37:29  markl
051   Added new constructors.
052
053   Revision 1.6  2000/10/11 10:44:26  markl
054   Fixed close window logic.
055
056   Revision 1.5  1999/06/03 06:47:15  markl
057   Added canCancel() method.
058
059   Revision 1.4  1999/04/19 06:00:12  markl
060   I18N changes.
061
062   Revision 1.3  1999/02/07 08:09:16  markl
063   made setComment() public
064
065   Revision 1.2  1999/01/10 03:22:17  markl
066   added GPL header & RCS tag
067   ----------------------------------------------------------------------------
068*/
069
070package kiwi.ui.dialog;
071
072import java.awt.*;
073import java.awt.event.*;
074import javax.swing.*;
075import javax.swing.text.JTextComponent;
076import javax.swing.border.EmptyBorder;
077
078import kiwi.ui.*;
079import kiwi.util.*;
080import kiwi.event.*;
081
082/** A base class for custom dialog windows. This class provides some base
083  * functionality that can be useful across many different types of dialogs.
084  * The class constructs a skeleton dialog consisting of an optional comment
085  * line, an icon, <i>OK</i> and <i>Cancel</i> buttons, and a middle area that
086  * must be filled in by subclassers.
087  * <p>
088  * A <code>ComponentDialog</code> is <i>accepted</i> by clicking the
089  * <i>OK</i> button, though subclassers can determine the conditions under
090  * which a dialog may be accepted by overriding the <code>accept()</code>
091  * method; it is <i>cancelled</i> by clicking the <i>Cancel</i> button or
092  * closing the window.
093  *
094  * @author Mark Lindner
095  */
096
097public abstract class ComponentDialog extends KDialog
098  {
099  /** The OK button. */
100  protected KButton b_ok;
101
102  /** The Cancel button. */
103  protected KButton b_cancel = null;
104  
105  private _ActionListener actionListener;
106  private KPanel main;
107  private KLabel iconLabel, commentLabel;
108  private JTextField inputComponent = null;
109  private ButtonPanel buttons;
110  private int fixedButtons = 1;
111
112  /** Construct a new <code>ComponentDialog</code>.
113    *
114    * @param parent The parent dialog for this dialog.
115    * @param title The title for this dialog's window.
116    * @param modal A flag specifying whether this dialog will be modal.
117    */
118  
119  public ComponentDialog(Dialog parent, String title, boolean modal)
120    {
121    this(parent, title, modal, true);
122    }
123
124  /** Construct a new <code>ComponentDialog</code>.
125    *
126    * @param parent The parent dialog for this dialog.
127    * @param title The title for this dialog's window.
128    * @param modal A flag specifying whether this dialog will be modal.
129    * @param hasCancel A flag specifying whether this dialog should have a
130    * <i>Cancel</i> button.
131    */
132  
133  public ComponentDialog(Dialog parent, String title, boolean modal,
134                         boolean hasCancel)
135    {
136    super(parent, title, modal);
137
138    _init(hasCancel);
139    }
140  
141  /** Construct a new <code>ComponentDialog</code>.
142    *
143    * @param parent The parent frame for this dialog.
144    * @param title The title for this dialog's window.
145    * @param modal A flag specifying whether this dialog will be modal.
146    */
147
148  public ComponentDialog(Frame parent, String title, boolean modal)
149    {
150    this(parent, title, modal, true);
151    }
152
153  /** Construct a new <code>ComponentDialog</code>.
154    *
155    * @param parent The parent frame for this dialog.
156    * @param title The title for this dialog's window.
157    * @param modal A flag specifying whether this dialog will be modal.
158    * @param hasCancel A flag specifying whether this dialog should have a
159    * <i>Cancel</i> button.
160    */
161
162  public ComponentDialog(Frame parent, String title, boolean modal,
163                         boolean hasCancel)
164    {
165    super(parent, title, modal);
166
167    _init(hasCancel);
168    }
169
170  /*
171   * Common initialization.
172   */
173
174  private void _init(boolean hasCancel)
175    {
176    LocaleData loc = LocaleManager.getDefault().getLocaleData("KiwiDialogs");
177  
178    actionListener = new _ActionListener();
179    
180    main = getMainContainer();
181    main.setBorder(new EmptyBorder(5, 5, 5, 5));
182    main.setLayout(new BorderLayout(5, 5));
183
184    commentLabel = new KLabel(loc.getMessage("kiwi.dialog.prompt"));
185    main.add("North", commentLabel);
186
187    iconLabel = new KLabel();
188    iconLabel.setBorder(new EmptyBorder(5, 0, 5, 0));
189    iconLabel.setVerticalAlignment(SwingConstants.CENTER);
190    iconLabel.setHorizontalAlignment(SwingConstants.CENTER);
191
192    buttons = new ButtonPanel();
193
194    b_ok = new KButton(loc.getMessage("kiwi.button.ok"));
195    b_ok.addActionListener(actionListener);
196    buttons.addButton(b_ok);
197
198    if(hasCancel)
199      {
200      b_cancel = new KButton(loc.getMessage("kiwi.button.cancel"));
201      b_cancel.addActionListener(actionListener);
202      buttons.addButton(b_cancel);
203      fixedButtons++;
204      }
205
206    main.add("South", buttons);
207
208    installDialogUI();
209    }
210
211  /** Install the component returned by <code>buildDialogUI()</code>
212   * into the dialog. If it is not possible to build the dialog UI at
213   * the time that the constructor calls <code>buildDialogUI()</code>,
214   * that method should return <b>null</b>. The subclass constructor
215   * can then explicitly call <code>installDialogUI()</code>, at which
216   * time <code>buildDialogUI</code> should return a valid component.
217   */
218
219  protected void installDialogUI()
220    {
221    Component c = buildDialogUI();
222    if(c != null)
223      {
224      main.add("Center", c);
225      pack();
226      }
227    }
228
229  /** Construct the component that will be displayed in the center of the
230    * dialog window. Subclassers implement this method to customize the look of
231    * the dialog.
232    *
233    * @return A <code>Component</code> to display in the dialog, or
234    * <code>null</code> if the component will be constructed later.
235    */
236  
237  protected abstract Component buildDialogUI();
238
239  /** Show or hide the dialog.
240    */
241  
242  public void setVisible(boolean flag)
243    {
244    if(flag)
245      {
246      validate();
247      //pack();
248      }
249    super.setVisible(flag);
250    }
251
252  /** Register a text field with this dialog. In some dialogs, most notably
253    * <code>KInputDialog</code>, pressing <i>Return</i> in a text field is
254    * equivalent to pressing the dialog's <i>OK</i> button. Subclassers may use
255    * this method to register a text field that should function in this way.
256    *
257    * @param c The <code>JTextField</code> to register.
258    */
259
260  protected void registerTextInputComponent(JTextField c)
261    {
262    inputComponent = c;
263
264    inputComponent.addActionListener(actionListener);
265    }
266
267  /** This is overridden to fix a Swing layout bug. */
268
269  /*
270  public void pack()
271    {
272    // only do this for JDK 1.3 and earlier
273
274    // add a test here
275    
276    boolean old = isResizable();
277    setResizable(true);
278    super.pack();
279    setResizable(old);
280    }
281  */
282  
283  /** Change the dialog's comment.
284    *
285    * @param comment The new text to display in the comment portion of the
286    * dialog.
287    */
288
289  public void setComment(String comment)
290    {
291    setComment(null, comment);
292    }
293
294  /** Change the dialog's comment.
295   *
296   * @param comment The new text to display in the comment portion of the
297   * dialog.
298   * @param icon An icon to display to the left of the comment text.
299   *
300   * @since Kiwi 2.0
301   */
302
303  public void setComment(Icon icon, String comment)
304    {
305    commentLabel.setText(comment);
306    commentLabel.setIcon(icon);
307    commentLabel.invalidate();
308    commentLabel.validate();
309    }
310
311  /** Set the icon to display in the left part of the dialog
312    * window. The method can be called by classes that extend this
313    * class to provide an appropriate icon for the dialog.
314    *
315    * @param icon The icon.
316    */
317
318  public void setIcon(Icon icon)
319    {
320    if(icon != null)
321      {
322      iconLabel.setIcon(icon);
323      main.add("West", iconLabel);
324      }
325    else
326      main.remove(iconLabel);
327    }
328
329  /* action listener */
330
331  private class _ActionListener implements ActionListener
332    {
333    public void actionPerformed(ActionEvent evt)
334      {
335      Object o = evt.getSource();
336
337      if((o == b_ok) || (o == inputComponent))
338        {
339        doAccept();
340        }
341      else if(o == b_cancel)
342        {
343        if(canCancel())
344          doCancel();
345        }
346      }
347    }
348
349  /** Determine if the dialog can be cancelled. This method is called in
350   * response to a click on the <i>Cancel</i> button or on the dialog
351   * window's close icon/option. Subclassers may wish to override this
352   * method to prevent cancellation of a window in certain circumstances.
353   *
354   * @return <code>true</code> if the dialog may be cancelled,
355   * <code>false</code> otherwise. The default implementation returns
356   * <code>true</code> if the dialog has a <i>Cancel</i> button and
357   * <code>false</code> otherwise.
358   */
359  
360  protected boolean canCancel()
361    {
362    return(b_cancel != null);
363    }
364  
365  /* Set the opacity on all the buttons */
366
367  void setButtonOpacity(boolean flag)
368    {
369    Component c[] = buttons.getComponents();
370
371    for(int i = 0; i < c.length; i++)
372      {
373      if(c[i] instanceof JButton)
374        ((JButton)c[i]).setOpaque(flag);
375      }
376    }
377
378  /** Add a button to the dialog's button panel. The button is added
379    * immediately before the <i>OK</i> button.
380    *
381    * @param button The button to add.
382    */
383  
384  protected void addButton(JButton button)
385    {
386    addButton(button, -1);
387    }
388
389  /** Add a button to the dialog's button panel at the specified position.
390    *
391    * @param button The button to add.
392    * @param pos The position at which to add the button. A value of 0 denotes
393    * the first position, and -1 denotes the last position. The possible
394    * range of values for <code>pos</code> excludes the <i>OK</i> and
395    * (if present) <i>Cancel</i> buttons; buttons may not be added after
396    * these "fixed" buttons.
397    */
398  
399  protected void addButton(JButton button, int pos)
400    throws IllegalArgumentException
401    {
402    int bc = buttons.getButtonCount();
403    int maxpos = bc - fixedButtons;
404
405    if(pos > maxpos)
406      throw(new IllegalArgumentException("Position out of range."));      
407    else if(pos < 0)
408      pos = maxpos;
409
410    buttons.addButton(button, pos);
411    }
412
413  /** Remove a button from the dialog's button panel.
414    *
415    * @param button The button to remove. Neither the <i>OK</i> nor the
416    * <i>Cancel</i> button may be removed.
417    */
418  
419  protected void removeButton(JButton button)
420    {
421    if((button != b_ok) && (button != b_cancel))
422      buttons.removeButton(button);
423    }
424
425  /** Remove a button from the specified position in the  dialog's button
426    * panel.
427    *
428    * @param pos The position of the button to remove, where 0 denotes
429    * the first position, and -1 denotes the last position. The possible
430    * range of values for <code>pos</code> excludes the <i>OK</i> and
431    * (if present) <i>Cancel</i> buttons; these "fixed" buttons may not be
432    * removed.
433    */
434  
435  protected void removeButton(int pos)
436    {
437    int bc = buttons.getButtonCount();
438    int maxpos = bc - fixedButtons;
439
440    if(pos > maxpos)
441      throw(new IllegalArgumentException("Position out of range."));      
442    else if(pos < 0)
443      pos = maxpos;
444
445    buttons.removeButton(pos);
446    }
447
448  /** Set the label text for the <i>OK</i> button.
449    *
450    * @param text The text for the accept button (for example, "Yes").
451    */
452
453  public void setAcceptButtonText(String text)
454    {
455    b_ok.setText(text);
456    }
457
458  /** Set the label text for the <i>Cancel</i> button.
459    *
460    * @param text The text for the cancel button (for example, "No").
461    */
462  
463  public void setCancelButtonText(String text)
464    {
465    if(b_cancel != null)
466      b_cancel.setText(text);
467    }
468
469  }
470
471/* end of source file */