OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicOptionPaneUI.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* BasicOptionPaneUI.java --
2
   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing.plaf.basic;
40
 
41
import java.awt.BorderLayout;
42
import java.awt.Color;
43
import java.awt.Component;
44
import java.awt.Container;
45
import java.awt.Dimension;
46
import java.awt.Graphics;
47
import java.awt.GridBagConstraints;
48
import java.awt.GridBagLayout;
49
import java.awt.Insets;
50
import java.awt.LayoutManager;
51
import java.awt.Polygon;
52
import java.awt.Window;
53
import java.awt.event.ActionEvent;
54
import java.awt.event.ActionListener;
55
import java.beans.PropertyChangeEvent;
56
import java.beans.PropertyChangeListener;
57
import java.beans.PropertyVetoException;
58
 
59
import javax.swing.BorderFactory;
60
import javax.swing.Box;
61
import javax.swing.BoxLayout;
62
import javax.swing.Icon;
63
import javax.swing.JButton;
64
import javax.swing.JComboBox;
65
import javax.swing.JComponent;
66
import javax.swing.JDialog;
67
import javax.swing.JInternalFrame;
68
import javax.swing.JLabel;
69
import javax.swing.JList;
70
import javax.swing.JOptionPane;
71
import javax.swing.JPanel;
72
import javax.swing.JTextField;
73
import javax.swing.LookAndFeel;
74
import javax.swing.SwingUtilities;
75
import javax.swing.UIManager;
76
import javax.swing.border.Border;
77
import javax.swing.plaf.ComponentUI;
78
import javax.swing.plaf.OptionPaneUI;
79
 
80
/**
81
 * This class is the UI delegate for JOptionPane in the Basic Look and Feel.
82
 */
