/*
* 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:
*
*
* String[] choices = { "A", "long", "array", "of", "strings" };
* String selectedName = ListDialog.showDialog(componentInControllingFrame,
* locatorComponent, "A description of the list:", "Dialog Title", choices,
* choices[0]);
*
*/
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);
}
}