Imported GNU Classpath 0.19 + gcj-import-20051115.
[official-gcc.git] / libjava / classpath / javax / swing / plaf / basic / BasicOptionPaneUI.java
blob6b37d315fa84f3f5b7261b34070e35adb9e30251
1 /* BasicOptionPaneUI.java --
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package javax.swing.plaf.basic;
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;
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;
80 /**
81 * This class is the UI delegate for JOptionPane in the Basic Look and Feel.
83 public class BasicOptionPaneUI extends OptionPaneUI
85 /**
86 * This is a helper class that listens to the buttons located at the bottom
87 * of the JOptionPane.
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.
93 public class ButtonActionListener implements ActionListener
95 /** The index of the option this button represents. */
96 protected int buttonIndex;
98 /**
99 * Creates a new ButtonActionListener object with the given buttonIndex.
101 * @param buttonIndex The index of the option this button represents.
103 public ButtonActionListener(int buttonIndex)
105 this.buttonIndex = buttonIndex;
109 * This method is called when one of the option buttons are pressed.
111 * @param e The ActionEvent.
113 public void actionPerformed(ActionEvent e)
115 Object value = new Integer(JOptionPane.CLOSED_OPTION);
116 Object[] options = optionPane.getOptions();
117 if (options != null)
118 value = new Integer(buttonIndex);
119 else
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);
131 optionPane.setValue(value);
132 resetInputValue();
134 Window owner = SwingUtilities.windowForComponent(optionPane);
136 if (owner instanceof JDialog)
137 ((JDialog) owner).dispose();
139 //else we probably have some kind of internal frame.
140 JInternalFrame inf = (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class,
141 optionPane);
142 if (inf != null)
146 inf.setClosed(true);
148 catch (PropertyVetoException pve)
150 // We do nothing if attempt has been vetoed.
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.
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.
165 public static class ButtonAreaLayout implements LayoutManager
167 /** Whether this layout will center the buttons. */
168 protected boolean centersChildren = true;
170 /** The space between the buttons. */
171 protected int padding;
173 /** Whether the buttons will share the same widths. */
174 protected boolean syncAllWidths;
176 /** The width of the widest button. */
177 private transient int widthOfWidestButton;
179 /** The height of the tallest button. */
180 private transient int tallestButton;
183 * Creates a new ButtonAreaLayout object with the given sync widths
184 * property and padding.
186 * @param syncAllWidths Whether the buttons will share the same widths.
187 * @param padding The padding between the buttons.
189 public ButtonAreaLayout(boolean syncAllWidths, int padding)
191 this.syncAllWidths = syncAllWidths;
192 this.padding = padding;
196 * This method is called when a component is added to the container.
198 * @param string The constraints string.
199 * @param comp The component added.
201 public void addLayoutComponent(String string, Component comp)
203 // Do nothing.
207 * This method returns whether the children will be centered.
209 * @return Whether the children will be centered.
211 public boolean getCentersChildren()
213 return centersChildren;
217 * This method returns the amount of space between components.
219 * @return The amount of space between components.
221 public int getPadding()
223 return padding;
227 * This method returns whether all components will share widths (set to
228 * largest width).
230 * @return Whether all components will share widths.
232 public boolean getSyncAllWidths()
234 return syncAllWidths;
238 * This method lays out the given container.
240 * @param container The container to lay out.
242 public void layoutContainer(Container container)
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++)
251 Dimension dims = buttonList[i].getPreferredSize();
252 if (syncAllWidths)
254 buttonList[i].setBounds(x, 0, widthOfWidestButton, dims.height);
255 x += widthOfWidestButton + getPadding();
257 else
259 buttonList[i].setBounds(x, 0, dims.width, dims.height);
260 x += dims.width + getPadding();
266 * This method returns the width of the given container taking into
267 * consideration the padding and syncAllWidths.
269 * @param c The container to calculate width for.
271 * @return The width of the given container.
273 private int buttonRowLength(Container c)
275 Component[] buttonList = c.getComponents();
277 int buttonLength = 0;
278 int widest = 0;
279 int tallest = 0;
281 for (int i = 0; i < buttonList.length; i++)
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);
289 widthOfWidestButton = widest;
290 tallestButton = tallest;
292 int width;
293 if (getSyncAllWidths())
294 width = widest * buttonList.length
295 + getPadding() * (buttonList.length - 1);
296 else
297 width = buttonLength;
299 Insets insets = c.getInsets();
300 width += insets.left + insets.right;
302 return width;
306 * This method returns the minimum layout size for the given container.
308 * @param c The container to measure.
310 * @return The minimum layout size.
312 public Dimension minimumLayoutSize(Container c)
314 return preferredLayoutSize(c);
318 * This method returns the preferred size of the given container.
320 * @param c The container to measure.
322 * @return The preferred size.
324 public Dimension preferredLayoutSize(Container c)
326 int w = buttonRowLength(c);
328 return new Dimension(w, tallestButton);
332 * This method removes the given component from the layout manager's
333 * knowledge.
335 * @param c The component to remove.
337 public void removeLayoutComponent(Component c)
339 // Do nothing.
343 * This method sets whether the children will be centered.
345 * @param newValue Whether the children will be centered.
347 public void setCentersChildren(boolean newValue)
349 centersChildren = newValue;
353 * This method sets the amount of space between each component.
355 * @param newPadding The padding between components.
357 public void setPadding(int newPadding)
359 padding = newPadding;
363 * This method sets whether the widths will be synced.
365 * @param newValue Whether the widths will be synced.
367 public void setSyncAllWidths(boolean newValue)
369 syncAllWidths = newValue;
374 * This helper class handles property change events from the JOptionPane.
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.
380 public class PropertyChangeHandler implements PropertyChangeListener
383 * This method is called when one of the properties of the JOptionPane
384 * changes.
386 * @param e The PropertyChangeEvent.
388 public void propertyChange(PropertyChangeEvent e)
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))
399 Container newButtons = createButtonArea();
400 optionPane.remove(buttonContainer);
401 optionPane.add(newButtons);
402 buttonContainer = newButtons;
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))
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);
418 optionPane.invalidate();
419 optionPane.repaint();
424 * The minimum width for JOptionPanes.
426 public static final int MinimumWidth = 262;
429 * The minimum height for JOptionPanes.
431 public static final int MinimumHeight = 90;
433 /** Whether the JOptionPane contains custom components. */
434 protected boolean hasCustomComponents = false;
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).
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.
446 protected Component initialFocusComponent;
448 /** The component that receives input when the JOptionPane needs it. */
449 protected JComponent inputComponent;
451 /** The minimum dimensions of the JOptionPane. */
452 protected Dimension minimumSize;
454 /** The propertyChangeListener for the JOptionPane. */
455 protected PropertyChangeListener propertyChangeListener;
457 /** The JOptionPane this UI delegate is used for. */
458 protected JOptionPane optionPane;
460 /** The size of the icons. */
461 // FIXME: wrong name for a constant.
462 private static final int iconSize = 36;
464 /** The foreground color for the message area. */
465 private transient Color messageForeground;
467 /** The border around the message area. */
468 private transient Border messageBorder;
470 /** The border around the button area. */
471 private transient Border buttonBorder;
473 /** The string used to describe OK buttons. */
474 private static final String OK_STRING = "OK";
476 /** The string used to describe Yes buttons. */
477 private static final String YES_STRING = "Yes";
479 /** The string used to describe No buttons. */
480 private static final String NO_STRING = "No";
482 /** The string used to describe Cancel buttons. */
483 private static final String CANCEL_STRING = "Cancel";
485 /** The container for the message area.
486 * This is package-private to avoid an accessor method. */
487 transient Container messageAreaContainer;
489 /** The container for the buttons.
490 * This is package-private to avoid an accessor method. */
491 transient Container buttonContainer;
494 * A helper class that implements Icon. This is used temporarily until
495 * ImageIcons are fixed.
497 private static class MessageIcon implements Icon
500 * This method returns the width of the icon.
502 * @return The width of the icon.
504 public int getIconWidth()
506 return iconSize;
510 * This method returns the height of the icon.
512 * @return The height of the icon.
514 public int getIconHeight()
516 return iconSize;
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.
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.
528 public void paintIcon(Component c, Graphics g, int x, int y)
530 // Nothing to do here.
534 /** The icon displayed for ERROR_MESSAGE. */
535 private static MessageIcon errorIcon = new MessageIcon()
537 public void paintIcon(Component c, Graphics g, int x, int y)
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);
543 Color saved = g.getColor();
544 g.setColor(Color.RED);
546 g.fillPolygon(oct);
548 g.setColor(Color.BLACK);
549 g.drawRect(13, 16, 10, 4);
551 g.setColor(saved);
552 g.translate(-x, -y);
556 /** The icon displayed for INFORMATION_MESSAGE. */
557 private static MessageIcon infoIcon = new MessageIcon()
559 public void paintIcon(Component c, Graphics g, int x, int y)
561 g.translate(x, y);
562 Color saved = g.getColor();
564 // Should be purple.
565 g.setColor(Color.RED);
567 g.fillOval(0, 0, iconSize, iconSize);
569 g.setColor(Color.BLACK);
570 g.drawOval(16, 6, 4, 4);
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 },
575 g.drawPolygon(bottomI);
577 g.setColor(saved);
578 g.translate(-x, -y);
582 /** The icon displayed for WARNING_MESSAGE. */
583 private static MessageIcon warningIcon = new MessageIcon()
585 public void paintIcon(Component c, Graphics g, int x, int y)
587 g.translate(x, y);
588 Color saved = g.getColor();
589 g.setColor(Color.YELLOW);
591 Polygon triangle = new Polygon(new int[] { 0, 18, 36 },
592 new int[] { 36, 0, 36 }, 3);
593 g.fillPolygon(triangle);
595 g.setColor(Color.BLACK);
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);
602 g.setColor(saved);
603 g.translate(-x, -y);
607 /** The icon displayed for MESSAGE_ICON. */
608 private static MessageIcon questionIcon = new MessageIcon()
610 public void paintIcon(Component c, Graphics g, int x, int y)
612 g.translate(x, y);
613 Color saved = g.getColor();
614 g.setColor(Color.GREEN);
616 g.fillRect(0, 0, iconSize, iconSize);
618 g.setColor(Color.BLACK);
620 g.drawOval(11, 2, 16, 16);
621 g.drawOval(14, 5, 10, 10);
623 g.setColor(Color.GREEN);
624 g.fillRect(0, 10, iconSize, iconSize - 10);
626 g.setColor(Color.BLACK);
628 g.drawLine(11, 10, 14, 10);
630 g.drawLine(24, 10, 17, 22);
631 g.drawLine(27, 10, 20, 22);
632 g.drawLine(17, 22, 20, 22);
634 g.drawOval(17, 25, 3, 3);
636 g.setColor(saved);
637 g.translate(-x, -y);
641 // FIXME: Uncomment when the ImageIcons are fixed.
643 /* IconUIResource warningIcon, questionIcon, infoIcon, errorIcon;*/
646 * Creates a new BasicOptionPaneUI object.
648 public BasicOptionPaneUI()
650 // Nothing to do here.
654 * This method is messaged to add the buttons to the given container.
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.
664 protected void addButtonComponents(Container container, Object[] buttons,
665 int initialIndex)
667 if (buttons == null)
668 return;
669 for (int i = 0; i < buttons.length; i++)
671 if (buttons[i] != null)
673 Component toAdd;
674 if (buttons[i] instanceof Component)
675 toAdd = (Component) buttons[i];
676 else
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;
684 if (toAdd instanceof JButton)
685 ((JButton) toAdd).addActionListener(createButtonActionListener(i));
686 if (i == initialIndex)
687 initialFocusComponent = toAdd;
688 container.add(toAdd);
691 selectInitialValue(optionPane);
695 * This method adds the appropriate icon the given container.
697 * @param top The container to add an icon to.
699 protected void addIcon(Container top)
701 JLabel iconLabel = null;
702 Icon icon = getIcon();
703 if (icon != null)
705 iconLabel = new JLabel(icon);
706 top.add(iconLabel, BorderLayout.WEST);
711 * A helper method that returns an instance of GridBagConstraints to be used
712 * for creating the message area.
714 * @return An instance of GridBagConstraints.
716 private static GridBagConstraints createConstraints()
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);
726 return constraints;
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.
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.
745 protected void addMessageComponents(Container container,
746 GridBagConstraints cons, Object msg,
747 int maxll, boolean internallyCreated)
749 if (msg == null)
750 return;
751 hasCustomComponents = internallyCreated;
752 if (msg instanceof Object[])
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;
760 else if (msg instanceof Component)
762 container.add((Component) msg, cons);
763 cons.gridy++;
765 else if (msg instanceof Icon)
767 container.add(new JLabel((Icon) msg), cons);
768 cons.gridy++;
770 else
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)
779 Box tmp = new Box(BoxLayout.Y_AXIS);
780 burstStringInto(tmp, msg.toString(), maxll);
781 addMessageComponents(container, cons, tmp, maxll, true);
783 else
784 addMessageComponents(container, cons, new JLabel(msg.toString()),
785 maxll, true);
790 * This method creates instances of d (recursively if necessary based on
791 * maxll) and adds to c.
793 * @param c The container to add to.
794 * @param d The string to burst.
795 * @param maxll The max line length.
797 protected void burstStringInto(Container c, String d, int maxll)
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);
813 * This method returns true if the given JOptionPane contains custom
814 * components.
816 * @param op The JOptionPane to check.
818 * @return True if the JOptionPane contains custom components.
820 public boolean containsCustomComponents(JOptionPane op)
822 return hasCustomComponents;
826 * This method creates a button action listener for the given button index.
828 * @param buttonIndex The index of the button in components.
830 * @return A new ButtonActionListener.
832 protected ActionListener createButtonActionListener(int buttonIndex)
834 return new ButtonActionListener(buttonIndex);
838 * This method creates the button area.
840 * @return A new Button Area.
842 protected Container createButtonArea()
844 JPanel buttonPanel = new JPanel();
846 buttonPanel.setLayout(createLayoutManager());
847 addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex());
849 return buttonPanel;
853 * This method creates a new LayoutManager for the button area.
855 * @return A new LayoutManager for the button area.
857 protected LayoutManager createLayoutManager()
859 return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6);
863 * This method creates the message area.
865 * @return A new message area.
867 protected Container createMessageArea()
869 JPanel messageArea = new JPanel();
870 messageArea.setLayout(new BorderLayout());
871 addIcon(messageArea);
873 JPanel rightSide = new JPanel();
874 rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
875 rightSide.setLayout(new GridBagLayout());
876 GridBagConstraints con = createConstraints();
878 addMessageComponents(rightSide, con, getMessage(),
879 getMaxCharactersPerLineCount(), false);
881 if (optionPane.getWantsInput())
883 Object[] selection = optionPane.getSelectionValues();
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)
893 addMessageComponents(rightSide, con, inputComponent,
894 getMaxCharactersPerLineCount(), false);
895 resetSelectedValue();
896 selectInitialValue(optionPane);
900 messageArea.add(rightSide, BorderLayout.CENTER);
902 return messageArea;
906 * This method creates a new PropertyChangeListener for listening to the
907 * JOptionPane.
909 * @return A new PropertyChangeListener.
911 protected PropertyChangeListener createPropertyChangeListener()
913 return new PropertyChangeHandler();
917 * This method creates a Container that will separate the message and button
918 * areas.
920 * @return A Container that will separate the message and button areas.
922 protected Container createSeparator()
924 // FIXME: Figure out what this method is supposed to return and where
925 // this should be added to the OptionPane.
926 return null;
930 * This method creates a new BasicOptionPaneUI for the given component.
932 * @param x The component to create a UI for.
934 * @return A new BasicOptionPaneUI.
936 public static ComponentUI createUI(JComponent x)
938 return new BasicOptionPaneUI();
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.
945 * @return The buttons that will be added.
947 protected Object[] getButtons()
949 if (optionPane.getOptions() != null)
950 return optionPane.getOptions();
951 switch (optionPane.getOptionType())
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 };
967 return null;
971 * This method will return the icon the user has set or the icon that will
972 * be used based on message type.
974 * @return The icon to use in the JOptionPane.
976 protected Icon getIcon()
978 if (optionPane.getIcon() != null)
979 return optionPane.getIcon();
980 else
981 return getIconForType(optionPane.getMessageType());
985 * This method returns the icon for the given messageType.
987 * @param messageType The type of message.
989 * @return The icon for the given messageType.
991 protected Icon getIconForType(int messageType)
993 Icon tmp = null;
994 switch (messageType)
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;
1009 return tmp;
1010 // FIXME: Don't cast till the default icons are in.
1011 // return new IconUIResource(tmp);
1015 * This method returns the index of the initialValue in the options array.
1017 * @return The index of the initalValue.
1019 protected int getInitialValueIndex()
1021 Object[] buttons = getButtons();
1023 if (buttons == null)
1024 return -1;
1026 Object select = optionPane.getInitialValue();
1028 for (int i = 0; i < buttons.length; i++)
1030 if (select == buttons[i])
1031 return i;
1033 return 0;
1037 * This method returns the maximum number of characters that should be
1038 * placed on a line.
1040 * @return The maximum number of characteres that should be placed on a
1041 * line.
1043 protected int getMaxCharactersPerLineCount()
1045 return optionPane.getMaxCharactersPerLineCount();
1049 * This method returns the maximum size.
1051 * @param c The JComponent to measure.
1053 * @return The maximum size.
1055 public Dimension getMaximumSize(JComponent c)
1057 return getPreferredSize(c);
1061 * This method returns the message of the JOptionPane.
1063 * @return The message.
1065 protected Object getMessage()
1067 return optionPane.getMessage();
1071 * This method returns the minimum size of the JOptionPane.
1073 * @return The minimum size.
1075 public Dimension getMinimumOptionPaneSize()
1077 return minimumSize;
1081 * This method returns the minimum size.
1083 * @param c The JComponent to measure.
1085 * @return The minimum size.
1087 public Dimension getMinimumSize(JComponent c)
1089 return getPreferredSize(c);
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.
1097 * @param c The JComponent to measure.
1099 * @return The preferred size.
1101 public Dimension getPreferredSize(JComponent c)
1103 Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane);
1104 Dimension d2 = getMinimumOptionPaneSize();
1106 int w = Math.max(d.width, d2.width);
1107 int h = Math.max(d.height, d2.height);
1108 return new Dimension(w, h);
1112 * This method returns whether all buttons should have the same width.
1114 * @return Whether all buttons should have the same width.
1116 protected boolean getSizeButtonsToSameWidth()
1118 return true;
1122 * This method installs components for the JOptionPane.
1124 protected void installComponents()
1126 // reset it.
1127 hasCustomComponents = false;
1128 Container msg = createMessageArea();
1129 if (msg != null)
1131 ((JComponent) msg).setBorder(messageBorder);
1132 msg.setForeground(messageForeground);
1133 messageAreaContainer = msg;
1134 optionPane.add(msg);
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);
1145 Container button = createButtonArea();
1146 if (button != null)
1148 ((JComponent) button).setBorder(buttonBorder);
1149 buttonContainer = button;
1150 optionPane.add(button);
1153 optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
1154 optionPane.invalidate();
1158 * This method installs defaults for the JOptionPane.
1160 protected void installDefaults()
1162 LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
1163 "OptionPane.foreground",
1164 "OptionPane.font");
1165 LookAndFeel.installBorder(optionPane, "OptionPane.border");
1166 optionPane.setOpaque(true);
1168 messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
1169 messageForeground = UIManager.getColor("OptionPane.messageForeground");
1170 buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");
1172 minimumSize = UIManager.getDimension("OptionPane.minimumSize");
1174 // FIXME: Image icons don't seem to work properly right now.
1175 // Once they do, replace the synthetic icons with these ones.
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");
1186 * This method installs keyboard actions for the JOptionpane.
1188 protected void installKeyboardActions()
1190 // FIXME: implement.
1194 * This method installs listeners for the JOptionPane.
1196 protected void installListeners()
1198 propertyChangeListener = createPropertyChangeListener();
1200 optionPane.addPropertyChangeListener(propertyChangeListener);
1204 * This method installs the UI for the JOptionPane.
1206 * @param c The JComponent to install the UI for.
1208 public void installUI(JComponent c)
1210 if (c instanceof JOptionPane)
1212 optionPane = (JOptionPane) c;
1214 installDefaults();
1215 installComponents();
1216 installListeners();
1217 installKeyboardActions();
1222 * Changes the inputValue property in the JOptionPane based on the current
1223 * value of the inputComponent.
1225 protected void resetInputValue()
1227 if (optionPane.getWantsInput() && inputComponent != null)
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();
1237 if (output != null)
1238 optionPane.setInputValue(output);
1243 * This method requests focus to the inputComponent (if one is present) and
1244 * the initialFocusComponent otherwise.
1246 * @param op The JOptionPane.
1248 public void selectInitialValue(JOptionPane op)
1250 if (inputComponent != null)
1252 inputComponent.requestFocus();
1253 return;
1255 if (initialFocusComponent != null)
1256 initialFocusComponent.requestFocus();
1260 * This method resets the value in the inputComponent to the
1261 * initialSelectionValue property.
1262 * This is package-private to avoid an accessor method.
1264 void resetSelectedValue()
1266 if (inputComponent != null)
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)
1277 // ((JList) inputComponent).setSelectedValue(init, true);
1283 * This method uninstalls all the components in the JOptionPane.
1285 protected void uninstallComponents()
1287 optionPane.removeAll();
1288 buttonContainer = null;
1289 messageAreaContainer = null;
1293 * This method uninstalls the defaults for the JOptionPane.
1295 protected void uninstallDefaults()
1297 optionPane.setFont(null);
1298 optionPane.setForeground(null);
1299 optionPane.setBackground(null);
1301 minimumSize = null;
1303 messageBorder = null;
1304 buttonBorder = null;
1305 messageForeground = null;
1307 // FIXME: ImageIcons don't seem to work properly
1310 warningIcon = null;
1311 errorIcon = null;
1312 questionIcon = null;
1313 infoIcon = null;
1318 * This method uninstalls keyboard actions for the JOptionPane.
1320 protected void uninstallKeyboardActions()
1322 // FIXME: implement.
1326 * This method uninstalls listeners for the JOptionPane.
1328 protected void uninstallListeners()
1330 optionPane.removePropertyChangeListener(propertyChangeListener);
1331 propertyChangeListener = null;
1335 * This method uninstalls the UI for the given JComponent.
1337 * @param c The JComponent to uninstall for.
1339 public void uninstallUI(JComponent c)
1341 uninstallKeyboardActions();
1342 uninstallListeners();
1343 uninstallComponents();
1344 uninstallDefaults();
1346 optionPane = null;