Mega Code Archive

 
Categories / Java / Swing Components
 

Use this modal dialog to let the user choose one string from a long list

/*  * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *  *   - Redistributions of source code must retain the above copyright  *     notice, this list of conditions and the following disclaimer.  *  *   - Redistributions in binary form must reproduce the above copyright  *     notice, this list of conditions and the following disclaimer in the  *     documentation and/or other materials provided with the distribution.  *  *   - Neither the name of Sun Microsystems nor the names of its  *     contributors may be used to endorse or promote products derived  *     from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */ import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; /**  * A 1.4 application that brings up a ListDialog.  */ public class ListDialogRunner {   static JFrame frame;   static String[] names = { "Arlo", "Cosmo", "Elmo", "Hugo", "Jethro",       "Laszlo", "Milo", "Nemo", "Otto", "Ringo", "Rocco", "Rollo" };   public static JPanel createUI() {     // Create the labels.     JLabel intro = new JLabel("The chosen name:");     final JLabel name = new JLabel(names[1]);     intro.setLabelFor(name);     // Use a wacky font if it exists. If not, this falls     // back to a font we know exists.     name.setFont(getAFont());     // Create the button.     final JButton button = new JButton("Pick a new name...");     button.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         String selectedName = ListDialog.showDialog(frame, button,             "Baby names ending in O:", "Name Chooser", names, name.getText(),             "Cosmo  ");         name.setText(selectedName);       }     });     // Create the panel we'll return and set up the layout.     JPanel panel = new JPanel();     panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));     panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));     intro.setAlignmentX(JComponent.CENTER_ALIGNMENT);     name.setAlignmentX(JComponent.CENTER_ALIGNMENT);     button.setAlignmentX(JComponent.CENTER_ALIGNMENT);     // Add the labels to the content pane.     panel.add(intro);     panel.add(Box.createVerticalStrut(5)); // extra space     panel.add(name);     // Add a vertical spacer that also guarantees us a minimum width:     panel.add(Box.createRigidArea(new Dimension(150, 10)));     // Add the button.     panel.add(button);     return panel;   }   /**    * Finds a cursive font to use, or falls back to using an italic serif font.    */   protected static Font getAFont() {     // initial strings of desired fonts     String[] desiredFonts = { "French Script", "FrenchScript", "Script" };     String[] existingFamilyNames = null; // installed fonts     String fontName = null; // font we'll use     // Search for all installed font families. The first     // call may take a while on some systems with hundreds of     // installed fonts, so if possible execute it in idle time,     // and certainly not in a place that delays painting of     // the UI (for example, when bringing up a menu).     //     // In systems with malformed fonts, this code might cause     // serious problems; use the latest JRE in this case. (You'll     // see the same problems if you use Swing's HTML support or     // anything else that searches for all fonts.) If this call     // causes problems for you under the latest JRE, please let     // us know:     // http://java.sun.com/docs/books/tutorial/forms/sendusmail.html     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();     if (ge != null) {       existingFamilyNames = ge.getAvailableFontFamilyNames();     }     // See if there's one we like.     if ((existingFamilyNames != null) && (desiredFonts != null)) {       int i = 0;       while ((fontName == null) && (i < desiredFonts.length)) {         // Look for a font whose name starts with desiredFonts[i].         int j = 0;         while ((fontName == null) && (j < existingFamilyNames.length)) {           if (existingFamilyNames[j].startsWith(desiredFonts[i])) {             // We've found a match. Test whether it can display             // the Latin character 'A'. (You might test for             // a different character if you're using a different             // language.)             Font f = new Font(existingFamilyNames[j], Font.PLAIN, 1);             if (f.canDisplay('A')) {               fontName = existingFamilyNames[j];               System.out.println("Using font: " + fontName);             }           }           j++; // Look at next existing font name.         }         i++; // Look for next desired font.       }     }     // Return a valid Font.     if (fontName != null) {       return new Font(fontName, Font.PLAIN, 36);     } else {       return new Font("Serif", Font.ITALIC, 36);     }   }   /**    * Create the GUI and show it. For thread safety, this method should be    * invoked from the event-dispatching thread.    */   private static void createAndShowGUI() {     // Create and set up the window.     frame = new JFrame("Name That Baby");     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     // Create and set up the content pane.     JComponent newContentPane = createUI();     newContentPane.setOpaque(true); // content panes must be opaque     frame.setContentPane(newContentPane);     // Display the window.     frame.pack();     frame.setVisible(true);   }   public static void main(String[] args) {     // Schedule a job for the event-dispatching thread:     // creating and showing this application's GUI.     javax.swing.SwingUtilities.invokeLater(new Runnable() {       public void run() {         createAndShowGUI();       }     });   } } /*  * Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.  *   * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met:  *  - Redistributions of source code must retain the above copyright notice,  * this list of conditions and the following disclaimer.  *  - Redistributions in binary form must reproduce the above copyright notice,  * this list of conditions and the following disclaimer in the documentation  * and/or other materials provided with the distribution.  *  - Neither the name of Sun Microsystems nor the names of its contributors may  * be used to endorse or promote products derived from this software without  * specific prior written permission.  *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  * POSSIBILITY OF SUCH DAMAGE.  */ /*  * ListDialog.java is meant to be used by programs such as ListDialogRunner. It  * requires no additional files.  */ /**  * Use this modal dialog to let the user choose one string from a long list. See  * ListDialogRunner.java for an example of using ListDialog. The basics:  *   * <pre>  * String[] choices = { &quot;A&quot;, &quot;long&quot;, &quot;array&quot;, &quot;of&quot;, &quot;strings&quot; };  * String selectedName = ListDialog.showDialog(componentInControllingFrame,  *     locatorComponent, &quot;A description of the list:&quot;, &quot;Dialog Title&quot;, choices,  *     choices[0]);  * </pre>  */ class ListDialog extends JDialog implements ActionListener {   private static ListDialog dialog;   private static String value = "";   private JList list;   /**    * Set up and show the dialog. The first Component argument determines which    * frame the dialog depends on; it should be a component in the dialog's    * controlling frame. The second Component argument should be null if you want    * the dialog to come up with its left corner in the center of the screen;    * otherwise, it should be the component on top of which the dialog should    * appear.    */   public static String showDialog(Component frameComp, Component locationComp,       String labelText, String title, String[] possibleValues,       String initialValue, String longValue) {     Frame frame = JOptionPane.getFrameForComponent(frameComp);     dialog = new ListDialog(frame, locationComp, labelText, title,         possibleValues, initialValue, longValue);     dialog.setVisible(true);     return value;   }   private void setValue(String newValue) {     value = newValue;     list.setSelectedValue(value, true);   }   private ListDialog(Frame frame, Component locationComp, String labelText,       String title, Object[] data, String initialValue, String longValue) {     super(frame, title, true);     // Create and initialize the buttons.     JButton cancelButton = new JButton("Cancel");     cancelButton.addActionListener(this);     //     final JButton setButton = new JButton("Set");     setButton.setActionCommand("Set");     setButton.addActionListener(this);     getRootPane().setDefaultButton(setButton);     // main part of the dialog     list = new JList(data) {       // Subclass JList to workaround bug 4832765, which can cause the       // scroll pane to not let the user easily scroll up to the beginning       // of the list. An alternative would be to set the unitIncrement       // of the JScrollBar to a fixed value. You wouldn't get the nice       // aligned scrolling, but it should work.       public int getScrollableUnitIncrement(Rectangle visibleRect,           int orientation, int direction) {         int row;         if (orientation == SwingConstants.VERTICAL && direction < 0             && (row = getFirstVisibleIndex()) != -1) {           Rectangle r = getCellBounds(row, row);           if ((r.y == visibleRect.y) && (row != 0)) {             Point loc = r.getLocation();             loc.y--;             int prevIndex = locationToIndex(loc);             Rectangle prevR = getCellBounds(prevIndex, prevIndex);             if (prevR == null || prevR.y >= r.y) {               return 0;             }             return prevR.height;           }         }         return super.getScrollableUnitIncrement(visibleRect, orientation,             direction);       }     };     list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);     if (longValue != null) {       list.setPrototypeCellValue(longValue); // get extra space     }     list.setLayoutOrientation(JList.HORIZONTAL_WRAP);     list.setVisibleRowCount(-1);     list.addMouseListener(new MouseAdapter() {       public void mouseClicked(MouseEvent e) {         if (e.getClickCount() == 2) {           setButton.doClick(); // emulate button click         }       }     });     JScrollPane listScroller = new JScrollPane(list);     listScroller.setPreferredSize(new Dimension(250, 80));     listScroller.setAlignmentX(LEFT_ALIGNMENT);     // Create a container so that we can add a title around     // the scroll pane. Can't add a title directly to the     // scroll pane because its background would be white.     // Lay out the label and scroll pane from top to bottom.     JPanel listPane = new JPanel();     listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));     JLabel label = new JLabel(labelText);     label.setLabelFor(list);     listPane.add(label);     listPane.add(Box.createRigidArea(new Dimension(0, 5)));     listPane.add(listScroller);     listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));     // Lay out the buttons from left to right.     JPanel buttonPane = new JPanel();     buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));     buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));     buttonPane.add(Box.createHorizontalGlue());     buttonPane.add(cancelButton);     buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));     buttonPane.add(setButton);     // Put everything together, using the content pane's BorderLayout.     Container contentPane = getContentPane();     contentPane.add(listPane, BorderLayout.CENTER);     contentPane.add(buttonPane, BorderLayout.PAGE_END);     // Initialize values.     setValue(initialValue);     pack();     setLocationRelativeTo(locationComp);   }   // Handle clicks on the Set and Cancel buttons.   public void actionPerformed(ActionEvent e) {     if ("Set".equals(e.getActionCommand())) {       ListDialog.value = (String) (list.getSelectedValue());     }     ListDialog.dialog.setVisible(false);   } }