83
public class BasicOptionPaneUI extends OptionPaneUI
84
{
85
  /**
86
   * This is a helper class that listens to the buttons located at the bottom
87
   * of the JOptionPane.
88
   *
89
   * @specnote Apparently this class was intended to be protected,
90
   *           but was made public by a compiler bug and is now
91
   *           public for compatibility.
92
   */
93
  public class ButtonActionListener implements ActionListener
94
  {
95
    /** The index of the option this button represents. */
96
    protected int buttonIndex;
97
 
98
    /**
99
     * Creates a new ButtonActionListener object with the given buttonIndex.
100
     *
101
     * @param buttonIndex The index of the option this button represents.
102
     */
103
    public ButtonActionListener(int buttonIndex)
104
    {
105
      this.buttonIndex = buttonIndex;
106
    }
107
 
108
    /**
109
     * This method is called when one of the option buttons are pressed.
110
     *
111
     * @param e The ActionEvent.
112
     */
113
    public void actionPerformed(ActionEvent e)
114
    {
115
      Object value = new Integer(JOptionPane.CLOSED_OPTION);
116
      Object[] options = optionPane.getOptions();
117
      if (options != null)
118
        value = new Integer(buttonIndex);
119
      else
120
        {
121
          String text = ((JButton) e.getSource()).getText();
122
          if (text.equals(OK_STRING))
123
            value = new Integer(JOptionPane.OK_OPTION);
124
          if (text.equals(CANCEL_STRING))
125
            value = new Integer(JOptionPane.CANCEL_OPTION);
126
          if (text.equals(YES_STRING))
127
            value = new Integer(JOptionPane.YES_OPTION);
128
          if (text.equals(NO_STRING))
129
            value = new Integer(JOptionPane.NO_OPTION);
130
        }
131
      optionPane.setValue(value);
132
      resetInputValue();
133
 
134
      Window owner = SwingUtilities.windowForComponent(optionPane);
135
 
136
      if (owner instanceof JDialog)
137
        ((JDialog) owner).dispose();
138
 
139
      //else we probably have some kind of internal frame.
140
      JInternalFrame inf = (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class,
141
                                                                              optionPane);
142
      if (inf != null)
143
        {
144
          try
145
            {
146
              inf.setClosed(true);
147
            }
148
          catch (PropertyVetoException pve)
149
            {
150
              // We do nothing if attempt has been vetoed.
151
            }
152
        }
153
    }
154
  }
155
 
156
  /**
157
   * This helper layout manager is responsible for the layout of the button
158
   * area. The button area is the panel that holds the buttons which
159
   * represent the options.
160
   *
161
   * @specnote Apparently this class was intended to be protected,
162
   *           but was made public by a compiler bug and is now
163
   *           public for compatibility.
164
   */
165
  public static class ButtonAreaLayout implements LayoutManager
166
  {
167
    /** Whether this layout will center the buttons. */
168
    protected boolean centersChildren = true;
169
 
170
    /** The space between the buttons. */
171
    protected int padding;
172
 
173
    /** Whether the buttons will share the same widths. */
174
    protected boolean syncAllWidths;
175
 
176
    /** The width of the widest button. */
177
    private transient int widthOfWidestButton;
178
 
179
    /** The height of the tallest button. */
180
    private transient int tallestButton;
181
 
182
    /**
183
     * Creates a new ButtonAreaLayout object with the given sync widths
184
     * property and padding.
185
     *
186
     * @param syncAllWidths Whether the buttons will share the same widths.
187
     * @param padding The padding between the buttons.
188
     */
189
    public ButtonAreaLayout(boolean syncAllWidths, int padding)
190
    {
191
      this.syncAllWidths = syncAllWidths;
192
      this.padding = padding;
193
    }
194
 
195
    /**
196
     * This method is called when a component is added to the container.
197
     *
198
     * @param string The constraints string.
199
     * @param comp The component added.
200
     */
201
    public void addLayoutComponent(String string, Component comp)
202
    {
203
      // Do nothing.
204
    }
205
 
206
    /**
207
     * This method returns whether the children will be centered.
208
     *
209
     * @return Whether the children will be centered.
210
     */
211
    public boolean getCentersChildren()
212
    {
213
      return centersChildren;
214
    }
215
 
216
    /**
217
     * This method returns the amount of space between components.
218
     *
219
     * @return The amount of space between components.
220
     */
221
    public int getPadding()
222
    {
223
      return padding;
224
    }
225
 
226
    /**
227
     * This method returns whether all components will share widths (set to
228
     * largest width).
229
     *
230
     * @return Whether all components will share widths.
231
     */
232
    public boolean getSyncAllWidths()
233
    {
234
      return syncAllWidths;
235
    }
236
 
237
    /**
238
     * This method lays out the given container.
239
     *
240
     * @param container The container to lay out.
241
     */
242
    public void layoutContainer(Container container)
243
    {
244
      Component[] buttonList = container.getComponents();
245
      int x = container.getInsets().left;
246
      if (getCentersChildren())
247
        x += (int) ((double) (container.getSize().width) / 2
248
        - (double) (buttonRowLength(container)) / 2);
249
      for (int i = 0; i < buttonList.length; i++)
250
        {
251
          Dimension dims = buttonList[i].getPreferredSize();
252
          if (syncAllWidths)
253
            {
254
              buttonList[i].setBounds(x, 0, widthOfWidestButton, dims.height);
255
              x += widthOfWidestButton + getPadding();
256
            }
257
          else
258
            {
259
              buttonList[i].setBounds(x, 0, dims.width, dims.height);
260
              x += dims.width + getPadding();
261
            }
262
        }
263
    }
264
 
265
    /**
266
     * This method returns the width of the given container taking into
267
     * consideration the padding and syncAllWidths.
268
     *
269
     * @param c The container to calculate width for.
270
     *
271
     * @return The width of the given container.
272
     */
273
    private int buttonRowLength(Container c)
274
    {
275
      Component[] buttonList = c.getComponents();
276
 
277
      int buttonLength = 0;
278
      int widest = 0;
279
      int tallest = 0;
280
 
281
      for (int i = 0; i < buttonList.length; i++)
282
        {
283
          Dimension dims = buttonList[i].getPreferredSize();
284
          buttonLength += dims.width + getPadding();
285
          widest = Math.max(widest, dims.width);
286
          tallest = Math.max(tallest, dims.height);
287
        }
288
 
289
      widthOfWidestButton = widest;
290
      tallestButton = tallest;
291
 
292
      int width;
293
      if (getSyncAllWidths())
294
        width = widest * buttonList.length
295
                + getPadding() * (buttonList.length - 1);
296
      else
297
        width = buttonLength;
298
 
299
      Insets insets = c.getInsets();
300
      width += insets.left + insets.right;
301
 
302
      return width;
303
    }
304
 
305
    /**
306
     * This method returns the minimum layout size for the given container.
307
     *
308
     * @param c The container to measure.
309
     *
310
     * @return The minimum layout size.
311
     */
312
    public Dimension minimumLayoutSize(Container c)
313
    {
314
      return preferredLayoutSize(c);
315
    }
316
 
317
    /**
318
     * This method returns the preferred size of the given container.
319
     *
320
     * @param c The container to measure.
321
     *
322
     * @return The preferred size.
323
     */
324
    public Dimension preferredLayoutSize(Container c)
325
    {
326
      int w = buttonRowLength(c);
327
 
328
      return new Dimension(w, tallestButton);
329
    }
330
 
331
    /**
332
     * This method removes the given component from the layout manager's
333
     * knowledge.
334
     *
335
     * @param c The component to remove.
336
     */
337
    public void removeLayoutComponent(Component c)
338
    {
339
      // Do nothing.
340
    }
341
 
342
    /**
343
     * This method sets whether the children will be centered.
344
     *
345
     * @param newValue Whether the children will be centered.
346
     */
347
    public void setCentersChildren(boolean newValue)
348
    {
349
      centersChildren = newValue;
350
    }
351
 
352
    /**
353
     * This method sets the amount of space between each component.
354
     *
355
     * @param newPadding The padding between components.
356
     */
357
    public void setPadding(int newPadding)
358
    {
359
      padding = newPadding;
360
    }
361
 
362
    /**
363
     * This method sets whether the widths will be synced.
364
     *
365
     * @param newValue Whether the widths will be synced.
366
     */
367
    public void setSyncAllWidths(boolean newValue)
368
    {
369
      syncAllWidths = newValue;
370
    }
371
  }
372
 
373
  /**
374
   * This helper class handles property change events from the JOptionPane.
375
   *
376
   * @specnote Apparently this class was intended to be protected,
377
   *           but was made public by a compiler bug and is now
378
   *           public for compatibility.
379
   */
380
  public class PropertyChangeHandler implements PropertyChangeListener
381
  {
382
    /**
383
     * This method is called when one of the properties of the JOptionPane
384
     * changes.
385
     *
386
     * @param e The PropertyChangeEvent.
387
     */
388
    public void propertyChange(PropertyChangeEvent e)
389
    {
390
      if (e.getPropertyName().equals(JOptionPane.ICON_PROPERTY)
391
          || e.getPropertyName().equals(JOptionPane.MESSAGE_TYPE_PROPERTY))
392
        addIcon(messageAreaContainer);
393
      else if (e.getPropertyName().equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY))
394
        resetSelectedValue();
395
      else if (e.getPropertyName().equals(JOptionPane.INITIAL_VALUE_PROPERTY)
396
               || e.getPropertyName().equals(JOptionPane.OPTIONS_PROPERTY)
397
               || e.getPropertyName().equals(JOptionPane.OPTION_TYPE_PROPERTY))
398
        {
399
          Container newButtons = createButtonArea();
400
          optionPane.remove(buttonContainer);
401
          optionPane.add(newButtons);
402
          buttonContainer = newButtons;
403
        }
404
 
405
      else if (e.getPropertyName().equals(JOptionPane.MESSAGE_PROPERTY)
406
               || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY)
407
               || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY))
