Imported GNU Classpath 0.20
[official-gcc.git] / libjava / classpath / javax / swing / plaf / basic / BasicOptionPaneUI.java
blob005a3b394a8460df9a69121590e933a5576fdb5e
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 || msg.toString().contains("\n"))
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 if (d == null || c == null)
800 return;
802 int newlineIndex = d.indexOf('\n');
803 String line;
804 String remainder;
805 if (newlineIndex >= 0 && newlineIndex < maxll)
807 line = d.substring(0, newlineIndex);
808 remainder = d.substring(newlineIndex + 1);
810 else
812 line = d.substring(0, maxll);
813 remainder = d.substring(maxll);
815 JLabel label = new JLabel(line);
816 c.add(label);
818 // If there is nothing left to burst, then we can stop.
819 if (remainder.length() == 0)
820 return;
822 // Recursivly call ourselves to burst the remainder of the string,
823 if ((remainder.length() > maxll || remainder.contains("\n")))
824 burstStringInto(c, remainder, maxll);
825 else
826 // Add the remainder to the container and be done.
827 c.add(new JLabel(remainder));
831 * This method returns true if the given JOptionPane contains custom
832 * components.
834 * @param op The JOptionPane to check.
836 * @return True if the JOptionPane contains custom components.
838 public boolean containsCustomComponents(JOptionPane op)
840 return hasCustomComponents;
844 * This method creates a button action listener for the given button index.
846 * @param buttonIndex The index of the button in components.
848 * @return A new ButtonActionListener.
850 protected ActionListener createButtonActionListener(int buttonIndex)
852 return new ButtonActionListener(buttonIndex);
856 * This method creates the button area.
858 * @return A new Button Area.
860 protected Container createButtonArea()
862 JPanel buttonPanel = new JPanel();
864 buttonPanel.setLayout(createLayoutManager());
865 addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex());
867 return buttonPanel;
871 * This method creates a new LayoutManager for the button area.
873 * @return A new LayoutManager for the button area.
875 protected LayoutManager createLayoutManager()
877 return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6);
881 * This method creates the message area.
883 * @return A new message area.
885 protected Container createMessageArea()
887 JPanel messageArea = new JPanel();
888 messageArea.setLayout(new BorderLayout());
889 addIcon(messageArea);
891 JPanel rightSide = new JPanel();
892 rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
893 rightSide.setLayout(new GridBagLayout());
894 GridBagConstraints con = createConstraints();
896 addMessageComponents(rightSide, con, getMessage(),
897 getMaxCharactersPerLineCount(), false);
899 if (optionPane.getWantsInput())
901 Object[] selection = optionPane.getSelectionValues();
903 if (selection == null)
904 inputComponent = new JTextField(15);
905 else if (selection.length < 20)
906 inputComponent = new JComboBox(selection);
907 else
908 inputComponent = new JList(selection);
909 if (inputComponent != null)
911 addMessageComponents(rightSide, con, inputComponent,
912 getMaxCharactersPerLineCount(), false);
913 resetSelectedValue();
914 selectInitialValue(optionPane);
918 messageArea.add(rightSide, BorderLayout.CENTER);
920 return messageArea;
924 * This method creates a new PropertyChangeListener for listening to the
925 * JOptionPane.
927 * @return A new PropertyChangeListener.
929 protected PropertyChangeListener createPropertyChangeListener()
931 return new PropertyChangeHandler();
935 * This method creates a Container that will separate the message and button
936 * areas.
938 * @return A Container that will separate the message and button areas.
940 protected Container createSeparator()
942 // FIXME: Figure out what this method is supposed to return and where
943 // this should be added to the OptionPane.
944 return null;
948 * This method creates a new BasicOptionPaneUI for the given component.
950 * @param x The component to create a UI for.
952 * @return A new BasicOptionPaneUI.
954 public static ComponentUI createUI(JComponent x)
956 return new BasicOptionPaneUI();
960 * This method returns the buttons for the JOptionPane. If no options are
961 * set, a set of options will be created based upon the optionType.
963 * @return The buttons that will be added.
965 protected Object[] getButtons()
967 if (optionPane.getOptions() != null)
968 return optionPane.getOptions();
969 switch (optionPane.getOptionType())
971 case JOptionPane.YES_NO_OPTION:
972 return new Object[] { YES_STRING, NO_STRING };
973 case JOptionPane.YES_NO_CANCEL_OPTION:
974 return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING };
975 case JOptionPane.OK_CANCEL_OPTION:
976 return new Object[] { OK_STRING, CANCEL_STRING };
977 case JOptionPane.DEFAULT_OPTION:
978 return (optionPane.getWantsInput() ) ?
979 new Object[] { OK_STRING, CANCEL_STRING } :
980 ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ?
981 new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } :
982 // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE
983 new Object[] { OK_STRING };
985 return null;
989 * This method will return the icon the user has set or the icon that will
990 * be used based on message type.
992 * @return The icon to use in the JOptionPane.
994 protected Icon getIcon()
996 if (optionPane.getIcon() != null)
997 return optionPane.getIcon();
998 else
999 return getIconForType(optionPane.getMessageType());
1003 * This method returns the icon for the given messageType.
1005 * @param messageType The type of message.
1007 * @return The icon for the given messageType.
1009 protected Icon getIconForType(int messageType)
1011 Icon tmp = null;
1012 switch (messageType)
1014 case JOptionPane.ERROR_MESSAGE:
1015 tmp = errorIcon;
1016 break;
1017 case JOptionPane.INFORMATION_MESSAGE:
1018 tmp = infoIcon;
1019 break;
1020 case JOptionPane.WARNING_MESSAGE:
1021 tmp = warningIcon;
1022 break;
1023 case JOptionPane.QUESTION_MESSAGE:
1024 tmp = questionIcon;
1025 break;
1027 return tmp;
1028 // FIXME: Don't cast till the default icons are in.
1029 // return new IconUIResource(tmp);
1033 * This method returns the index of the initialValue in the options array.
1035 * @return The index of the initalValue.
1037 protected int getInitialValueIndex()
1039 Object[] buttons = getButtons();
1041 if (buttons == null)
1042 return -1;
1044 Object select = optionPane.getInitialValue();
1046 for (int i = 0; i < buttons.length; i++)
1048 if (select == buttons[i])
1049 return i;
1051 return 0;
1055 * This method returns the maximum number of characters that should be
1056 * placed on a line.
1058 * @return The maximum number of characteres that should be placed on a
1059 * line.
1061 protected int getMaxCharactersPerLineCount()
1063 return optionPane.getMaxCharactersPerLineCount();
1067 * This method returns the maximum size.
1069 * @param c The JComponent to measure.
1071 * @return The maximum size.
1073 public Dimension getMaximumSize(JComponent c)
1075 return getPreferredSize(c);
1079 * This method returns the message of the JOptionPane.
1081 * @return The message.
1083 protected Object getMessage()
1085 return optionPane.getMessage();
1089 * This method returns the minimum size of the JOptionPane.
1091 * @return The minimum size.
1093 public Dimension getMinimumOptionPaneSize()
1095 return minimumSize;
1099 * This method returns the minimum size.
1101 * @param c The JComponent to measure.
1103 * @return The minimum size.
1105 public Dimension getMinimumSize(JComponent c)
1107 return getPreferredSize(c);
1111 * This method returns the preferred size of the JOptionPane. The preferred
1112 * size is the maximum of the size desired by the layout and the minimum
1113 * size.
1115 * @param c The JComponent to measure.
1117 * @return The preferred size.
1119 public Dimension getPreferredSize(JComponent c)
1121 Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane);
1122 Dimension d2 = getMinimumOptionPaneSize();
1124 int w = Math.max(d.width, d2.width);
1125 int h = Math.max(d.height, d2.height);
1126 return new Dimension(w, h);
1130 * This method returns whether all buttons should have the same width.
1132 * @return Whether all buttons should have the same width.
1134 protected boolean getSizeButtonsToSameWidth()
1136 return true;
1140 * This method installs components for the JOptionPane.
1142 protected void installComponents()
1144 // reset it.
1145 hasCustomComponents = false;
1146 Container msg = createMessageArea();
1147 if (msg != null)
1149 ((JComponent) msg).setBorder(messageBorder);
1150 msg.setForeground(messageForeground);
1151 messageAreaContainer = msg;
1152 optionPane.add(msg);
1155 // FIXME: Figure out if the separator should be inserted here or what
1156 // this thing is supposed to do. Note: The JDK does NOT insert another
1157 // component at this place. The JOptionPane only has two panels in it
1158 // and there actually are applications that depend on this beeing so.
1159 Container sep = createSeparator();
1160 if (sep != null)
1161 optionPane.add(sep);
1163 Container button = createButtonArea();
1164 if (button != null)
1166 ((JComponent) button).setBorder(buttonBorder);
1167 buttonContainer = button;
1168 optionPane.add(button);
1171 optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
1172 optionPane.invalidate();
1176 * This method installs defaults for the JOptionPane.
1178 protected void installDefaults()
1180 LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
1181 "OptionPane.foreground",
1182 "OptionPane.font");
1183 LookAndFeel.installBorder(optionPane, "OptionPane.border");
1184 optionPane.setOpaque(true);
1186 messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
1187 messageForeground = UIManager.getColor("OptionPane.messageForeground");
1188 buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");
1190 minimumSize = UIManager.getDimension("OptionPane.minimumSize");
1192 // FIXME: Image icons don't seem to work properly right now.
1193 // Once they do, replace the synthetic icons with these ones.
1196 warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon");
1197 infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon");
1198 errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon");
1199 questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon");
1204 * This method installs keyboard actions for the JOptionpane.
1206 protected void installKeyboardActions()
1208 // FIXME: implement.
1212 * This method installs listeners for the JOptionPane.
1214 protected void installListeners()
1216 propertyChangeListener = createPropertyChangeListener();
1218 optionPane.addPropertyChangeListener(propertyChangeListener);
1222 * This method installs the UI for the JOptionPane.
1224 * @param c The JComponent to install the UI for.
1226 public void installUI(JComponent c)
1228 if (c instanceof JOptionPane)
1230 optionPane = (JOptionPane) c;
1232 installDefaults();
1233 installComponents();
1234 installListeners();
1235 installKeyboardActions();
1240 * Changes the inputValue property in the JOptionPane based on the current
1241 * value of the inputComponent.
1243 protected void resetInputValue()
1245 if (optionPane.getWantsInput() && inputComponent != null)
1247 Object output = null;
1248 if (inputComponent instanceof JTextField)
1249 output = ((JTextField) inputComponent).getText();
1250 else if (inputComponent instanceof JComboBox)
1251 output = ((JComboBox) inputComponent).getSelectedItem();
1252 else if (inputComponent instanceof JList)
1253 output = ((JList) inputComponent).getSelectedValue();
1255 if (output != null)
1256 optionPane.setInputValue(output);
1261 * This method requests focus to the inputComponent (if one is present) and
1262 * the initialFocusComponent otherwise.
1264 * @param op The JOptionPane.
1266 public void selectInitialValue(JOptionPane op)
1268 if (inputComponent != null)
1270 inputComponent.requestFocus();
1271 return;
1273 if (initialFocusComponent != null)
1274 initialFocusComponent.requestFocus();
1278 * This method resets the value in the inputComponent to the
1279 * initialSelectionValue property.
1280 * This is package-private to avoid an accessor method.
1282 void resetSelectedValue()
1284 if (inputComponent != null)
1286 Object init = optionPane.getInitialSelectionValue();
1287 if (init == null)
1288 return;
1289 if (inputComponent instanceof JTextField)
1290 ((JTextField) inputComponent).setText((String) init);
1291 else if (inputComponent instanceof JComboBox)
1292 ((JComboBox) inputComponent).setSelectedItem(init);
1293 else if (inputComponent instanceof JList)
1295 // ((JList) inputComponent).setSelectedValue(init, true);
1301 * This method uninstalls all the components in the JOptionPane.
1303 protected void uninstallComponents()
1305 optionPane.removeAll();
1306 buttonContainer = null;
1307 messageAreaContainer = null;
1311 * This method uninstalls the defaults for the JOptionPane.
1313 protected void uninstallDefaults()
1315 optionPane.setFont(null);
1316 optionPane.setForeground(null);
1317 optionPane.setBackground(null);
1319 minimumSize = null;
1321 messageBorder = null;
1322 buttonBorder = null;
1323 messageForeground = null;
1325 // FIXME: ImageIcons don't seem to work properly
1328 warningIcon = null;
1329 errorIcon = null;
1330 questionIcon = null;
1331 infoIcon = null;
1336 * This method uninstalls keyboard actions for the JOptionPane.
1338 protected void uninstallKeyboardActions()
1340 // FIXME: implement.
1344 * This method uninstalls listeners for the JOptionPane.
1346 protected void uninstallListeners()
1348 optionPane.removePropertyChangeListener(propertyChangeListener);
1349 propertyChangeListener = null;
1353 * This method uninstalls the UI for the given JComponent.
1355 * @param c The JComponent to uninstall for.
1357 public void uninstallUI(JComponent c)
1359 uninstallKeyboardActions();
1360 uninstallListeners();
1361 uninstallComponents();
1362 uninstallDefaults();
1364 optionPane = null;