History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/plaf/basic/BasicOptionPaneUI.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/plaf/basic/BasicOptionPaneUI.java+1455−0
@@ -0,0 +1,1455 @@
1+/*
2+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.swing.plaf.basic;
27+
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:<p>
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+ public static final int MinimumWidth = 262;
83+ public static final int MinimumHeight = 90;
84+
85+ private static String newline;
86+
87+ /**
88+ * <code>JOptionPane</code> that the receiver is providing the
89+ * look and feel for.
90+ */
91+ protected JOptionPane optionPane;
92+
93+ protected Dimension minimumSize;
94+
95+ /** JComponent provide for input if optionPane.getWantsInput() returns
96+ * true. */
97+ protected JComponent inputComponent;
98+
99+ /** Component to receive focus when messaged with selectInitialValue. */
100+ protected Component initialFocusComponent;
101+
102+ /** This is set to true in validateComponent if a Component is contained
103+ * in either the message or the buttons. */
104+ protected boolean hasCustomComponents;
105+
106+ protected PropertyChangeListener propertyChangeListener;
107+
108+ private Handler handler;
109+
110+
111+ static {
112+ newline = java.security.AccessController.doPrivileged(
113+ new GetPropertyAction("line.separator"));
114+ if (newline == null) {
115+ newline = "\n";
116+ }
117+ }
118+
119+ static void loadActionMap(LazyActionMap map) {
120+ map.put(new Actions(Actions.CLOSE));
121+ BasicLookAndFeel.installAudioActionMap(map);
122+ }
123+
124+
125+
126+ /**
127+ * Creates a new BasicOptionPaneUI instance.
128+ */
129+ public static ComponentUI createUI(JComponent x) {
130+ return new BasicOptionPaneUI();
131+ }
132+
133+ /**
134+ * Installs the receiver as the L&F for the passed in
135+ * <code>JOptionPane</code>.
136+ */
137+ public void installUI(JComponent c) {
138+ optionPane = (JOptionPane)c;
139+ installDefaults();
140+ optionPane.setLayout(createLayoutManager());
141+ installComponents();
142+ installListeners();
143+ installKeyboardActions();
144+ }
145+
146+ /**
147+ * Removes the receiver from the L&F controller of the passed in split
148+ * pane.
149+ */
150+ public void uninstallUI(JComponent c) {
151+ uninstallComponents();
152+ optionPane.setLayout(null);
153+ uninstallKeyboardActions();
154+ uninstallListeners();
155+ uninstallDefaults();
156+ optionPane = null;
157+ }
158+
159+ protected void installDefaults() {
160+ LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
161+ "OptionPane.foreground", "OptionPane.font");
162+ LookAndFeel.installBorder(optionPane, "OptionPane.border");
163+ minimumSize = UIManager.getDimension("OptionPane.minimumSize");
164+ LookAndFeel.installProperty(optionPane, "opaque", Boolean.TRUE);
165+ }
166+
167+ protected void uninstallDefaults() {
168+ LookAndFeel.uninstallBorder(optionPane);
169+ }
170+
171+ protected void installComponents() {
172+ optionPane.add(createMessageArea());
173+
174+ Container separator = createSeparator();
175+ if (separator != null) {
176+ optionPane.add(separator);
177+ }
178+ optionPane.add(createButtonArea());
179+ optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
180+ }
181+
182+ protected void uninstallComponents() {
183+ hasCustomComponents = false;
184+ inputComponent = null;
185+ initialFocusComponent = null;
186+ optionPane.removeAll();
187+ }
188+
189+ protected LayoutManager createLayoutManager() {
190+ return new BoxLayout(optionPane, BoxLayout.Y_AXIS);
191+ }
192+
193+ protected void installListeners() {
194+ if ((propertyChangeListener = createPropertyChangeListener()) != null) {
195+ optionPane.addPropertyChangeListener(propertyChangeListener);
196+ }
197+ }
198+
199+ protected void uninstallListeners() {
200+ if (propertyChangeListener != null) {
201+ optionPane.removePropertyChangeListener(propertyChangeListener);
202+ propertyChangeListener = null;
203+ }
204+ handler = null;
205+ }
206+
207+ protected PropertyChangeListener createPropertyChangeListener() {
208+ return getHandler();
209+ }
210+
211+ private Handler getHandler() {
212+ if (handler == null) {
213+ handler = new Handler();
214+ }
215+ return handler;
216+ }
217+
218+ protected void installKeyboardActions() {
219+ InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
220+
221+ SwingUtilities.replaceUIInputMap(optionPane, JComponent.
222+ WHEN_IN_FOCUSED_WINDOW, map);
223+
224+ LazyActionMap.installLazyActionMap(optionPane, BasicOptionPaneUI.class,
225+ "OptionPane.actionMap");
226+ }
227+
228+ protected void uninstallKeyboardActions() {
229+ SwingUtilities.replaceUIInputMap(optionPane, JComponent.
230+ WHEN_IN_FOCUSED_WINDOW, null);
231+ SwingUtilities.replaceUIActionMap(optionPane, null);
232+ }
233+
234+ InputMap getInputMap(int condition) {
235+ if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
236+ Object[] bindings = (Object[])DefaultLookup.get(
237+ optionPane, this, "OptionPane.windowBindings");
238+ if (bindings != null) {
239+ return LookAndFeel.makeComponentInputMap(optionPane, bindings);
240+ }
241+ }
242+ return null;
243+ }
244+
245+ /**
246+ * Returns the minimum size the option pane should be. Primarily
247+ * provided for subclassers wishing to offer a different minimum size.
248+ */
249+ public Dimension getMinimumOptionPaneSize() {
250+ if (minimumSize == null) {
251+ return new Dimension(MinimumWidth, MinimumHeight);
252+ }
253+ return new Dimension(minimumSize.width,
254+ minimumSize.height);
255+ }
256+
257+ /**
258+ * If <code>c</code> is the <code>JOptionPane</code> the receiver
259+ * is contained in, the preferred
260+ * size that is returned is the maximum of the preferred size of
261+ * the <code>LayoutManager</code> for the <code>JOptionPane</code>, and
262+ * <code>getMinimumOptionPaneSize</code>.
263+ */
264+ public Dimension getPreferredSize(JComponent c) {
265+ if (c == optionPane) {
266+ Dimension ourMin = getMinimumOptionPaneSize();
267+ LayoutManager lm = c.getLayout();
268+
269+ if (lm != null) {
270+ Dimension lmSize = lm.preferredLayoutSize(c);
271+
272+ if (ourMin != null)
273+ return new Dimension
274+ (Math.max(lmSize.width, ourMin.width),
275+ Math.max(lmSize.height, ourMin.height));
276+ return lmSize;
277+ }
278+ return ourMin;
279+ }
280+ return null;
281+ }
282+
283+ /**
284+ * Messaged from installComponents to create a Container containing the
285+ * body of the message. The icon is the created by calling
286+ * <code>addIcon</code>.
287+ */
288+ protected Container createMessageArea() {
289+ JPanel top = new JPanel();
290+ Border topBorder = (Border)DefaultLookup.get(optionPane, this,
291+ "OptionPane.messageAreaBorder");
292+ if (topBorder != null) {
293+ top.setBorder(topBorder);
294+ }
295+ top.setLayout(new BorderLayout());
296+
297+ /* Fill the body. */
298+ Container body = new JPanel(new GridBagLayout());
299+ Container realBody = new JPanel(new BorderLayout());
300+
301+ body.setName("OptionPane.body");
302+ realBody.setName("OptionPane.realBody");
303+
304+ if (getIcon() != null) {
305+ JPanel sep = new JPanel();
306+ sep.setName("OptionPane.separator");
307+ sep.setPreferredSize(new Dimension(15, 1));
308+ realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
309+ }
310+ realBody.add(body, BorderLayout.CENTER);
311+
312+ GridBagConstraints cons = new GridBagConstraints();
313+ cons.gridx = cons.gridy = 0;
314+ cons.gridwidth = GridBagConstraints.REMAINDER;
315+ cons.gridheight = 1;
316+ cons.anchor = DefaultLookup.getInt(optionPane, this,
317+ "OptionPane.messageAnchor", GridBagConstraints.CENTER);
318+ cons.insets = new Insets(0,0,3,0);
319+
320+ addMessageComponents(body, cons, getMessage(),
321+ getMaxCharactersPerLineCount(), false);
322+ top.add(realBody, BorderLayout.CENTER);
323+
324+ addIcon(top);
325+ return top;
326+ }
327+
328+ /**
329+ * Creates the appropriate object to represent <code>msg</code> and
330+ * places it into <code>container</code>. If <code>msg</code> is an
331+ * instance of Component, it is added directly, if it is an Icon,
332+ * a JLabel is created to represent it, otherwise a JLabel is
333+ * created for the string, if <code>d</code> is an Object[], this
334+ * method will be recursively invoked for the children.
335+ * <code>internallyCreated</code> is true if Objc is an instance
336+ * of Component and was created internally by this method (this is
337+ * used to correctly set hasCustomComponents only if !internallyCreated).
338+ */
339+ protected void addMessageComponents(Container container,
340+ GridBagConstraints cons,
341+ Object msg, int maxll,
342+ boolean internallyCreated) {
343+ if (msg == null) {
344+ return;
345+ }
346+ if (msg instanceof Component) {
347+ // To workaround problem where Gridbad will set child
348+ // to its minimum size if its preferred size will not fit
349+ // within allocated cells
350+ if (msg instanceof JScrollPane || msg instanceof JPanel) {
351+ cons.fill = GridBagConstraints.BOTH;
352+ cons.weighty = 1;
353+ } else {
354+ cons.fill = GridBagConstraints.HORIZONTAL;
355+ }
356+ cons.weightx = 1;
357+
358+ container.add((Component) msg, cons);
359+ cons.weightx = 0;
360+ cons.weighty = 0;
361+ cons.fill = GridBagConstraints.NONE;
362+ cons.gridy++;
363+ if (!internallyCreated) {
364+ hasCustomComponents = true;
365+ }
366+
367+ } else if (msg instanceof Object[]) {
368+ Object [] msgs = (Object[]) msg;
369+ for (Object o : msgs) {
370+ addMessageComponents(container, cons, o, maxll, false);
371+ }
372+
373+ } else if (msg instanceof Icon) {
374+ JLabel label = new JLabel( (Icon)msg, SwingConstants.CENTER );
375+ configureMessageLabel(label);
376+ addMessageComponents(container, cons, label, maxll, true);
377+
378+ } else {
379+ String s = msg.toString();
380+ int len = s.length();
381+ if (len <= 0) {
382+ return;
383+ }
384+ int nl;
385+ int nll = 0;
386+
387+ if ((nl = s.indexOf(newline)) >= 0) {
388+ nll = newline.length();
389+ } else if ((nl = s.indexOf("\r\n")) >= 0) {
390+ nll = 2;
391+ } else if ((nl = s.indexOf('\n')) >= 0) {
392+ nll = 1;
393+ }
394+ if (nl >= 0) {
395+ // break up newlines
396+ if (nl == 0) {
397+ JPanel breakPanel = new JPanel() {
398+ public Dimension getPreferredSize() {
399+ Font f = getFont();
400+
401+ if (f != null) {
402+ return new Dimension(1, f.getSize() + 2);
403+ }
404+ return new Dimension(0, 0);
405+ }
406+ };
407+ breakPanel.setName("OptionPane.break");
408+ addMessageComponents(container, cons, breakPanel, maxll,
409+ true);
410+ } else {
411+ addMessageComponents(container, cons, s.substring(0, nl),
412+ maxll, false);
413+ }
414+ addMessageComponents(container, cons, s.substring(nl + nll), maxll,
415+ false);
416+
417+ } else if (len > maxll) {
418+ Container c = Box.createVerticalBox();
419+ c.setName("OptionPane.verticalBox");
420+ burstStringInto(c, s, maxll);
421+ addMessageComponents(container, cons, c, maxll, true );
422+
423+ } else {
424+ JLabel label;
425+ label = new JLabel( s, JLabel.LEADING );
426+ label.setName("OptionPane.label");
427+ configureMessageLabel(label);
428+ addMessageComponents(container, cons, label, maxll, true);
429+ }
430+ }
431+ }
432+
433+ /**
434+ * Returns the message to display from the JOptionPane the receiver is
435+ * providing the look and feel for.
436+ */
437+ protected Object getMessage() {
438+ inputComponent = null;
439+ if (optionPane != null) {
440+ if (optionPane.getWantsInput()) {
441+ /* Create a user component to capture the input. If the
442+ selectionValues are non null the component and there
443+ are < 20 values it'll be a combobox, if non null and
444+ >= 20, it'll be a list, otherwise it'll be a textfield. */
445+ Object message = optionPane.getMessage();
446+ Object[] sValues = optionPane.getSelectionValues();
447+ Object inputValue = optionPane
448+ .getInitialSelectionValue();
449+ JComponent toAdd;
450+
451+ if (sValues != null) {
452+ if (sValues.length < 20) {
453+ JComboBox cBox = new JComboBox();
454+
455+ cBox.setName("OptionPane.comboBox");
456+ for(int counter = 0, maxCounter = sValues.length;
457+ counter < maxCounter; counter++) {
458+ cBox.addItem(sValues[counter]);
459+ }
460+ if (inputValue != null) {
461+ cBox.setSelectedItem(inputValue);
462+ }
463+ inputComponent = cBox;
464+ toAdd = cBox;
465+
466+ } else {
467+ JList list = new JList(sValues);
468+ JScrollPane sp = new JScrollPane(list);
469+
470+ sp.setName("OptionPane.scrollPane");
471+ list.setName("OptionPane.list");
472+ list.setVisibleRowCount(10);
473+ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
474+ if(inputValue != null)
475+ list.setSelectedValue(inputValue, true);
476+ list.addMouseListener(getHandler());
477+ toAdd = sp;
478+ inputComponent = list;
479+ }
480+
481+ } else {
482+ MultiplexingTextField tf = new MultiplexingTextField(20);
483+
484+ tf.setName("OptionPane.textField");
485+ tf.setKeyStrokes(new KeyStroke[] {
486+ KeyStroke.getKeyStroke("ENTER") } );
487+ if (inputValue != null) {
488+ String inputString = inputValue.toString();
489+ tf.setText(inputString);
490+ tf.setSelectionStart(0);
491+ tf.setSelectionEnd(inputString.length());
492+ }
493+ tf.addActionListener(getHandler());
494+ toAdd = inputComponent = tf;
495+ }
496+
497+ Object[] newMessage;
498+
499+ if (message == null) {
500+ newMessage = new Object[1];
501+ newMessage[0] = toAdd;
502+
503+ } else {
504+ newMessage = new Object[2];
505+ newMessage[0] = message;
506+ newMessage[1] = toAdd;
507+ }
508+ return newMessage;
509+ }
510+ return optionPane.getMessage();
511+ }
512+ return null;
513+ }
514+
515+ /**
516+ * Creates and adds a JLabel representing the icon returned from
517+ * <code>getIcon</code> to <code>top</code>. This is messaged from
518+ * <code>createMessageArea</code>
519+ */
520+ protected void addIcon(Container top) {
521+ /* Create the icon. */
522+ Icon sideIcon = getIcon();
523+
524+ if (sideIcon != null) {
525+ JLabel iconLabel = new JLabel(sideIcon);
526+
527+ iconLabel.setName("OptionPane.iconLabel");
528+ iconLabel.setVerticalAlignment(SwingConstants.TOP);
529+ top.add(iconLabel, BorderLayout.BEFORE_LINE_BEGINS);
530+ }
531+ }
532+
533+ /**
534+ * Returns the icon from the JOptionPane the receiver is providing
535+ * the look and feel for, or the default icon as returned from
536+ * <code>getDefaultIcon</code>.
537+ */
538+ protected Icon getIcon() {
539+ Icon mIcon = (optionPane == null ? null : optionPane.getIcon());
540+
541+ if(mIcon == null && optionPane != null)
542+ mIcon = getIconForType(optionPane.getMessageType());
543+ return mIcon;
544+ }
545+
546+ /**
547+ * Returns the icon to use for the passed in type.
548+ */
549+ protected Icon getIconForType(int messageType) {
550+ if(messageType < 0 || messageType > 3)
551+ return null;
552+ String propertyName = null;
553+ switch(messageType) {
554+ case 0:
555+ propertyName = "OptionPane.errorIcon";
556+ break;
557+ case 1:
558+ propertyName = "OptionPane.informationIcon";
559+ break;
560+ case 2:
561+ propertyName = "OptionPane.warningIcon";
562+ break;
563+ case 3:
564+ propertyName = "OptionPane.questionIcon";
565+ break;
566+ }
567+ if (propertyName != null) {
568+ return (Icon)DefaultLookup.get(optionPane, this, propertyName);
569+ }
570+ return null;
571+ }
572+
573+ /**
574+ * Returns the maximum number of characters to place on a line.
575+ */
576+ protected int getMaxCharactersPerLineCount() {
577+ return optionPane.getMaxCharactersPerLineCount();
578+ }
579+
580+ /**
581+ * Recursively creates new JLabel instances to represent <code>d</code>.
582+ * Each JLabel instance is added to <code>c</code>.
583+ */
584+ protected void burstStringInto(Container c, String d, int maxll) {
585+ // Primitive line wrapping
586+ int len = d.length();
587+ if (len <= 0)
588+ return;
589+ if (len > maxll) {
590+ int p = d.lastIndexOf(' ', maxll);
591+ if (p <= 0)
592+ p = d.indexOf(' ', maxll);
593+ if (p > 0 && p < len) {
594+ burstStringInto(c, d.substring(0, p), maxll);
595+ burstStringInto(c, d.substring(p + 1), maxll);
596+ return;
597+ }
598+ }
599+ JLabel label = new JLabel(d, JLabel.LEFT);
600+ label.setName("OptionPane.label");
601+ configureMessageLabel(label);
602+ c.add(label);
603+ }
604+
605+ protected Container createSeparator() {
606+ return null;
607+ }
608+
609+ /**
610+ * Creates and returns a Container containing the buttons. The buttons
611+ * are created by calling <code>getButtons</code>.
612+ */
613+ protected Container createButtonArea() {
614+ JPanel bottom = new JPanel();
615+ Border border = (Border)DefaultLookup.get(optionPane, this,
616+ "OptionPane.buttonAreaBorder");
617+ bottom.setName("OptionPane.buttonArea");
618+ if (border != null) {
619+ bottom.setBorder(border);
620+ }
621+ bottom.setLayout(new ButtonAreaLayout(
622+ DefaultLookup.getBoolean(optionPane, this,
623+ "OptionPane.sameSizeButtons", true),
624+ DefaultLookup.getInt(optionPane, this, "OptionPane.buttonPadding",
625+ 6),
626+ DefaultLookup.getInt(optionPane, this,
627+ "OptionPane.buttonOrientation", SwingConstants.CENTER),
628+ DefaultLookup.getBoolean(optionPane, this, "OptionPane.isYesLast",
629+ false)));
630+ addButtonComponents(bottom, getButtons(), getInitialValueIndex());
631+ return bottom;
632+ }
633+
634+ /**
635+ * Creates the appropriate object to represent each of the objects in
636+ * <code>buttons</code> and adds it to <code>container</code>. This
637+ * differs from addMessageComponents in that it will recurse on
638+ * <code>buttons</code> and that if button is not a Component
639+ * it will create an instance of JButton.
640+ */
641+ protected void addButtonComponents(Container container, Object[] buttons,
642+ int initialIndex) {
643+ if (buttons != null && buttons.length > 0) {
644+ boolean sizeButtonsToSame = getSizeButtonsToSameWidth();
645+ boolean createdAll = true;
646+ int numButtons = buttons.length;
647+ JButton[] createdButtons = null;
648+ int maxWidth = 0;
649+
650+ if (sizeButtonsToSame) {
651+ createdButtons = new JButton[numButtons];
652+ }
653+
654+ for(int counter = 0; counter < numButtons; counter++) {
655+ Object button = buttons[counter];
656+ Component newComponent;
657+
658+ if (button instanceof Component) {
659+ createdAll = false;
660+ newComponent = (Component)button;
661+ container.add(newComponent);
662+ hasCustomComponents = true;
663+
664+ } else {
665+ JButton aButton;
666+
667+ if (button instanceof ButtonFactory) {
668+ aButton = ((ButtonFactory)button).createButton();
669+ }
670+ else if (button instanceof Icon)
671+ aButton = new JButton((Icon)button);
672+ else
673+ aButton = new JButton(button.toString());
674+
675+ aButton.setName("OptionPane.button");
676+ aButton.setMultiClickThreshhold(DefaultLookup.getInt(
677+ optionPane, this, "OptionPane.buttonClickThreshhold",
678+ 0));
679+ configureButton(aButton);
680+
681+ container.add(aButton);
682+
683+ ActionListener buttonListener = createButtonActionListener(counter);
684+ if (buttonListener != null) {
685+ aButton.addActionListener(buttonListener);
686+ }
687+ newComponent = aButton;
688+ }
689+ if (sizeButtonsToSame && createdAll &&
690+ (newComponent instanceof JButton)) {
691+ createdButtons[counter] = (JButton)newComponent;
692+ maxWidth = Math.max(maxWidth,
693+ newComponent.getMinimumSize().width);
694+ }
695+ if (counter == initialIndex) {
696+ initialFocusComponent = newComponent;
697+ if (initialFocusComponent instanceof JButton) {
698+ JButton defaultB = (JButton)initialFocusComponent;
699+ defaultB.addHierarchyListener(new HierarchyListener() {
700+ public void hierarchyChanged(HierarchyEvent e) {
701+ if ((e.getChangeFlags() &
702+ HierarchyEvent.PARENT_CHANGED) != 0) {
703+ JButton defaultButton = (JButton) e.getComponent();
704+ JRootPane root =
705+ SwingUtilities.getRootPane(defaultButton);
706+ if (root != null) {
707+ root.setDefaultButton(defaultButton);
708+ }
709+ }
710+ }
711+ });
712+ }
713+ }
714+ }
715+ ((ButtonAreaLayout)container.getLayout()).
716+ setSyncAllWidths((sizeButtonsToSame && createdAll));
717+ /* Set the padding, windows seems to use 8 if <= 2 components,
718+ otherwise 4 is used. It may actually just be the size of the
719+ buttons is always the same, not sure. */
720+ if (DefaultLookup.getBoolean(optionPane, this,
721+ "OptionPane.setButtonMargin", true) && sizeButtonsToSame &&
722+ createdAll) {
723+ JButton aButton;
724+ int padSize;
725+
726+ padSize = (numButtons <= 2? 8 : 4);
727+
728+ for(int counter = 0; counter < numButtons; counter++) {
729+ aButton = createdButtons[counter];
730+ aButton.setMargin(new Insets(2, padSize, 2, padSize));
731+ }
732+ }
733+ }
734+ }
735+
736+ protected ActionListener createButtonActionListener(int buttonIndex) {
737+ return new ButtonActionListener(buttonIndex);
738+ }
739+
740+ /**
741+ * Returns the buttons to display from the JOptionPane the receiver is
742+ * providing the look and feel for. If the JOptionPane has options
743+ * set, they will be provided, otherwise if the optionType is
744+ * YES_NO_OPTION, yesNoOptions is returned, if the type is
745+ * YES_NO_CANCEL_OPTION yesNoCancelOptions is returned, otherwise
746+ * defaultButtons are returned.
747+ */
748+ protected Object[] getButtons() {
749+ if (optionPane != null) {
750+ Object[] suppliedOptions = optionPane.getOptions();
751+
752+ if (suppliedOptions == null) {
753+ Object[] defaultOptions;
754+ int type = optionPane.getOptionType();
755+ Locale l = optionPane.getLocale();
756+ int minimumWidth =
757+ DefaultLookup.getInt(optionPane, this,
758+ "OptionPane.buttonMinimumWidth",-1);
759+ if (type == JOptionPane.YES_NO_OPTION) {
760+ defaultOptions = new ButtonFactory[2];
761+ defaultOptions[0] = new ButtonFactory(
762+ UIManager.getString("OptionPane.yesButtonText", l),
763+ getMnemonic("OptionPane.yesButtonMnemonic", l),
764+ (Icon)DefaultLookup.get(optionPane, this,
765+ "OptionPane.yesIcon"), minimumWidth);
766+ defaultOptions[1] = new ButtonFactory(
767+ UIManager.getString("OptionPane.noButtonText", l),
768+ getMnemonic("OptionPane.noButtonMnemonic", l),
769+ (Icon)DefaultLookup.get(optionPane, this,
770+ "OptionPane.noIcon"), minimumWidth);
771+ } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) {
772+ defaultOptions = new ButtonFactory[3];
773+ defaultOptions[0] = new ButtonFactory(
774+ UIManager.getString("OptionPane.yesButtonText", l),
775+ getMnemonic("OptionPane.yesButtonMnemonic", l),
776+ (Icon)DefaultLookup.get(optionPane, this,
777+ "OptionPane.yesIcon"), minimumWidth);
778+ defaultOptions[1] = new ButtonFactory(
779+ UIManager.getString("OptionPane.noButtonText",l),
780+ getMnemonic("OptionPane.noButtonMnemonic", l),
781+ (Icon)DefaultLookup.get(optionPane, this,
782+ "OptionPane.noIcon"), minimumWidth);
783+ defaultOptions[2] = new ButtonFactory(
784+ UIManager.getString("OptionPane.cancelButtonText",l),
785+ getMnemonic("OptionPane.cancelButtonMnemonic", l),
786+ (Icon)DefaultLookup.get(optionPane, this,
787+ "OptionPane.cancelIcon"), minimumWidth);
788+ } else if (type == JOptionPane.OK_CANCEL_OPTION) {
789+ defaultOptions = new ButtonFactory[2];
790+ defaultOptions[0] = new ButtonFactory(
791+ UIManager.getString("OptionPane.okButtonText",l),
792+ getMnemonic("OptionPane.okButtonMnemonic", l),
793+ (Icon)DefaultLookup.get(optionPane, this,
794+ "OptionPane.okIcon"), minimumWidth);
795+ defaultOptions[1] = new ButtonFactory(
796+ UIManager.getString("OptionPane.cancelButtonText",l),
797+ getMnemonic("OptionPane.cancelButtonMnemonic", l),
798+ (Icon)DefaultLookup.get(optionPane, this,
799+ "OptionPane.cancelIcon"), minimumWidth);
800+ } else {
801+ defaultOptions = new ButtonFactory[1];
802+ defaultOptions[0] = new ButtonFactory(
803+ UIManager.getString("OptionPane.okButtonText",l),
804+ getMnemonic("OptionPane.okButtonMnemonic", l),
805+ (Icon)DefaultLookup.get(optionPane, this,
806+ "OptionPane.okIcon"), minimumWidth);
807+ }
808+ return defaultOptions;
809+
810+ }
811+ return suppliedOptions;
812+ }
813+ return null;
814+ }
815+
816+ private int getMnemonic(String key, Locale l) {
817+ String value = (String)UIManager.get(key, l);
818+
819+ if (value == null) {
820+ return 0;
821+ }
822+ try {
823+ return Integer.parseInt(value);
824+ }
825+ catch (NumberFormatException nfe) { }
826+ return 0;
827+ }
828+
829+ /**
830+ * Returns true, basic L&F wants all the buttons to have the same
831+ * width.
832+ */
833+ protected boolean getSizeButtonsToSameWidth() {
834+ return true;
835+ }
836+
837+ /**
838+ * Returns the initial index into the buttons to select. The index
839+ * is calculated from the initial value from the JOptionPane and
840+ * options of the JOptionPane or 0.
841+ */
842+ protected int getInitialValueIndex() {
843+ if (optionPane != null) {
844+ Object iv = optionPane.getInitialValue();
845+ Object[] options = optionPane.getOptions();
846+
847+ if(options == null) {
848+ return 0;
849+ }
850+ else if(iv != null) {
851+ for(int counter = options.length - 1; counter >= 0; counter--){
852+ if(options[counter].equals(iv))
853+ return counter;
854+ }
855+ }
856+ }
857+ return -1;
858+ }
859+
860+ /**
861+ * Sets the input value in the option pane the receiver is providing
862+ * the look and feel for based on the value in the inputComponent.
863+ */
864+ protected void resetInputValue() {
865+ if(inputComponent != null && (inputComponent instanceof JTextField)) {
866+ optionPane.setInputValue(((JTextField)inputComponent).getText());
867+
868+ } else if(inputComponent != null &&
869+ (inputComponent instanceof JComboBox)) {
870+ optionPane.setInputValue(((JComboBox)inputComponent)
871+ .getSelectedItem());
872+ } else if(inputComponent != null) {
873+ optionPane.setInputValue(((JList)inputComponent)
874+ .getSelectedValue());
875+ }
876+ }
877+
878+
879+ /**
880+ * If inputComponent is non-null, the focus is requested on that,
881+ * otherwise request focus on the default value
882+ */
883+ public void selectInitialValue(JOptionPane op) {
884+ if (inputComponent != null)
885+ inputComponent.requestFocus();
886+ else {
887+ if (initialFocusComponent != null)
888+ initialFocusComponent.requestFocus();
889+
890+ if (initialFocusComponent instanceof JButton) {
891+ JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
892+ if (root != null) {
893+ root.setDefaultButton((JButton)initialFocusComponent);
894+ }
895+ }
896+ }
897+ }
898+
899+ /**
900+ * Returns true if in the last call to validateComponent the message
901+ * or buttons contained a subclass of Component.
902+ */
903+ public boolean containsCustomComponents(JOptionPane op) {
904+ return hasCustomComponents;
905+ }
906+
907+
908+ /**
909+ * <code>ButtonAreaLayout</code> behaves in a similar manner to
910+ * <code>FlowLayout</code>. It lays out all components from left to
911+ * right. If <code>syncAllWidths</code> is true, the widths of each
912+ * component will be set to the largest preferred size width.
913+ *
914+ * This class should be treated as a &quot;protected&quot; inner class.
915+ * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
916+ */
917+ public static class ButtonAreaLayout implements LayoutManager {
918+ protected boolean syncAllWidths;
919+ protected int padding;
920+ /** If true, children are lumped together in parent. */
921+ protected boolean centersChildren;
922+ private int orientation;
923+ private boolean reverseButtons;
924+ /**
925+ * Indicates whether or not centersChildren should be used vs
926+ * the orientation. This is done for backward compatability
927+ * for subclassers.
928+ */
929+ private boolean useOrientation;
930+
931+ public ButtonAreaLayout(boolean syncAllWidths, int padding) {
932+ this.syncAllWidths = syncAllWidths;
933+ this.padding = padding;
934+ centersChildren = true;
935+ useOrientation = false;
936+ }
937+
938+ ButtonAreaLayout(boolean syncAllSizes, int padding, int orientation,
939+ boolean reverseButtons) {
940+ this(syncAllSizes, padding);
941+ useOrientation = true;
942+ this.orientation = orientation;
943+ this.reverseButtons = reverseButtons;
944+ }
945+
946+ public void setSyncAllWidths(boolean newValue) {
947+ syncAllWidths = newValue;
948+ }
949+
950+ public boolean getSyncAllWidths() {
951+ return syncAllWidths;
952+ }
953+
954+ public void setPadding(int newPadding) {
955+ this.padding = newPadding;
956+ }
957+
958+ public int getPadding() {
959+ return padding;
960+ }
961+
962+ public void setCentersChildren(boolean newValue) {
963+ centersChildren = newValue;
964+ useOrientation = false;
965+ }
966+
967+ public boolean getCentersChildren() {
968+ return centersChildren;
969+ }
970+
971+ private int getOrientation(Container container) {
972+ if (!useOrientation) {
973+ return SwingConstants.CENTER;
974+ }
975+ if (container.getComponentOrientation().isLeftToRight()) {
976+ return orientation;
977+ }
978+ switch (orientation) {
979+ case SwingConstants.LEFT:
980+ return SwingConstants.RIGHT;
981+ case SwingConstants.RIGHT:
982+ return SwingConstants.LEFT;
983+ case SwingConstants.CENTER:
984+ return SwingConstants.CENTER;
985+ }
986+ return SwingConstants.LEFT;
987+ }
988+
989+ public void addLayoutComponent(String string, Component comp) {
990+ }
991+
992+ public void layoutContainer(Container container) {
993+ Component[] children = container.getComponents();
994+
995+ if(children != null && children.length > 0) {
996+ int numChildren = children.length;
997+ Insets insets = container.getInsets();
998+ int maxWidth = 0;
999+ int maxHeight = 0;
1000+ int totalButtonWidth = 0;
1001+ int x = 0;
1002+ int xOffset = 0;
1003+ boolean ltr = container.getComponentOrientation().
1004+ isLeftToRight();
1005+ boolean reverse = (ltr) ? reverseButtons : !reverseButtons;
1006+
1007+ for(int counter = 0; counter < numChildren; counter++) {
1008+ Dimension pref = children[counter].getPreferredSize();
1009+ maxWidth = Math.max(maxWidth, pref.width);
1010+ maxHeight = Math.max(maxHeight, pref.height);
1011+ totalButtonWidth += pref.width;
1012+ }
1013+ if (getSyncAllWidths()) {
1014+ totalButtonWidth = maxWidth * numChildren;
1015+ }
1016+ totalButtonWidth += (numChildren - 1) * padding;
1017+
1018+ switch (getOrientation(container)) {
1019+ case SwingConstants.LEFT:
1020+ x = insets.left;
1021+ break;
1022+ case SwingConstants.RIGHT:
1023+ x = container.getWidth() - insets.right - totalButtonWidth;
1024+ break;
1025+ case SwingConstants.CENTER:
1026+ if (getCentersChildren() || numChildren < 2) {
1027+ x = (container.getWidth() - totalButtonWidth) / 2;
1028+ }
1029+ else {
1030+ x = insets.left;
1031+ if (getSyncAllWidths()) {
1032+ xOffset = (container.getWidth() - insets.left -
1033+ insets.right - totalButtonWidth) /
1034+ (numChildren - 1) + maxWidth;
1035+ }
1036+ else {
1037+ xOffset = (container.getWidth() - insets.left -
1038+ insets.right - totalButtonWidth) /
1039+ (numChildren - 1);
1040+ }
1041+ }
1042+ break;
1043+ }
1044+
1045+ for (int counter = 0; counter < numChildren; counter++) {
1046+ int index = (reverse) ? numChildren - counter - 1 :
1047+ counter;
1048+ Dimension pref = children[index].getPreferredSize();
1049+
1050+ if (getSyncAllWidths()) {
1051+ children[index].setBounds(x, insets.top,
1052+ maxWidth, maxHeight);
1053+ }
1054+ else {
1055+ children[index].setBounds(x, insets.top, pref.width,
1056+ pref.height);
1057+ }
1058+ if (xOffset != 0) {
1059+ x += xOffset;
1060+ }
1061+ else {
1062+ x += children[index].getWidth() + padding;
1063+ }
1064+ }
1065+ }
1066+ }
1067+
1068+ public Dimension minimumLayoutSize(Container c) {
1069+ if(c != null) {
1070+ Component[] children = c.getComponents();
1071+
1072+ if(children != null && children.length > 0) {
1073+ Dimension aSize;
1074+ int numChildren = children.length;
1075+ int height = 0;
1076+ Insets cInsets = c.getInsets();
1077+ int extraHeight = cInsets.top + cInsets.bottom;
1078+ int extraWidth = cInsets.left + cInsets.right;
1079+
1080+ if (syncAllWidths) {
1081+ int maxWidth = 0;
1082+
1083+ for(int counter = 0; counter < numChildren; counter++){
1084+ aSize = children[counter].getPreferredSize();
1085+ height = Math.max(height, aSize.height);
1086+ maxWidth = Math.max(maxWidth, aSize.width);
1087+ }
1088+ return new Dimension(extraWidth + (maxWidth * numChildren) +
1089+ (numChildren - 1) * padding,
1090+ extraHeight + height);
1091+ }
1092+ else {
1093+ int totalWidth = 0;
1094+
1095+ for(int counter = 0; counter < numChildren; counter++){
1096+ aSize = children[counter].getPreferredSize();
1097+ height = Math.max(height, aSize.height);
1098+ totalWidth += aSize.width;
1099+ }
1100+ totalWidth += ((numChildren - 1) * padding);
1101+ return new Dimension(extraWidth + totalWidth, extraHeight + height);
1102+ }
1103+ }
1104+ }
1105+ return new Dimension(0, 0);
1106+ }
1107+
1108+ public Dimension preferredLayoutSize(Container c) {
1109+ return minimumLayoutSize(c);
1110+ }
1111+
1112+ public void removeLayoutComponent(Component c) { }
1113+ }
1114+
1115+
1116+ /**
1117+ * This class should be treated as a &quot;protected&quot; inner class.
1118+ * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1119+ */
1120+ public class PropertyChangeHandler implements PropertyChangeListener {
1121+ /**
1122+ * If the source of the PropertyChangeEvent <code>e</code> equals the
1123+ * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
1124+ * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
1125+ * validateComponent is invoked.
1126+ */
1127+ public void propertyChange(PropertyChangeEvent e) {
1128+ getHandler().propertyChange(e);
1129+ }
1130+ }
1131+
1132+ /**
1133+ * Configures any necessary colors/fonts for the specified label
1134+ * used representing the message.
1135+ */
1136+ private void configureMessageLabel(JLabel label) {
1137+ Color color = (Color)DefaultLookup.get(optionPane, this,
1138+ "OptionPane.messageForeground");
1139+ if (color != null) {
1140+ label.setForeground(color);
1141+ }
1142+ Font messageFont = (Font)DefaultLookup.get(optionPane, this,
1143+ "OptionPane.messageFont");
1144+ if (messageFont != null) {
1145+ label.setFont(messageFont);
1146+ }
1147+ }
1148+
1149+ /**
1150+ * Configures any necessary colors/fonts for the specified button
1151+ * used representing the button portion of the optionpane.
1152+ */
1153+ private void configureButton(JButton button) {
1154+ Font buttonFont = (Font)DefaultLookup.get(optionPane, this,
1155+ "OptionPane.buttonFont");
1156+ if (buttonFont != null) {
1157+ button.setFont(buttonFont);
1158+ }
1159+ }
1160+
1161+ /**
1162+ * This class should be treated as a &quot;protected&quot; inner class.
1163+ * Instantiate it only within subclasses of {@code BasicOptionPaneUI}.
1164+ */
1165+ public class ButtonActionListener implements ActionListener {
1166+ protected int buttonIndex;
1167+
1168+ public ButtonActionListener(int buttonIndex) {
1169+ this.buttonIndex = buttonIndex;
1170+ }
1171+
1172+ public void actionPerformed(ActionEvent e) {
1173+ if (optionPane != null) {
1174+ int optionType = optionPane.getOptionType();
1175+ Object[] options = optionPane.getOptions();
1176+
1177+ /* If the option pane takes input, then store the input value
1178+ * if custom options were specified, if the option type is
1179+ * DEFAULT_OPTION, OR if option type is set to a predefined
1180+ * one and the user chose the affirmative answer.
1181+ */
1182+ if (inputComponent != null) {
1183+ if (options != null ||
1184+ optionType == JOptionPane.DEFAULT_OPTION ||
1185+ ((optionType == JOptionPane.YES_NO_OPTION ||
1186+ optionType == JOptionPane.YES_NO_CANCEL_OPTION ||
1187+ optionType == JOptionPane.OK_CANCEL_OPTION) &&
1188+ buttonIndex == 0)) {
1189+ resetInputValue();
1190+ }
1191+ }
1192+ if (options == null) {
1193+ if (optionType == JOptionPane.OK_CANCEL_OPTION &&
1194+ buttonIndex == 1) {
1195+ optionPane.setValue(Integer.valueOf(2));
1196+
1197+ } else {
1198+ optionPane.setValue(Integer.valueOf(buttonIndex));
1199+ }
1200+ } else {
1201+ optionPane.setValue(options[buttonIndex]);
1202+ }
1203+ }
1204+ }
1205+ }
1206+
1207+
1208+ private class Handler implements ActionListener, MouseListener,
1209+ PropertyChangeListener {
1210+ //
1211+ // ActionListener
1212+ //
1213+ public void actionPerformed(ActionEvent e) {
1214+ optionPane.setInputValue(((JTextField)e.getSource()).getText());
1215+ }
1216+
1217+
1218+ //
1219+ // MouseListener
1220+ //
1221+ public void mouseClicked(MouseEvent e) {
1222+ }
1223+
1224+ public void mouseReleased(MouseEvent e) {
1225+ }
1226+
1227+ public void mouseEntered(MouseEvent e) {
1228+ }
1229+
1230+ public void mouseExited(MouseEvent e) {
1231+ }
1232+
1233+ public void mousePressed(MouseEvent e) {
1234+ if (e.getClickCount() == 2) {
1235+ JList list = (JList)e.getSource();
1236+ int index = list.locationToIndex(e.getPoint());
1237+
1238+ optionPane.setInputValue(list.getModel().getElementAt(index));
1239+ }
1240+ }
1241+
1242+ //
1243+ // PropertyChangeListener
1244+ //
1245+ public void propertyChange(PropertyChangeEvent e) {
1246+ if(e.getSource() == optionPane) {
1247+ // Option Pane Auditory Cue Activation
1248+ // only respond to "ancestor" changes
1249+ // the idea being that a JOptionPane gets a JDialog when it is
1250+ // set to appear and loses it's JDialog when it is dismissed.
1251+ if ("ancestor" == e.getPropertyName()) {
1252+ JOptionPane op = (JOptionPane)e.getSource();
1253+ boolean isComingUp;
1254+
1255+ // if the old value is null, then the JOptionPane is being
1256+ // created since it didn't previously have an ancestor.
1257+ if (e.getOldValue() == null) {
1258+ isComingUp = true;
1259+ } else {
1260+ isComingUp = false;
1261+ }
1262+
1263+ // figure out what to do based on the message type
1264+ switch (op.getMessageType()) {
1265+ case JOptionPane.PLAIN_MESSAGE:
1266+ if (isComingUp) {
1267+ BasicLookAndFeel.playSound(optionPane,
1268+ "OptionPane.informationSound");
1269+ }
1270+ break;
1271+ case JOptionPane.QUESTION_MESSAGE:
1272+ if (isComingUp) {
1273+ BasicLookAndFeel.playSound(optionPane,
1274+ "OptionPane.questionSound");
1275+ }
1276+ break;
1277+ case JOptionPane.INFORMATION_MESSAGE:
1278+ if (isComingUp) {
1279+ BasicLookAndFeel.playSound(optionPane,
1280+ "OptionPane.informationSound");
1281+ }
1282+ break;
1283+ case JOptionPane.WARNING_MESSAGE:
1284+ if (isComingUp) {
1285+ BasicLookAndFeel.playSound(optionPane,
1286+ "OptionPane.warningSound");
1287+ }
1288+ break;
1289+ case JOptionPane.ERROR_MESSAGE:
1290+ if (isComingUp) {
1291+ BasicLookAndFeel.playSound(optionPane,
1292+ "OptionPane.errorSound");
1293+ }
1294+ break;
1295+ default:
1296+ System.err.println("Undefined JOptionPane type: " +
1297+ op.getMessageType());
1298+ break;
1299+ }
1300+ }
1301+ // Visual activity
1302+ String changeName = e.getPropertyName();
1303+
1304+ if(changeName == JOptionPane.OPTIONS_PROPERTY ||
1305+ changeName == JOptionPane.INITIAL_VALUE_PROPERTY ||
1306+ changeName == JOptionPane.ICON_PROPERTY ||
1307+ changeName == JOptionPane.MESSAGE_TYPE_PROPERTY ||
1308+ changeName == JOptionPane.OPTION_TYPE_PROPERTY ||
1309+ changeName == JOptionPane.MESSAGE_PROPERTY ||
1310+ changeName == JOptionPane.SELECTION_VALUES_PROPERTY ||
1311+ changeName == JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY ||
1312+ changeName == JOptionPane.WANTS_INPUT_PROPERTY) {
1313+ uninstallComponents();
1314+ installComponents();
1315+ optionPane.validate();
1316+ }
1317+ else if (changeName == "componentOrientation") {
1318+ ComponentOrientation o = (ComponentOrientation)e.getNewValue();
1319+ JOptionPane op = (JOptionPane)e.getSource();
1320+ if (o != e.getOldValue()) {
1321+ op.applyComponentOrientation(o);
1322+ }
1323+ }
1324+ }
1325+ }
1326+ }
1327+
1328+
1329+ //
1330+ // Classes used when optionPane.getWantsInput returns true.
1331+ //
1332+
1333+ /**
1334+ * A JTextField that allows you to specify an array of KeyStrokes that
1335+ * that will have their bindings processed regardless of whether or
1336+ * not they are registered on the JTextField. This is used as we really
1337+ * want the ActionListener to be notified so that we can push the
1338+ * change to the JOptionPane, but we also want additional bindings
1339+ * (those of the JRootPane) to be processed as well.
1340+ */
1341+ private static class MultiplexingTextField extends JTextField {
1342+ private KeyStroke[] strokes;
1343+
1344+ MultiplexingTextField(int cols) {
1345+ super(cols);
1346+ }
1347+
1348+ /**
1349+ * Sets the KeyStrokes that will be additional processed for
1350+ * ancestor bindings.
1351+ */
1352+ void setKeyStrokes(KeyStroke[] strokes) {
1353+ this.strokes = strokes;
1354+ }
1355+
1356+ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
1357+ int condition, boolean pressed) {
1358+ boolean processed = super.processKeyBinding(ks, e, condition,
1359+ pressed);
1360+
1361+ if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
1362+ for (int counter = strokes.length - 1; counter >= 0;
1363+ counter--) {
1364+ if (strokes[counter].equals(ks)) {
1365+ // Returning false will allow further processing
1366+ // of the bindings, eg our parent Containers will get a
1367+ // crack at them.
1368+ return false;
1369+ }
1370+ }
1371+ }
1372+ return processed;
1373+ }
1374+ }
1375+
1376+
1377+
1378+ /**
1379+ * Registered in the ActionMap. Sets the value of the option pane
1380+ * to <code>JOptionPane.CLOSED_OPTION</code>.
1381+ */
1382+ private static class Actions extends UIAction {
1383+ private static final String CLOSE = "close";
1384+
1385+ Actions(String key) {
1386+ super(key);
1387+ }
1388+
1389+ public void actionPerformed(ActionEvent e) {
1390+ if (getName() == CLOSE) {
1391+ JOptionPane optionPane = (JOptionPane)e.getSource();
1392+
1393+ optionPane.setValue(Integer.valueOf(JOptionPane.CLOSED_OPTION));
1394+ }
1395+ }
1396+ }
1397+
1398+
1399+ /**
1400+ * This class is used to create the default buttons. This indirection is
1401+ * used so that addButtonComponents can tell which Buttons were created
1402+ * by us vs subclassers or from the JOptionPane itself.
1403+ */
1404+ private static class ButtonFactory {
1405+ private String text;
1406+ private int mnemonic;
1407+ private Icon icon;
1408+ private int minimumWidth = -1;
1409+
1410+ ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) {
1411+ this.text = text;
1412+ this.mnemonic = mnemonic;
1413+ this.icon = icon;
1414+ this.minimumWidth = minimumWidth;
1415+ }
1416+
1417+ JButton createButton() {
1418+ JButton button;
1419+
1420+ if (minimumWidth > 0) {
1421+ button = new ConstrainedButton(text, minimumWidth);
1422+ } else {
1423+ button = new JButton(text);
1424+ }
1425+ if (icon != null) {
1426+ button.setIcon(icon);
1427+ }
1428+ if (mnemonic != 0) {
1429+ button.setMnemonic(mnemonic);
1430+ }
1431+ return button;
1432+ }
1433+
1434+ private static class ConstrainedButton extends JButton {
1435+ int minimumWidth;
1436+
1437+ ConstrainedButton(String text, int minimumWidth) {
1438+ super(text);
1439+ this.minimumWidth = minimumWidth;
1440+ }
1441+
1442+ public Dimension getMinimumSize() {
1443+ Dimension min = super.getMinimumSize();
1444+ min.width = Math.max(min.width, minimumWidth);
1445+ return min;
1446+ }
1447+
1448+ public Dimension getPreferredSize() {
1449+ Dimension pref = super.getPreferredSize();
1450+ pref.width = Math.max(pref.width, minimumWidth);
1451+ return pref;
1452+ }
1453+ }
1454+ }
1455+}