408
        {
409
          optionPane.remove(messageAreaContainer);
410
          messageAreaContainer = createMessageArea();
411
          optionPane.add(messageAreaContainer);
412
          Container newButtons = createButtonArea();
413
          optionPane.remove(buttonContainer);
414
          optionPane.add(newButtons);
415
          buttonContainer = newButtons;
416
          optionPane.add(buttonContainer);
417
        }
418
      optionPane.invalidate();
419
      optionPane.repaint();
420
    }
421
  }
422
 
423
  /**
424
   * The minimum width for JOptionPanes.
425
   */
426
  public static final int MinimumWidth = 262;
427
 
428
  /**
429
   * The minimum height for JOptionPanes.
430
   */
431
  public static final int MinimumHeight = 90;
432
 
433
  /** Whether the JOptionPane contains custom components. */
434
  protected boolean hasCustomComponents = false;
435
 
436
  // The initialFocusComponent seems to always be set to a button (even if 
437
  // I try to set initialSelectionValue). This is different from what the 
438
  // javadocs state (which should switch this reference to the input component 
439
  // if one is present since that is what's going to get focus). 
440
 
441
  /**
442
   * The button that will receive focus based on initialValue when no input
443
   * component is present. If an input component is present, then the input
444
   * component will receive focus instead.
445
   */
446
  protected Component initialFocusComponent;
447
 
448
  /** The component that receives input when the JOptionPane needs it. */
449
  protected JComponent inputComponent;
450
 
451
  /** The minimum dimensions of the JOptionPane. */
452
  protected Dimension minimumSize;
453
 
454
  /** The propertyChangeListener for the JOptionPane. */
455
  protected PropertyChangeListener propertyChangeListener;
456
 
457
  /** The JOptionPane this UI delegate is used for. */
458
  protected JOptionPane optionPane;
459
 
460
  /** The size of the icons. */
461
  // FIXME: wrong name for a constant.
462
  private static final int iconSize = 36;
463
 
464
  /** The foreground color for the message area. */
465
  private transient Color messageForeground;
466
 
467
  /** The border around the message area. */
468
  private transient Border messageBorder;
469
 
470
  /** The border around the button area. */
471
  private transient Border buttonBorder;
472
 
473
  /** The string used to describe OK buttons. */
474
  private static final String OK_STRING = "OK";
475
 
476
  /** The string used to describe Yes buttons. */
477
  private static final String YES_STRING = "Yes";
478
 
479
  /** The string used to describe No buttons. */
480
  private static final String NO_STRING = "No";
481
 
482
  /** The string used to describe Cancel buttons. */
483
  private static final String CANCEL_STRING = "Cancel";
484
 
485
  /** The container for the message area.
486
   * This is package-private to avoid an accessor method. */
487
  transient Container messageAreaContainer;
488
 
489
  /** The container for the buttons.
490
   * This is package-private to avoid an accessor method.  */
491
  transient Container buttonContainer;
492
 
493
  /**
494
   * A helper class that implements Icon. This is used temporarily until
495
   * ImageIcons are fixed.
496
   */
497
  private static class MessageIcon implements Icon
498
  {
499
    /**
500
     * This method returns the width of the icon.
501
     *
502
     * @return The width of the icon.
503
     */
504
    public int getIconWidth()
505
    {
506
      return iconSize;
507
    }
508
 
509
    /**
510
     * This method returns the height of the icon.
511
     *
512
     * @return The height of the icon.
513
     */
514
    public int getIconHeight()
515
    {
516
      return iconSize;
517
    }
518
 
519
    /**
520
     * This method paints the icon as a part of the given component using the
521
     * given graphics and the given x and y position.
522
     *
523
     * @param c The component that owns this icon.
524
     * @param g The Graphics object to paint with.
525
     * @param x The x coordinate.
526
     * @param y The y coordinate.
527
     */
528
    public void paintIcon(Component c, Graphics g, int x, int y)
529
    {
530
      // Nothing to do here.
531
    }
532
  }
533
 
534
  /** The icon displayed for ERROR_MESSAGE. */
