28 import sun.swing.DefaultLookup;
29 import sun.swing.UIAction;
30 import javax.swing.border.Border;
31 import javax.swing.border.EmptyBorder;
32 import javax.swing.*;
33 import javax.swing.event.*;
34 import javax.swing.plaf.ActionMapUIResource;
35 import javax.swing.plaf.ComponentUI;
36 import javax.swing.plaf.OptionPaneUI;
37 import java.awt.*;
38 import java.awt.event.*;
39 import java.beans.PropertyChangeEvent;
40 import java.beans.PropertyChangeListener;
41 import java.util.Locale;
42 import java.security.AccessController;
43
44 import sun.security.action.GetPropertyAction;
45
46
47 /**
48 * Provides the basic look and feel for a <code>JOptionPane</code>.
49 * <code>BasicMessagePaneUI</code> provides a means to place an icon,
50 * message and buttons into a <code>Container</code>.
51 * Generally, the layout will look like:
52 * <pre>
53 * ------------------
54 * | i | message |
55 * | c | message |
56 * | o | message |
57 * | n | message |
58 * ------------------
59 * | buttons |
60 * |________________|
61 * </pre>
62 * icon is an instance of <code>Icon</code> that is wrapped inside a
63 * <code>JLabel</code>. The message is an opaque object and is tested
64 * for the following: if the message is a <code>Component</code> it is
65 * added to the <code>Container</code>, if it is an <code>Icon</code>
66 * it is wrapped inside a <code>JLabel</code> and added to the
67 * <code>Container</code> otherwise it is wrapped inside a <code>JLabel</code>.
68 * <p>
69 * The above layout is used when the option pane's
70 * <code>ComponentOrientation</code> property is horizontal, left-to-right.
71 * The layout will be adjusted appropriately for other orientations.
72 * <p>
73 * The <code>Container</code>, message, icon, and buttons are all
74 * determined from abstract methods.
75 *
76 * @author James Gosling
77 * @author Scott Violet
78 * @author Amy Fowler
79 */
80 public class BasicOptionPaneUI extends OptionPaneUI {
81
82 /**
83 * The mininum width of {@code JOptionPane}.
84 */
85 public static final int MinimumWidth = 262;
86 /**
87 * The mininum height of {@code JOptionPane}.
88 */
89 public static final int MinimumHeight = 90;
90
91 private static String newline;
92
93 /**
128 }
129
130 static void loadActionMap(LazyActionMap map) {
131 map.put(new Actions(Actions.CLOSE));
132 BasicLookAndFeel.installAudioActionMap(map);
133 }
134
135
136
137 /**
138 * Creates a new {@code BasicOptionPaneUI} instance.
139 * @param x the component
140 * @return a new {@code BasicOptionPaneUI} instance
141 */
142 public static ComponentUI createUI(JComponent x) {
143 return new BasicOptionPaneUI();
144 }
145
146 /**
147 * Installs the receiver as the L&F for the passed in
148 * <code>JOptionPane</code>.
149 */
150 public void installUI(JComponent c) {
151 optionPane = (JOptionPane)c;
152 installDefaults();
153 optionPane.setLayout(createLayoutManager());
154 installComponents();
155 installListeners();
156 installKeyboardActions();
157 }
158
159 /**
160 * Removes the receiver from the L&F controller of the passed in split
161 * pane.
162 */
163 public void uninstallUI(JComponent c) {
164 uninstallComponents();
165 optionPane.setLayout(null);
166 uninstallKeyboardActions();
167 uninstallListeners();
168 uninstallDefaults();
287 }
288 }
289 return null;
290 }
291
292 /**
293 * Returns the minimum size the option pane should be. Primarily
294 * provided for subclassers wishing to offer a different minimum size.
295 *
296 * @return the minimum size of the option pane
297 */
298 public Dimension getMinimumOptionPaneSize() {
299 if (minimumSize == null) {
300 return new Dimension(MinimumWidth, MinimumHeight);
301 }
302 return new Dimension(minimumSize.width,
303 minimumSize.height);
304 }
305
306 /**
307 * If <code>c</code> is the <code>JOptionPane</code> the receiver
308 * is contained in, the preferred
309 * size that is returned is the maximum of the preferred size of
310 * the <code>LayoutManager</code> for the <code>JOptionPane</code>, and
311 * <code>getMinimumOptionPaneSize</code>.
312 */
313 public Dimension getPreferredSize(JComponent c) {
314 if (c == optionPane) {
315 Dimension ourMin = getMinimumOptionPaneSize();
316 LayoutManager lm = c.getLayout();
317
318 if (lm != null) {
319 Dimension lmSize = lm.preferredLayoutSize(c);
320
321 if (ourMin != null)
322 return new Dimension
323 (Math.max(lmSize.width, ourMin.width),
324 Math.max(lmSize.height, ourMin.height));
325 return lmSize;
326 }
327 return ourMin;
328 }
329 return null;
330 }
331
816 }
817 }
818 }
819 }
820
821 /**
822 * Constructs a new instance of a {@code ButtonActionListener}.
823 *
824 * @param buttonIndex an index of the button
825 * @return a new instance of a {@code ButtonActionListener}
826 */
827 protected ActionListener createButtonActionListener(int buttonIndex) {
828 return new ButtonActionListener(buttonIndex);
829 }
830
831 /**
832 * Returns the buttons to display from the {@code JOptionPane} the receiver is
833 * providing the look and feel for. If the {@code JOptionPane} has options
834 * set, they will be provided, otherwise if the optionType is
835 * {@code YES_NO_OPTION}, {@code yesNoOptions} is returned, if the type is
836 * {@code YES_NO_CANCEL_OPTION} {@code yesNoCancelOptions} is returned, otherwise
837 * {@code defaultButtons} are returned.
838 *
839 * @return the buttons to display from the JOptionPane
840 */
841 protected Object[] getButtons() {
842 if (optionPane != null) {
843 Object[] suppliedOptions = optionPane.getOptions();
844
845 if (suppliedOptions == null) {
846 Object[] defaultOptions;
847 int type = optionPane.getOptionType();
848 Locale l = optionPane.getLocale();
849 int minimumWidth =
850 DefaultLookup.getInt(optionPane, this,
851 "OptionPane.buttonMinimumWidth",-1);
852 if (type == JOptionPane.YES_NO_OPTION) {
853 defaultOptions = new ButtonFactory[2];
854 defaultOptions[0] = new ButtonFactory(
855 UIManager.getString("OptionPane.yesButtonText", l),
856 getMnemonic("OptionPane.yesButtonMnemonic", l),
986
987 if (initialFocusComponent instanceof JButton) {
988 JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
989 if (root != null) {
990 root.setDefaultButton((JButton)initialFocusComponent);
991 }
992 }
993 }
994 }
995
996 /**
997 * Returns true if in the last call to validateComponent the message
998 * or buttons contained a subclass of Component.
999 */
1000 public boolean containsCustomComponents(JOptionPane op) {
1001 return hasCustomComponents;
1002 }
1003
1004
1005 /**
1006 * <code>ButtonAreaLayout</code> behaves in a similar manner to
1007 * <code>FlowLayout</code>. It lays out all components from left to
1008 * right. If <code>syncAllWidths</code> is true, the widths of each
1009 * component will be set to the largest preferred size width.
1010 *
1011 * This class should be treated as a "protected" inner class.
1012 * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1013 */
1014 public static class ButtonAreaLayout implements LayoutManager {
1015 /**
1016 * The value represents if the width of children should be synchronized.
1017 */
1018 protected boolean syncAllWidths;
1019 /**
1020 * The padding value.
1021 */
1022 protected int padding;
1023 /** If true, children are lumped together in parent. */
1024 protected boolean centersChildren;
1025 private int orientation;
1026 private boolean reverseButtons;
1027 /**
1028 * Indicates whether or not centersChildren should be used vs
1241 }
1242 }
1243 }
1244 return new Dimension(0, 0);
1245 }
1246
1247 public Dimension preferredLayoutSize(Container c) {
1248 return minimumLayoutSize(c);
1249 }
1250
1251 public void removeLayoutComponent(Component c) { }
1252 }
1253
1254
1255 /**
1256 * This class should be treated as a "protected" inner class.
1257 * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1258 */
1259 public class PropertyChangeHandler implements PropertyChangeListener {
1260 /**
1261 * If the source of the PropertyChangeEvent <code>e</code> equals the
1262 * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
1263 * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
1264 * validateComponent is invoked.
1265 */
1266 public void propertyChange(PropertyChangeEvent e) {
1267 getHandler().propertyChange(e);
1268 }
1269 }
1270
1271 /**
1272 * Configures any necessary colors/fonts for the specified label
1273 * used representing the message.
1274 */
1275 private void configureMessageLabel(JLabel label) {
1276 Color color = (Color)DefaultLookup.get(optionPane, this,
1277 "OptionPane.messageForeground");
1278 if (color != null) {
1279 label.setForeground(color);
1280 }
1281 Font messageFont = (Font)DefaultLookup.get(optionPane, this,
1509
1510 if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
1511 for (int counter = strokes.length - 1; counter >= 0;
1512 counter--) {
1513 if (strokes[counter].equals(ks)) {
1514 // Returning false will allow further processing
1515 // of the bindings, eg our parent Containers will get a
1516 // crack at them.
1517 return false;
1518 }
1519 }
1520 }
1521 return processed;
1522 }
1523 }
1524
1525
1526
1527 /**
1528 * Registered in the ActionMap. Sets the value of the option pane
1529 * to <code>JOptionPane.CLOSED_OPTION</code>.
1530 */
1531 private static class Actions extends UIAction {
1532 private static final String CLOSE = "close";
1533
1534 Actions(String key) {
1535 super(key);
1536 }
1537
1538 public void actionPerformed(ActionEvent e) {
1539 if (getName() == CLOSE) {
1540 JOptionPane optionPane = (JOptionPane)e.getSource();
1541
1542 optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
1543 }
1544 }
1545 }
1546
1547
1548 /**
1549 * This class is used to create the default buttons. This indirection is
|
28 import sun.swing.DefaultLookup;
29 import sun.swing.UIAction;
30 import javax.swing.border.Border;
31 import javax.swing.border.EmptyBorder;
32 import javax.swing.*;
33 import javax.swing.event.*;
34 import javax.swing.plaf.ActionMapUIResource;
35 import javax.swing.plaf.ComponentUI;
36 import javax.swing.plaf.OptionPaneUI;
37 import java.awt.*;
38 import java.awt.event.*;
39 import java.beans.PropertyChangeEvent;
40 import java.beans.PropertyChangeListener;
41 import java.util.Locale;
42 import java.security.AccessController;
43
44 import sun.security.action.GetPropertyAction;
45
46
47 /**
48 * Provides the basic look and feel for a {@code JOptionPane}.
49 * {@code BasicMessagePaneUI} provides a means to place an icon,
50 * message and buttons into a {@code Container}.
51 * Generally, the layout will look like:
52 * <pre>
53 * ------------------
54 * | i | message |
55 * | c | message |
56 * | o | message |
57 * | n | message |
58 * ------------------
59 * | buttons |
60 * |________________|
61 * </pre>
62 * icon is an instance of {@code Icon} that is wrapped inside a
63 * {@code JLabel}. The message is an opaque object and is tested
64 * for the following: if the message is a {@code Component} it is
65 * added to the {@code Container}, if it is an {@code Icon}
66 * it is wrapped inside a {@code JLabel} and added to the
67 * {@code Container} otherwise it is wrapped inside a {@code JLabel}.
68 * <p>
69 * The above layout is used when the option pane's
70 * {@code ComponentOrientation} property is horizontal, left-to-right.
71 * The layout will be adjusted appropriately for other orientations.
72 * <p>
73 * The {@code Container}, message, icon, and buttons are all
74 * determined from abstract methods.
75 *
76 * @author James Gosling
77 * @author Scott Violet
78 * @author Amy Fowler
79 */
80 public class BasicOptionPaneUI extends OptionPaneUI {
81
82 /**
83 * The mininum width of {@code JOptionPane}.
84 */
85 public static final int MinimumWidth = 262;
86 /**
87 * The mininum height of {@code JOptionPane}.
88 */
89 public static final int MinimumHeight = 90;
90
91 private static String newline;
92
93 /**
128 }
129
130 static void loadActionMap(LazyActionMap map) {
131 map.put(new Actions(Actions.CLOSE));
132 BasicLookAndFeel.installAudioActionMap(map);
133 }
134
135
136
137 /**
138 * Creates a new {@code BasicOptionPaneUI} instance.
139 * @param x the component
140 * @return a new {@code BasicOptionPaneUI} instance
141 */
142 public static ComponentUI createUI(JComponent x) {
143 return new BasicOptionPaneUI();
144 }
145
146 /**
147 * Installs the receiver as the L&F for the passed in
148 * {@code JOptionPane}.
149 */
150 public void installUI(JComponent c) {
151 optionPane = (JOptionPane)c;
152 installDefaults();
153 optionPane.setLayout(createLayoutManager());
154 installComponents();
155 installListeners();
156 installKeyboardActions();
157 }
158
159 /**
160 * Removes the receiver from the L&F controller of the passed in split
161 * pane.
162 */
163 public void uninstallUI(JComponent c) {
164 uninstallComponents();
165 optionPane.setLayout(null);
166 uninstallKeyboardActions();
167 uninstallListeners();
168 uninstallDefaults();
287 }
288 }
289 return null;
290 }
291
292 /**
293 * Returns the minimum size the option pane should be. Primarily
294 * provided for subclassers wishing to offer a different minimum size.
295 *
296 * @return the minimum size of the option pane
297 */
298 public Dimension getMinimumOptionPaneSize() {
299 if (minimumSize == null) {
300 return new Dimension(MinimumWidth, MinimumHeight);
301 }
302 return new Dimension(minimumSize.width,
303 minimumSize.height);
304 }
305
306 /**
307 * If {@code c} is the {@code JOptionPane} the receiver
308 * is contained in, the preferred
309 * size that is returned is the maximum of the preferred size of
310 * the {@code LayoutManager} for the {@code JOptionPane}, and
311 * {@code getMinimumOptionPaneSize}.
312 */
313 public Dimension getPreferredSize(JComponent c) {
314 if (c == optionPane) {
315 Dimension ourMin = getMinimumOptionPaneSize();
316 LayoutManager lm = c.getLayout();
317
318 if (lm != null) {
319 Dimension lmSize = lm.preferredLayoutSize(c);
320
321 if (ourMin != null)
322 return new Dimension
323 (Math.max(lmSize.width, ourMin.width),
324 Math.max(lmSize.height, ourMin.height));
325 return lmSize;
326 }
327 return ourMin;
328 }
329 return null;
330 }
331
816 }
817 }
818 }
819 }
820
821 /**
822 * Constructs a new instance of a {@code ButtonActionListener}.
823 *
824 * @param buttonIndex an index of the button
825 * @return a new instance of a {@code ButtonActionListener}
826 */
827 protected ActionListener createButtonActionListener(int buttonIndex) {
828 return new ButtonActionListener(buttonIndex);
829 }
830
831 /**
832 * Returns the buttons to display from the {@code JOptionPane} the receiver is
833 * providing the look and feel for. If the {@code JOptionPane} has options
834 * set, they will be provided, otherwise if the optionType is
835 * {@code YES_NO_OPTION}, {@code yesNoOptions} is returned, if the type is
836 * {@code YES_NO_CANCEL_OPTION yesNoCancelOptions} is returned, otherwise
837 * {@code defaultButtons} are returned.
838 *
839 * @return the buttons to display from the JOptionPane
840 */
841 protected Object[] getButtons() {
842 if (optionPane != null) {
843 Object[] suppliedOptions = optionPane.getOptions();
844
845 if (suppliedOptions == null) {
846 Object[] defaultOptions;
847 int type = optionPane.getOptionType();
848 Locale l = optionPane.getLocale();
849 int minimumWidth =
850 DefaultLookup.getInt(optionPane, this,
851 "OptionPane.buttonMinimumWidth",-1);
852 if (type == JOptionPane.YES_NO_OPTION) {
853 defaultOptions = new ButtonFactory[2];
854 defaultOptions[0] = new ButtonFactory(
855 UIManager.getString("OptionPane.yesButtonText", l),
856 getMnemonic("OptionPane.yesButtonMnemonic", l),
986
987 if (initialFocusComponent instanceof JButton) {
988 JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
989 if (root != null) {
990 root.setDefaultButton((JButton)initialFocusComponent);
991 }
992 }
993 }
994 }
995
996 /**
997 * Returns true if in the last call to validateComponent the message
998 * or buttons contained a subclass of Component.
999 */
1000 public boolean containsCustomComponents(JOptionPane op) {
1001 return hasCustomComponents;
1002 }
1003
1004
1005 /**
1006 * {@code ButtonAreaLayout} behaves in a similar manner to
1007 * {@code FlowLayout}. It lays out all components from left to
1008 * right. If {@code syncAllWidths} is true, the widths of each
1009 * component will be set to the largest preferred size width.
1010 *
1011 * This class should be treated as a "protected" inner class.
1012 * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1013 */
1014 public static class ButtonAreaLayout implements LayoutManager {
1015 /**
1016 * The value represents if the width of children should be synchronized.
1017 */
1018 protected boolean syncAllWidths;
1019 /**
1020 * The padding value.
1021 */
1022 protected int padding;
1023 /** If true, children are lumped together in parent. */
1024 protected boolean centersChildren;
1025 private int orientation;
1026 private boolean reverseButtons;
1027 /**
1028 * Indicates whether or not centersChildren should be used vs
1241 }
1242 }
1243 }
1244 return new Dimension(0, 0);
1245 }
1246
1247 public Dimension preferredLayoutSize(Container c) {
1248 return minimumLayoutSize(c);
1249 }
1250
1251 public void removeLayoutComponent(Component c) { }
1252 }
1253
1254
1255 /**
1256 * This class should be treated as a "protected" inner class.
1257 * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1258 */
1259 public class PropertyChangeHandler implements PropertyChangeListener {
1260 /**
1261 * If the source of the PropertyChangeEvent {@code e} equals the
1262 * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
1263 * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
1264 * validateComponent is invoked.
1265 */
1266 public void propertyChange(PropertyChangeEvent e) {
1267 getHandler().propertyChange(e);
1268 }
1269 }
1270
1271 /**
1272 * Configures any necessary colors/fonts for the specified label
1273 * used representing the message.
1274 */
1275 private void configureMessageLabel(JLabel label) {
1276 Color color = (Color)DefaultLookup.get(optionPane, this,
1277 "OptionPane.messageForeground");
1278 if (color != null) {
1279 label.setForeground(color);
1280 }
1281 Font messageFont = (Font)DefaultLookup.get(optionPane, this,
1509
1510 if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
1511 for (int counter = strokes.length - 1; counter >= 0;
1512 counter--) {
1513 if (strokes[counter].equals(ks)) {
1514 // Returning false will allow further processing
1515 // of the bindings, eg our parent Containers will get a
1516 // crack at them.
1517 return false;
1518 }
1519 }
1520 }
1521 return processed;
1522 }
1523 }
1524
1525
1526
1527 /**
1528 * Registered in the ActionMap. Sets the value of the option pane
1529 * to {@code JOptionPane.CLOSED_OPTION}.
1530 */
1531 private static class Actions extends UIAction {
1532 private static final String CLOSE = "close";
1533
1534 Actions(String key) {
1535 super(key);
1536 }
1537
1538 public void actionPerformed(ActionEvent e) {
1539 if (getName() == CLOSE) {
1540 JOptionPane optionPane = (JOptionPane)e.getSource();
1541
1542 optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
1543 }
1544 }
1545 }
1546
1547
1548 /**
1549 * This class is used to create the default buttons. This indirection is
|