535
  private static MessageIcon errorIcon = new MessageIcon()
536
    {
537
      public void paintIcon(Component c, Graphics g, int x, int y)
538
      {
539
        Polygon oct = new Polygon(new int[] { 0, 0, 9, 27, 36, 36, 27, 9 },
540
                                  new int[] { 9, 27, 36, 36, 27, 9, 0, 0 }, 8);
541
        g.translate(x, y);
542
 
543
        Color saved = g.getColor();
544
        g.setColor(Color.RED);
545
 
546
        g.fillPolygon(oct);
547
 
548
        g.setColor(Color.BLACK);
549
        g.drawRect(13, 16, 10, 4);
550
 
551
        g.setColor(saved);
552
        g.translate(-x, -y);
553
      }
554
    };
555
 
556
  /** The icon displayed for INFORMATION_MESSAGE. */
557
  private static MessageIcon infoIcon = new MessageIcon()
558
    {
559
      public void paintIcon(Component c, Graphics g, int x, int y)
560
      {
561
        g.translate(x, y);
562
        Color saved = g.getColor();
563
 
564
        // Should be purple.
565
        g.setColor(Color.RED);
566
 
567
        g.fillOval(0, 0, iconSize, iconSize);
568
 
569
        g.setColor(Color.BLACK);
570
        g.drawOval(16, 6, 4, 4);
571
 
572
        Polygon bottomI = new Polygon(new int[] { 15, 15, 13, 13, 23, 23, 21, 21 },
573
                                      new int[] { 12, 28, 28, 30, 30, 28, 28, 12 },
574
                                      8);
575
        g.drawPolygon(bottomI);
576
 
577
        g.setColor(saved);
578
        g.translate(-x, -y);
579
      }
580
    };
581
 
582
  /** The icon displayed for WARNING_MESSAGE. */
583
  private static MessageIcon warningIcon = new MessageIcon()
584
    {
585
      public void paintIcon(Component c, Graphics g, int x, int y)
586
      {
587
        g.translate(x, y);
588
        Color saved = g.getColor();
589
        g.setColor(Color.YELLOW);
590
 
591
        Polygon triangle = new Polygon(new int[] { 0, 18, 36 },
592
                                       new int[] { 36, 0, 36 }, 3);
593
        g.fillPolygon(triangle);
594
 
595
        g.setColor(Color.BLACK);
596
 
597
        Polygon excl = new Polygon(new int[] { 15, 16, 20, 21 },
598
                                   new int[] { 8, 26, 26, 8 }, 4);
599
        g.drawPolygon(excl);
600
        g.drawOval(16, 30, 4, 4);
601
 
602
        g.setColor(saved);
603
        g.translate(-x, -y);
604
      }
605
    };
606
 
607
  /** The icon displayed for MESSAGE_ICON. */
608
  private static MessageIcon questionIcon = new MessageIcon()
609
    {
610
      public void paintIcon(Component c, Graphics g, int x, int y)
611
      {
612
        g.translate(x, y);
613
        Color saved = g.getColor();
614
        g.setColor(Color.GREEN);
615
 
616
        g.fillRect(0, 0, iconSize, iconSize);
617
 
618
        g.setColor(Color.BLACK);
619
 
620
        g.drawOval(11, 2, 16, 16);
621
        g.drawOval(14, 5, 10, 10);
622
 
623
        g.setColor(Color.GREEN);
624
        g.fillRect(0, 10, iconSize, iconSize - 10);
625
 
626
        g.setColor(Color.BLACK);
627
 
628
        g.drawLine(11, 10, 14, 10);
629
 
630
        g.drawLine(24, 10, 17, 22);
631
        g.drawLine(27, 10, 20, 22);
632
        g.drawLine(17, 22, 20, 22);
633
 
634
        g.drawOval(17, 25, 3, 3);
635
 
636
        g.setColor(saved);
637
        g.translate(-x, -y);
638
      }
639
    };
640
 
641
  // FIXME: Uncomment when the ImageIcons are fixed.
642
 
643
  /*  IconUIResource warningIcon, questionIcon, infoIcon, errorIcon;*/
644
 
645
  /**
646
   * Creates a new BasicOptionPaneUI object.
647
   */
648
  public BasicOptionPaneUI()
649
  {
650
    // Nothing to do here.
651
  }
652
 
653
  /**
654
   * This method is messaged to add the buttons to the given container.
655
   *
656
   * @param container The container to add components to.
657
   * @param buttons The buttons to add. (If it is an instance of component,
658
   *        the Object is added directly. If it is an instance of Icon, it is
659
   *        packed into a label and added. For all other cases, the string
660
   *        representation of the Object is retreived and packed into a
661
   *        label.)
662
   * @param initialIndex The index of the component that is the initialValue.
663
   */
664
  protected void addButtonComponents(Container container, Object[] buttons,
665
                                     int initialIndex)
666
  {
667
    if (buttons == null)
668
      return;
669
    for (int i = 0; i < buttons.length; i++)
670
      {
671
        if (buttons[i] != null)
672
          {
673
            Component toAdd;
674
            if (buttons[i] instanceof Component)
675
              toAdd = (Component) buttons[i];
676
            else
677
              {
678
                if (buttons[i] instanceof Icon)
679
                  toAdd = new JButton((Icon) buttons[i]);
680
                else
681
                  toAdd = new JButton(buttons[i].toString());
682
                hasCustomComponents = true;
683
              }
684
            if (toAdd instanceof JButton)
685
              ((JButton) toAdd).addActionListener(createButtonActionListener(i));
686
            if (i == initialIndex)
687
              initialFocusComponent = toAdd;
688
            container.add(toAdd);
689
          }
690
      }
691
    selectInitialValue(optionPane);
692
  }
693
 
694
  /**
695
   * This method adds the appropriate icon the given container.
696
   *
697
   * @param top The container to add an icon to.
698
   */
699
  protected void addIcon(Container top)
700
  {
701
    JLabel iconLabel = null;
702
    Icon icon = getIcon();
703
    if (icon != null)
704
      {
705
        iconLabel = new JLabel(icon);
706
        top.add(iconLabel, BorderLayout.WEST);
707
      }
708
  }
709
 
710
  /**
711
   * A helper method that returns an instance of GridBagConstraints to be used
712
   * for creating the message area.
713
   *
714
   * @return An instance of GridBagConstraints.
715
   */
716
  private static GridBagConstraints createConstraints()
717
  {
718
    GridBagConstraints constraints = new GridBagConstraints();
719
    constraints.gridx = GridBagConstraints.REMAINDER;
720
    constraints.gridy = GridBagConstraints.REMAINDER;
721
    constraints.gridwidth = 0;
722
    constraints.anchor = GridBagConstraints.LINE_START;
723
    constraints.fill = GridBagConstraints.NONE;
724
    constraints.insets = new Insets(0, 0, 3, 0);
725
 
726
    return constraints;
727
  }
728
 
729
  /**
730
   * This method creates the proper object (if necessary) to represent msg.
731
   * (If msg is an instance of Component, it will add it directly. If it is
732
   * an icon, then it will pack it in a label and add it. Otherwise, it gets
733
   * treated as a string. If the string is longer than maxll, a box is
734
   * created and the burstStringInto is called with the box as the container.
735
   * The box is then added to the given container. Otherwise, the string is
736
   * packed in a label and placed in the given container.) This method is
737
   * also used for adding the inputComponent to the container.
738
   *
739
   * @param container The container to add to.
740
   * @param cons The constraints when adding.
741
   * @param msg The message to add.
742
   * @param maxll The max line length.
743
   * @param internallyCreated Whether the msg is internally created.
744
   */
745
  protected void addMessageComponents(Container container,
746
                                      GridBagConstraints cons, Object msg,
747
                                      int maxll, boolean internallyCreated)
748
  {
749
    if (msg == null)
750
      return;
751
    hasCustomComponents = internallyCreated;
752
    if (msg instanceof Object[])
753
      {
754
        Object[] arr = (Object[]) msg;
755
        for (int i = 0; i < arr.length; i++)
756
          addMessageComponents(container, cons, arr[i], maxll,
757
                               internallyCreated);
758
        return;
759
      }
760
    else if (msg instanceof Component)
761
      {
762
        container.add((Component) msg, cons);
763
        cons.gridy++;
764
      }
765
    else if (msg instanceof Icon)
766
      {
767
        container.add(new JLabel((Icon) msg), cons);
768
        cons.gridy++;
769
      }
770
    else
771
      {
772
        // Undocumented behaviour.
773
        // if msg.toString().length greater than maxll
774
        // it will create a box and burst the string.
775
        // otherwise, it will just create a label and re-call 
776
        // this method with the label o.O
777
        if (msg.toString().length() > maxll)
778
          {
779
            Box tmp = new Box(BoxLayout.Y_AXIS);
780
            burstStringInto(tmp, msg.toString(), maxll);
781
            addMessageComponents(container, cons, tmp, maxll, true);
782
          }
783
        else
784
          addMessageComponents(container, cons, new JLabel(msg.toString()),
785
                               maxll, true);
786
      }
787
  }
788
 
789
  /**
790
   * This method creates instances of d (recursively if necessary based on
791
   * maxll) and adds to c.
792
   *
793
   * @param c The container to add to.
794
   * @param d The string to burst.
795
   * @param maxll The max line length.
796
   */
797
  protected void burstStringInto(Container c, String d, int maxll)
798
  {
799
    // FIXME: Verify that this is the correct behaviour.
800
    // One interpretation of the spec is that this method
801
    // should recursively call itself to create (and add) 
802
    // JLabels to the container if the length of the String d
803
    // is greater than maxll.
804
    // but in practice, even with a really long string, this is 
805
    // all that happens.
806
    if (d == null || c == null)
807
      return;
808
    JLabel label = new JLabel(d);
809
    c.add(label);
810
  }
811
 
812
  /**
813
   * This method returns true if the given JOptionPane contains custom
814
   * components.
815
   *
816
   * @param op The JOptionPane to check.
817
   *
818
   * @return True if the JOptionPane contains custom components.
819
   */
820
  public boolean containsCustomComponents(JOptionPane op)
821
  {
822
    return hasCustomComponents;
823
  }
824
 
825
  /**
826
   * This method creates a button action listener for the given button index.
827
   *
828
   * @param buttonIndex The index of the button in components.
829
   *
830
   * @return A new ButtonActionListener.
831
   */
832
  protected ActionListener createButtonActionListener(int buttonIndex)
833
  {
834
    return new ButtonActionListener(buttonIndex);
835
  }
836
 
837
  /**
838
   * This method creates the button area.
839
   *
840
   * @return A new Button Area.
841
   */
842
  protected Container createButtonArea()
843
  {
844
    JPanel buttonPanel = new JPanel();
845
 
846
    buttonPanel.setLayout(createLayoutManager());
847
    addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex());
848
 
849
    return buttonPanel;
850
  }
851
 
852
  /**
853
   * This method creates a new LayoutManager for the button area.
854
   *
855
   * @return A new LayoutManager for the button area.
856
   */
857
  protected LayoutManager createLayoutManager()
858
  {
859
    return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6);
860
  }
861
 
862
  /**
863
   * This method creates the message area.
864
   *
865
   * @return A new message area.
866
   */
867
  protected Container createMessageArea()
868
  {
869
    JPanel messageArea = new JPanel();
870
    messageArea.setLayout(new BorderLayout());
871
    addIcon(messageArea);
872
 
873
    JPanel rightSide = new JPanel();
874
    rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
875
    rightSide.setLayout(new GridBagLayout());
876
    GridBagConstraints con = createConstraints();
877
 
878
    addMessageComponents(rightSide, con, getMessage(),
879
                         getMaxCharactersPerLineCount(), false);
880
 
881
    if (optionPane.getWantsInput())
882
      {
883
        Object[] selection = optionPane.getSelectionValues();
884
 
885
        if (selection == null)
886
          inputComponent = new JTextField(15);
887
        else if (selection.length < 20)
888
          inputComponent = new JComboBox(selection);
889
        else
890
          inputComponent = new JList(selection);
891
        if (inputComponent != null)
892
          {
893
            addMessageComponents(rightSide, con, inputComponent,
894
                                 getMaxCharactersPerLineCount(), false);
895
            resetSelectedValue();
896
            selectInitialValue(optionPane);
897
          }
898
      }
899
 
900
    messageArea.add(rightSide, BorderLayout.CENTER);
901
 
902
    return messageArea;
903
  }
904
 
905
  /**
906
   * This method creates a new PropertyChangeListener for listening to the
907
   * JOptionPane.
908
   *
909
   * @return A new PropertyChangeListener.
910
   */
911
  protected PropertyChangeListener createPropertyChangeListener()
912
  {
913
    return new PropertyChangeHandler();
914
  }
915
 
916
  /**
917
   * This method creates a Container that will separate the message and button
918
   * areas.
919
   *
920
   * @return A Container that will separate the message and button areas.
921
   */
922
  protected Container createSeparator()
923
  {
924
    // FIXME: Figure out what this method is supposed to return and where
925
    // this should be added to the OptionPane.
926
    return null;
927
  }
928
 
929
  /**
930
   * This method creates a new BasicOptionPaneUI for the given component.
931
   *
932
   * @param x The component to create a UI for.
933
   *
934
   * @return A new BasicOptionPaneUI.
935
   */
936
  public static ComponentUI createUI(JComponent x)
937
  {
938
    return new BasicOptionPaneUI();
939
  }
940
 
941
  /**
942
   * This method returns the buttons for the JOptionPane. If no options are
943
   * set, a set of options will be created based upon the optionType.
944
   *
945
   * @return The buttons that will be added.
946
   */
947
  protected Object[] getButtons()
948
  {
949
    if (optionPane.getOptions() != null)
950
      return optionPane.getOptions();
951
    switch (optionPane.getOptionType())
952
      {
953
      case JOptionPane.YES_NO_OPTION:
954
        return new Object[] { YES_STRING, NO_STRING };
955
      case JOptionPane.YES_NO_CANCEL_OPTION:
956
        return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING };
957
      case JOptionPane.OK_CANCEL_OPTION:
958
        return new Object[] { OK_STRING, CANCEL_STRING };
959
      case JOptionPane.DEFAULT_OPTION:
960
        return (optionPane.getWantsInput() ) ?
961
               new Object[] { OK_STRING, CANCEL_STRING } :
962
               ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ?
963
               new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } :
964
               // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE
965
               new Object[] { OK_STRING };
966
      }
967
    return null;
968
  }
969
 
970
  /**
971
   * This method will return the icon the user has set or the icon that will
972
   * be used based on message type.
973
   *
974
   * @return The icon to use in the JOptionPane.
975
   */
976
  protected Icon getIcon()
977
  {
978
    if (optionPane.getIcon() != null)
979
      return optionPane.getIcon();
980
    else
981
      return getIconForType(optionPane.getMessageType());
982
  }
983
 
984
  /**
985
   * This method returns the icon for the given messageType.
986
   *
987
   * @param messageType The type of message.
988
   *
989
   * @return The icon for the given messageType.
990
   */
991
  protected Icon getIconForType(int messageType)
992
  {
993
    Icon tmp = null;
994
    switch (messageType)
995
      {
996
      case JOptionPane.ERROR_MESSAGE:
997
        tmp = errorIcon;
998
        break;
999
      case JOptionPane.INFORMATION_MESSAGE:
1000
        tmp = infoIcon;
1001
        break;
1002
      case JOptionPane.WARNING_MESSAGE:
1003
        tmp = warningIcon;
1004
        break;
1005
      case JOptionPane.QUESTION_MESSAGE:
1006
        tmp = questionIcon;
1007
        break;
1008
      }
1009
    return tmp;
1010
    // FIXME: Don't cast till the default icons are in.
1011
    // return new IconUIResource(tmp);
1012
  }
1013
 
1014
  /**
1015
   * This method returns the index of the initialValue in the options array.
1016
   *
1017
   * @return The index of the initalValue.
1018
   */
1019
  protected int getInitialValueIndex()
1020
  {
1021
    Object[] buttons = getButtons();
1022
 
1023
    if (buttons == null)
1024
      return -1;
1025
 
1026
    Object select = optionPane.getInitialValue();
1027
 
1028
    for (int i = 0; i < buttons.length; i++)
1029
      {
1030
        if (select == buttons[i])
1031
          return i;
1032
      }
1033
    return 0;
1034
  }
1035
 
1036
  /**
1037
   * This method returns the maximum number of characters that should be
1038
   * placed on a line.
1039
   *
1040
   * @return The maximum number of characteres that should be placed on a
1041
   *         line.
1042
   */
1043
  protected int getMaxCharactersPerLineCount()
1044
  {
1045
    return optionPane.getMaxCharactersPerLineCount();
1046
  }
1047
 
1048
  /**
1049
   * This method returns the maximum size.
1050
   *
1051
   * @param c The JComponent to measure.
1052
   *
1053
   * @return The maximum size.
1054
   */
1055
  public Dimension getMaximumSize(JComponent c)
1056
  {
1057
    return getPreferredSize(c);
1058
  }
1059
 
1060
  /**
1061
   * This method returns the message of the JOptionPane.
1062
   *
1063
   * @return The message.
1064
   */
1065
  protected Object getMessage()
1066
  {
1067
    return optionPane.getMessage();
1068
  }
1069
 
1070
  /**
1071
   * This method returns the minimum size of the JOptionPane.
1072
   *
1073
   * @return The minimum size.
1074
   */
1075
  public Dimension getMinimumOptionPaneSize()
1076
  {
1077
    return minimumSize;
1078
  }
1079
 
1080
  /**
1081
   * This method returns the minimum size.
1082
   *
1083
   * @param c The JComponent to measure.
1084
   *
1085
   * @return The minimum size.
1086
   */
1087
  public Dimension getMinimumSize(JComponent c)
1088
  {
1089
    return getPreferredSize(c);
1090
  }
1091
 
1092
  /**
1093
   * This method returns the preferred size of the JOptionPane. The preferred
1094
   * size is the maximum of the size desired by the layout and the minimum
1095
   * size.
1096
   *
1097
   * @param c The JComponent to measure.
1098
   *
1099
   * @return The preferred size.
1100
   */
1101
  public Dimension getPreferredSize(JComponent c)
1102
  {
1103
    Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane);
1104
    Dimension d2 = getMinimumOptionPaneSize();
1105
 
1106
    int w = Math.max(d.width, d2.width);
1107
    int h = Math.max(d.height, d2.height);
1108
    return new Dimension(w, h);
1109
  }
1110
 
1111
  /**
1112
   * This method returns whether all buttons should have the same width.
1113
   *
1114
   * @return Whether all buttons should have the same width.
1115
   */
1116
  protected boolean getSizeButtonsToSameWidth()
1117
  {
1118
    return true;
1119
  }
1120
 
1121
  /**
1122
   * This method installs components for the JOptionPane.
1123
   */
1124
  protected void installComponents()
1125
  {
1126
    // reset it.
1127
    hasCustomComponents = false;
1128
    Container msg = createMessageArea();
1129
    if (msg != null)
1130
      {
1131
        ((JComponent) msg).setBorder(messageBorder);
1132
        msg.setForeground(messageForeground);
1133
        messageAreaContainer = msg;
1134
        optionPane.add(msg);
1135
      }
1136
 
1137
    // FIXME: Figure out if the separator should be inserted here or what
1138
    // this thing is supposed to do. Note: The JDK does NOT insert another
1139
    // component at this place. The JOptionPane only has two panels in it
1140
    // and there actually are applications that depend on this beeing so.
1141
    Container sep = createSeparator();
1142
    if (sep != null)
1143
      optionPane.add(sep);
1144
 
1145
    Container button = createButtonArea();
1146
    if (button != null)
1147
      {
1148
        ((JComponent) button).setBorder(buttonBorder);
1149
        buttonContainer = button;
1150
        optionPane.add(button);
1151
      }
1152
 
1153
    optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
1154
    optionPane.invalidate();
1155
  }
1156
 
1157
  /**
1158
   * This method installs defaults for the JOptionPane.
1159
   */
1160
  protected void installDefaults()
1161
  {
1162
    LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
1163
                                     "OptionPane.foreground",
1164
                                     "OptionPane.font");
1165
    LookAndFeel.installBorder(optionPane, "OptionPane.border");
1166
    optionPane.setOpaque(true);
1167
 
1168
    messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
1169
    messageForeground = UIManager.getColor("OptionPane.messageForeground");
1170
    buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");
1171
 
1172
    minimumSize = UIManager.getDimension("OptionPane.minimumSize");
1173
 
1174
    // FIXME: Image icons don't seem to work properly right now.
1175
    // Once they do, replace the synthetic icons with these ones.
1176
 
1177
    /*
1178
    warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon");
1179
    infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon");
1180
    errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon");
1181
    questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon");
1182
    */
1183
  }
1184
 
1185
  /**
1186
   * This method installs keyboard actions for the JOptionpane.
1187
   */
1188
  protected void installKeyboardActions()
1189
  {
1190
    // FIXME: implement.
1191
  }
1192
 
1193
  /**
1194
   * This method installs listeners for the JOptionPane.
1195
   */
1196
  protected void installListeners()
1197
  {
1198
    propertyChangeListener = createPropertyChangeListener();
1199
 
1200
    optionPane.addPropertyChangeListener(propertyChangeListener);
1201
  }
1202
 
1203
  /**
1204
   * This method installs the UI for the JOptionPane.
1205
   *
1206
   * @param c The JComponent to install the UI for.
1207
   */
1208
  public void installUI(JComponent c)
1209
  {
1210
    if (c instanceof JOptionPane)
1211
      {
1212
        optionPane = (JOptionPane) c;
1213
 
1214
        installDefaults();
1215
        installComponents();
1216
        installListeners();
1217
        installKeyboardActions();
1218
      }
1219
  }
1220
 
1221
  /**
1222
   * Changes the inputValue property in the JOptionPane based on the current
1223
   * value of the inputComponent.
1224
   */
1225
  protected void resetInputValue()
1226
  {
1227
    if (optionPane.getWantsInput() && inputComponent != null)
1228
      {
1229
        Object output = null;
1230
        if (inputComponent instanceof JTextField)
1231
          output = ((JTextField) inputComponent).getText();
1232
        else if (inputComponent instanceof JComboBox)
1233
          output = ((JComboBox) inputComponent).getSelectedItem();
1234
        else if (inputComponent instanceof JList)
1235
          output = ((JList) inputComponent).getSelectedValue();
1236
 
1237
        if (output != null)
1238
          optionPane.setInputValue(output);
1239
      }
1240
  }
1241
 
1242
  /**
1243
   * This method requests focus to the inputComponent (if one is present) and
1244
   * the initialFocusComponent otherwise.
1245
   *
1246
   * @param op The JOptionPane.
1247
   */
1248
  public void selectInitialValue(JOptionPane op)
1249
  {
1250
    if (inputComponent != null)
1251
      {
1252
        inputComponent.requestFocus();
1253
        return;
1254
      }
1255
    if (initialFocusComponent != null)
1256
      initialFocusComponent.requestFocus();
1257
  }
1258
 
1259
  /**
1260
   * This method resets the value in the inputComponent to the
1261
   * initialSelectionValue property.
1262
   * This is package-private to avoid an accessor method.
1263
   */
1264
  void resetSelectedValue()
1265
  {
1266
    if (inputComponent != null)
1267
      {
1268
        Object init = optionPane.getInitialSelectionValue();
1269
        if (init == null)
1270
          return;
1271
        if (inputComponent instanceof JTextField)
1272
          ((JTextField) inputComponent).setText((String) init);
1273
        else if (inputComponent instanceof JComboBox)
1274
          ((JComboBox) inputComponent).setSelectedItem(init);
1275
        else if (inputComponent instanceof JList)
1276
          {
1277
            //  ((JList) inputComponent).setSelectedValue(init, true);
1278
          }
1279
      }
1280
  }
1281
 
1282
  /**
1283
   * This method uninstalls all the components in the JOptionPane.
1284
   */
1285
  protected void uninstallComponents()
1286
  {
1287
    optionPane.removeAll();
1288
    buttonContainer = null;
1289
    messageAreaContainer = null;
1290
  }
1291
 
1292
  /**
1293
   * This method uninstalls the defaults for the JOptionPane.
1294
   */
1295
  protected void uninstallDefaults()
1296
  {
1297
    optionPane.setFont(null);
1298
    optionPane.setForeground(null);
1299
    optionPane.setBackground(null);
1300
 
1301
    minimumSize = null;
1302
 
1303
    messageBorder = null;
1304
    buttonBorder = null;
1305
    messageForeground = null;
1306
 
1307
    // FIXME: ImageIcons don't seem to work properly
1308
 
1309
    /*
1310
    warningIcon = null;
1311
    errorIcon = null;
1312
    questionIcon = null;
1313
    infoIcon = null;
1314
    */
1315
  }
1316
 
1317
  /**
1318
   * This method uninstalls keyboard actions for the JOptionPane.
1319
   */
1320
  protected void uninstallKeyboardActions()
1321
  {
1322
    // FIXME: implement.
1323
  }
1324
 
1325
  /**
1326
   * This method uninstalls listeners for the JOptionPane.
1327
   */
1328
  protected void uninstallListeners()
1329
  {
1330
    optionPane.removePropertyChangeListener(propertyChangeListener);
1331
    propertyChangeListener = null;
1332
  }
1333
 
1334
  /**
1335
   * This method uninstalls the UI for the given JComponent.
1336
   *
1337
   * @param c The JComponent to uninstall for.
1338
   */
1339
  public void uninstallUI(JComponent c)
1340
  {
1341
    uninstallKeyboardActions();
1342
    uninstallListeners();
1343
    uninstallComponents();
1344
    uninstallDefaults();
1345
 
1346
    optionPane = null;
1347
  }
1348
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.