Java/Swing Components/Dialog
Содержание
- 1 About dialog
- 2 A popup dialog with a message and a scrollable list of items
- 3 Custom dialog box to enter dates
- 4 Dialog Panel
- 5 Login Dialog
- 6 Password Dialog
- 7 Shake a dialog
- 8 Swing error dialog (Exception dialog)
- 9 Swing Login Domain Dialog with animation
- 10 The base class for standard dialogs.
- 11 Tip Of Day Dialog
- 12 Use this modal dialog to let the user choose one string from a long list
- 13 Vista Transparent Dialog
- 14 Compatible Images
- 15 Creating Thumbnails
- 16 Image Manipulation
About dialog
<source lang="java">
import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; class AboutDialog extends JDialog {
public AboutDialog() { setTitle("About"); setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); add(Box.createRigidArea(new Dimension(0, 10))); JLabel name = new JLabel("Notes"); name.setAlignmentX(0.5f); add(name); add(Box.createRigidArea(new Dimension(0, 100))); JButton close = new JButton("Close"); close.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { dispose(); } }); close.setAlignmentX(0.5f); add(close); setModalityType(ModalityType.APPLICATION_MODAL); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setSize(300, 200); }
} public class SimpleDialog {
public static void main(String[] args) { JMenuBar menubar = new JMenuBar(); JMenu file = new JMenu("File"); file.setMnemonic(KeyEvent.VK_F); JMenu help = new JMenu("Help"); help.setMnemonic(KeyEvent.VK_H); JMenuItem about = new JMenuItem("About"); help.add(about); about.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { AboutDialog ad = new AboutDialog(); ad.setVisible(true); } }); menubar.add(file); menubar.add(help); JFrame f = new JFrame(); f.setJMenuBar(menubar); f.setSize(300, 200); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); }
}
</source>
A popup dialog with a message and a scrollable list of items
<source lang="java">
/*BEGIN_COPYRIGHT_BLOCK
* * Copyright (c) 2001-2008, JavaPLT group at Rice University (drjava@rice.edu) * 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 names of DrJava, the JavaPLT group, Rice University, 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. * * This software is Open Source Initiative approved Open Source Software. * Open Source Initative Approved is a trademark of the Open Source Initiative. * * This file is part of DrJava. Download the current version of this project * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/ * * END_COPYRIGHT_BLOCK*/
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.table.AbstractTableModel; /**
*The ScrollableListSelectionDialog is a popup dialog with a message * and a scrollable list of items. Each item may be either selected or * unselected. A ScrollableListSelectionDialog should be used when * an operation needs to act on a variable number of items, for * example, when saving modified files.
**
The message (also know as the leader text) is displayed above the * items with an optional icon. The items are displayed in a scrollable * table. A column of checkboxes allows selection of the items. Buttons * are added below the list of items.
**
This dialog is somewhat styled after * {@link javax.swing.JOptionPane} and uses the message-type constants * from JOptionPane.
* * @author Chris Warrington * @version $Id$ * @since 2007-04-08 */
public class ScrollableListSelectionDialog extends JDialog {
/** A enumeration of the various selection states. */ public enum SelectionState { /** Indicates that an item is selected. */ SELECTED, /** Indicates that an item is not selected. */ UNSELECTED }; /** The default width for this dialog. */ private static final int DEFAULT_WIDTH = 400; /** The default height for this dialog. */ private static final int DEFAULT_HEIGHT = 450; /** The ratio of the screen width to use by default. */ private static final double WIDTH_RATIO = .75; /** The ratio of the screen height to use by default. */ private static final double HEIGHT_RATIO = .50; /** The table displaying the items. */ protected final JTable table; /** The AbstractTableModel backing the table. */ protected final AbstractTableModel tableModel; /** The number of columns in the table. */ private static final int NUM_COLUMNS = 2; /** The column index of the checkboxes column. */ private static final int CHECKBOXES_COLUMN_INDEX = 0; /** The column index of the strings column. */ private static final int STRINGS_COLUMN_INDEX = 1; /** The items in the table. */ protected final Vector<String> dataAsStrings; /** The selected items in the table. This Vector maps to * _dataAsStrings by index. This value may be accessed by multiple * threads. Threads wishing to access it should acquire its * intrinsic lock. */ protected final Vector<Boolean> selectedItems;/**
Creates a new ScrollableListSelectionDialog with the given * title, leader text, and items. The list of items is used to * construct an internal string list that is not backed by the original * list. Changes made to the list or items after dialog construction * will not be reflected in the dialog.
**
The default sizing, message type, and icon are used. All the * items are selected by default.
* * @param owner The frame that owns this dialog. May be {@code null}. * @param dialogTitle The text to use as the dialog title. * @param leaderText Text to display before the list of items. * @param listItems The items to display in the list. * @param itemDescription A textual description of the items. This is used as the column heading for the items. * * @throws IllegalArgumentException if {@code listItems} is {@code null.} */ public ScrollableListSelectionDialog(final Frame owner, final String dialogTitle, final String leaderText, final Collection<?> listItems, final String itemDescription) { this(owner, dialogTitle, leaderText, listItems, itemDescription, SelectionState.SELECTED, JOptionPane.PLAIN_MESSAGE); }/**
Creates a new ScrollableListSelectionDialog with the given * title, leader text, items, and message type. The list of items is * used to construct an internal string list that is not backed by the * original list. Changes made to the list or items after dialog * construction will not be reflected in the dialog.
**
The message type must be one of the message types from * {@link javax.swing.JOptionPane}. The message type controlls which * default icon is used.
**
The default sizing and icon are used.
* * @param owner The frame that owns this dialog. May be {@code null}. * @param dialogTitle The text to use as the dialog title. * @param leaderText Text to display before the list of items. * @param listItems The items to display in the list. * @param itemDescription A textual description of the items. This is used as the column heading for the items. * @param defaultSelection The default selection state (selected or unselected) for the items. * @param messageType The type of dialog message. * * @throws IllegalArgumentException if {@code listItems} is {@code null.} * @throws IllegalArgumentException if the message type is unknown or {@code listItems} is {@code null.} */ public ScrollableListSelectionDialog(final Frame owner, final String dialogTitle, final String leaderText, final Collection<?> listItems, final String itemDescription, final SelectionState defaultSelection, final int messageType) { this(owner, dialogTitle, leaderText, listItems, itemDescription, defaultSelection, messageType, DEFAULT_WIDTH, DEFAULT_HEIGHT, null, true); }/**
Creates a new ScrollableListSelectionDialog with the given * title, leader text, items, message type, width, height, and icon. * The list of items is used to construct an internal string list that * is not backed by the original list. Changes made to the list or * items after dialog construction will not be reflected in the * dialog.
**
The message type must be one of the message types from * {@link javax.swing.JOptionPane}. The message type controlls which * default icon is used. If {@code icon} is non-null, it is used * instead of the default icon.
* * @param owner The frame that owns this dialog. May be {@code null}. * @param dialogTitle The text to use as the dialog title. * @param leaderText Text to display before the list of items. * @param listItems The items to display in the list. * @param itemDescription A textual description of the items. This is used as the column heading for the items. * @param defaultSelection The default selection state (selected or unselected) for the items. * @param messageType The type of dialog message. * @param width The width of the dialog box. * @param height The height of the dialog box. * @param icon The icon to display. May be {@code null}. * * @throws IllegalArgumentException if {@code listItems} is {@code null.} * @throws IllegalArgumentException if the message type is unknown or {@code listItems} is {@code null.} */ public ScrollableListSelectionDialog(final Frame owner, final String dialogTitle, final String leaderText, final Collection<?> listItems, final String itemDescription, final SelectionState defaultSelection, final int messageType, final int width, final int height, final Icon icon) { this(owner, dialogTitle, leaderText, listItems, itemDescription, defaultSelection, messageType, width, height, icon, false); }/**
Creates a new ScrollableListSelectionDialog with the given * title, leader text, items, message type, width, height, and icon. * The list of items is used to construct an internal string list that * is not backed by the original list. Changes made to the list or * items after dialog construction will not be reflected in the * dialog.
**
The message type must be one of the message types from * {@link javax.swing.JOptionPane}. The message type controlls which * default icon is used. If {@code icon} is non-null, it is used * instead of the default icon.
* * @param owner The frame that owns this dialog. May be {@code null}. * @param dialogTitle The text to use as the dialog title. * @param leaderText Text to display before the list of items. * @param listItems The items to display in the list. * @param itemDescription A textual description of the items. This is used as the column heading for the items. * @param defaultSelection The default selection state (selected or unselected) for the items. * @param messageType The type of dialog message. * @param width The width of the dialog box. * @param height The height of the dialog box. * @param icon The icon to display. May be {@code null}. * @param fitToScreen If {@code true}, the width and height of the dialog will be calculated using the screen * dimensions, {@link #WIDTH_RATIO}, and {@link #HEIGHT_RATIO}. If {@code false}, the provided width and * height will be used. * @throws IllegalArgumentException if {@code listItems} is {@code null.} * @throws IllegalArgumentException if the message type is unknown or {@code listItems} is {@code null.} */ private ScrollableListSelectionDialog(final Frame owner, final String dialogTitle, final String leaderText, final Collection<?> listItems, final String itemDescription, final SelectionState defaultSelection, final int messageType, final int width, final int height, final Icon icon, final boolean fitToScreen) { super(owner, dialogTitle, true); if (!_isknownMessageType(messageType)) { throw new IllegalArgumentException("The message type \"" + messageType + "\" is unknown"); } if (listItems == null) { throw new IllegalArgumentException("listItems cannot be null"); } /* create the leader text panel */ JLabel dialogIconLabel = null; if (icon != null) { //use the user-provided icon dialogIconLabel = new JLabel(icon); } else { //lookup the message-dependent icon Icon messageIcon = _getIcon(messageType); if (messageIcon != null) { dialogIconLabel = new JLabel(messageIcon); } } final JPanel leaderPanel = new JPanel(); final JLabel leaderLabel = new JLabel(leaderText); leaderPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); if (dialogIconLabel != null) { leaderPanel.add(dialogIconLabel); } leaderPanel.add(leaderLabel); /* create the table */ //copy the items string representations into a vector dataAsStrings = new Vector<String>(listItems.size()); for (Object obj : listItems) { if (obj != null) { final String objAsString = obj.toString(); dataAsStrings.add(objAsString); } } dataAsStrings.trimToSize(); final int numItems = dataAsStrings.size(); selectedItems = new Vector<Boolean>(numItems); synchronized(selectedItems) { for (int i = 0; i < numItems; ++i) { selectedItems.add(i, defaultSelection == SelectionState.SELECTED); } selectedItems.trimToSize(); } assert selectedItems.size() == dataAsStrings.size(); tableModel = new AbstractTableModel() { //@Override - uncomment when we start compiling with Java 6 public int getRowCount() { return numItems; } //@Override - uncomment when we start compiling with Java 6 public int getColumnCount() { return NUM_COLUMNS; } //@Override - uncomment when we start compiling with Java 6 public Object getValueAt(int row, int column) { if (column == CHECKBOXES_COLUMN_INDEX) { assert row >= 0; assert row < numItems; synchronized(selectedItems) { return selectedItems.get(row); } } else if (column == STRINGS_COLUMN_INDEX) { assert row >= 0; assert row < numItems; return dataAsStrings.get(row); } else { assert false; return null; } } @Override public String getColumnName(int column) { if (column == CHECKBOXES_COLUMN_INDEX) { return ""; } else if (column == STRINGS_COLUMN_INDEX) { return itemDescription; } else { assert false; return ""; } } @Override public Class<?> getColumnClass(final int columnIndex) { if (columnIndex == CHECKBOXES_COLUMN_INDEX) { return Boolean.class; } else if (columnIndex == STRINGS_COLUMN_INDEX) { return String.class; } else { assert false; return Object.class; } } @Override public boolean isCellEditable(final int rowIndex, final int columnIndex) { return columnIndex == CHECKBOXES_COLUMN_INDEX; //only checkboxes are editable } @Override public void setValueAt(final Object newValue, final int rowIndex, final int columnIndex) { assert columnIndex == CHECKBOXES_COLUMN_INDEX; assert rowIndex >= 0; assert rowIndex < numItems; assert newValue instanceof Boolean; final Boolean booleanValue = (Boolean)newValue; synchronized(selectedItems) { selectedItems.set(rowIndex, booleanValue); } } }; table = new JTable(tableModel); /* * this listener enabled clicking in the string column to update the * checkbox. */ table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { final Point clickPoint = e.getPoint(); // which column was clicked on final int clickColumn = table.columnAtPoint(clickPoint); if (clickColumn == STRINGS_COLUMN_INDEX) { //it was the strings column, so update the check status of the row //Swing does not do this automatically final int clickRow = table.rowAtPoint(clickPoint); if (clickRow >= 0 && clickRow < numItems) { synchronized(selectedItems) { final boolean currentValue = selectedItems.get(clickRow); final boolean newValue = !currentValue; selectedItems.set(clickRow, newValue); /* We are deliberately holding on to the lock while the * listeners are notified. This, in theory, speeds up the * listeners because they don"t have to re-acquire the * lock. Because the internals of Swing are unknown, the * lock may need to be released before the listeners are * notified. Only time will tell. * * PS: If it turns out that holding the lock during * the listener updates is a problem, modify this comment * accordingly. Thank you. */ tableModel.fireTableCellUpdated(clickRow, CHECKBOXES_COLUMN_INDEX); } } } } }); //set the column sizes table.getColumnModel().getColumn(CHECKBOXES_COLUMN_INDEX).setMinWidth(15); table.getColumnModel().getColumn(CHECKBOXES_COLUMN_INDEX).setMaxWidth(30); table.getColumnModel().getColumn(CHECKBOXES_COLUMN_INDEX).setPreferredWidth(20); table.getColumnModel().getColumn(CHECKBOXES_COLUMN_INDEX).sizeWidthToFit(); //create a scrollable view around the table final JScrollPane scrollPane = new JScrollPane(table); /* create the select all/select none panel */ final JPanel selectButtonsPanel = new JPanel(); selectButtonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); _addSelectButtons(selectButtonsPanel); /* create the button panel */ final JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); //allow children to add additional buttons, if overridden _addButtons(buttonPanel); /* create the center panel which contains the scroll pane and the * select all/select none buttons */ final JPanel centerPanel = new JPanel(); centerPanel.setLayout(new BorderLayout()); centerPanel.add(selectButtonsPanel, BorderLayout.NORTH); centerPanel.add(scrollPane, BorderLayout.CENTER); /* create the dialog */ final JPanel contentPanel = new JPanel(); contentPanel.setLayout(new BorderLayout(10, 5)); contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 10)); contentPanel.add(leaderPanel, BorderLayout.NORTH); contentPanel.add(centerPanel, BorderLayout.CENTER); contentPanel.add(buttonPanel, BorderLayout.SOUTH); getContentPane().add(contentPanel); /* calculate the dialog"s dimensions */ final Dimension dialogSize = new Dimension(); if (fitToScreen) { //use the screen dimensions to calculate the dialog"s final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int screenBasedWidth = (int) (WIDTH_RATIO * screenSize.getWidth()); int screenBasedHeight = (int) (HEIGHT_RATIO * screenSize.getHeight()); dialogSize.setSize(Math.max(DEFAULT_WIDTH, screenBasedWidth), Math.max(DEFAULT_HEIGHT, screenBasedHeight)); } else { //use the user-provided dimensions dialogSize.setSize(width, height); } setSize(dialogSize); } /** A method to check if they given message type is a know message * type. * * @param messageType The message type to check * @return {@code true} if the message type is known, {@code false} otherwise */ private boolean _isknownMessageType(final int messageType) { return messageType == JOptionPane.ERROR_MESSAGE || messageType == JOptionPane.INFORMATION_MESSAGE || messageType == JOptionPane.WARNING_MESSAGE || messageType == JOptionPane.QUESTION_MESSAGE || messageType == JOptionPane.PLAIN_MESSAGE; } /** Lookup the icon associated with the given messageType. The message * type must be one of the message types from * {@link javax.swing.JOptionPane}. * * @param messageType The message for which the icon is requested. * @return The message"s icon or {@code null} is no icon was found. */ private Icon _getIcon(final int messageType) { assert _isknownMessageType(messageType); /* The OptionPane.xxxIcon constants were taken from * javax.swing.plaf.basic.BasicOptionPaneUI, which may changed * without notice. */ if (messageType == JOptionPane.ERROR_MESSAGE) { return UIManager.getIcon("OptionPane.errorIcon"); } else if (messageType == JOptionPane.INFORMATION_MESSAGE) { return UIManager.getIcon("OptionPane.informationIcon"); } else if (messageType == JOptionPane.WARNING_MESSAGE) { return UIManager.getIcon("OptionPane.warningIcon"); } else if (messageType == JOptionPane.QUESTION_MESSAGE) { return UIManager.getIcon("OptionPane.questionIcon"); } else if (messageType == JOptionPane.PLAIN_MESSAGE) { return null; } else { //should never get here assert false; } return null; } /** Adds the "Select All" and "Select None" buttons * to the given panel. * * @param selectButtonsPanel The panel that should contain the buttons. */ private void _addSelectButtons(final JPanel selectButtonsPanel) { final JButton selectAllButton = new JButton("Select All"); selectAllButton.addActionListener(new SelectAllNoneActionListener(SelectionState.SELECTED)); selectButtonsPanel.add(selectAllButton); final JButton selectNoneButton = new JButton("Select None"); selectNoneButton.addActionListener(new SelectAllNoneActionListener(SelectionState.UNSELECTED)); selectButtonsPanel.add(selectNoneButton); } /** Adds buttons to the bottom of the dialog. By default, a single * "OK" button is added that calls {@link #closeDialog}. It * is also set as the dialog"s default button. * * Inheritors should feel free the change settings of the panel such * as the layout manager. However, no guarantees are made that every * change will work with every version of this class. * * @param buttonPanel The JPanel that should contain the buttons. */ protected void _addButtons(final JPanel buttonPanel) { final JButton okButton = new JButton("OK"); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent notUsed) { closeDialog(); } }); buttonPanel.add(okButton); getRootPane().setDefaultButton(okButton); } /** * Shows the dialog. */ public void showDialog() { pack(); setVisible(true); } /** Should be called when the dialog should be closed. The default implementation * simply hides the dialog. */ protected void closeDialog() { setVisible(false); } /** Returns the string representation of those items that are * currently selected. The items will be in the same relative order * as they were at construction time. The resultant collection may be * empty. The resultant collection is unmodifiable. The resultant * collection is simply a snapshot (i.e., It will not be updated as * more items are selected.). This method may be called from * non-event queue threads. * * @return The currently selected items. */ public java.util.List<String> selectedItems() { final java.util.List<String> results = new ArrayList<String>(); synchronized(selectedItems) { /* This entire loop is synchronized so that we get a consistent * view of the selected items. It is also faster. */ for (int i = 0; i < dataAsStrings.size(); ++i) { if (selectedItems.get(i)) { results.add(dataAsStrings.get(i)); } } } return Collections.unmodifiableList(results); } /** An ActionListener that handles the "Select All" and * "Select None" buttons. It will set the selection state * of every item to the given selection state. */ private class SelectAllNoneActionListener implements ActionListener { /** The value that the selection state will be set to when this * listener runs. */ private final boolean _setToValue; /** * Creates a new SelectAllNoneActionListener that will set the state * of every item to the given state. * * @param setToState The state to set all the items to. */ public SelectAllNoneActionListener(SelectionState setToState) { _setToValue = setToState == SelectionState.SELECTED; } /** * The code that runs in response to the button"s action. * This is the code that actually sets the selection state of the * items. * * @param notUsed Not used. */ public void actionPerformed(ActionEvent notUsed) { /* See comment in the table"s mouse listener for a discussion * about the duration of the lock. */ synchronized(selectedItems) { for (int i = 0; i < selectedItems.size(); ++i) { selectedItems.set(i, _setToValue); } tableModel.fireTableRowsUpdated(0, Math.max(0, selectedItems.size() - 1)); } } } /** A simple main method for testing purposes. * * @param args Not used. */ public static void main(String args[]) { final Collection<String> data = new java.util.ArrayList<String>(); data.add("how"); data.add("now"); data.add("brown"); data.add("cow"); EventQueue.invokeLater(new Runnable() { public void run() { ScrollableListSelectionDialog ld = new ScrollableListSelectionDialog(null, "TITLE", "LEADER", data, "Words", SelectionState.SELECTED, JOptionPane.ERROR_MESSAGE) { @Override protected void closeDialog() { super.closeDialog(); Collection<String> si = selectedItems(); for (String i : si) { System.out.println(i); } } }; ld.pack(); ld.setVisible(true); } }); }
}
</source>
Custom dialog box to enter dates
<source lang="java">
/**
* This file is part of the jcrontab package * Copyright (C) 2002 Alexandre Pereira Calsavara * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA * * For questions, suggestions: * * iolalla@yahoo.ru * */
import java.awt.Color; import java.awt.Container; import java.awt.Dialog; import java.awt.Frame; import java.awt.GridLayout; import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.Border;
/**
* Custom dialog box to enter dates. The DateChooser
* class presents a calendar and allows the user to visually select a
* day, month and year so that it is impossible to enter an invalid
* date.
* @author $Author: iolalla $
* @version $Revision: 1.1 $
**/
public class DateChooser extends JDialog
implements ItemListener, MouseListener, FocusListener, KeyListener, ActionListener
{
/** Names of the months. */ private static final String[] MONTHS = new String[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; /** Names of the days of the week. */ private static final String[] DAYS = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; /** Text color of the days of the weeks, used as column headers in the calendar. */ private static final Color WEEK_DAYS_FOREGROUND = Color.black; /** Text color of the days" numbers in the calendar. */ private static final Color DAYS_FOREGROUND = Color.blue; /** Background color of the selected day in the calendar. */ private static final Color SELECTED_DAY_FOREGROUND = Color.white; /** Text color of the selected day in the calendar. */ private static final Color SELECTED_DAY_BACKGROUND = Color.blue; /** Empty border, used when the calendar does not have the focus. */ private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(1,1,1,1); /** Border used to highlight the selected day when the calendar has the focus. */ private static final Border FOCUSED_BORDER = BorderFactory.createLineBorder(Color.yellow,1); /** First year that can be selected. */ private static final int FIRST_YEAR = 1900; /** Last year that can be selected. */ private static final int LAST_YEAR = 2100; /** Auxiliary variable to compute dates. */ private GregorianCalendar calendar; /** Calendar, as a matrix of labels. The first row represents the first week of the month, the second row, the second week, and so on. Each column represents a day of the week, the first is Sunday, and the last is Saturday. The label"s text is the number of the corresponding day. */ private JLabel[][] days; /** Day selection control. It is just a panel that can receive the focus. The actual user interaction is driven by theDateChooser
class. */ private FocusablePanel daysGrid; /** Month selection control. */ private JComboBox month; /** Year selection control. */ private JComboBox year; /** "Ok" button. */ private JButton ok; /** "Cancel" button. */ private JButton cancel; /** Day of the week (0=Sunday) corresponding to the first day of the selected month. Used to calculate the position, in the calendar ({@link #days}), corresponding to a given day. */ private int offset; /** Last day of the selected month. */ private int lastDay; /** Selected day. */ private JLabel day; /**true
if the "Ok" button was clicked to close the dialog box,false
otherwise. */ private boolean okClicked;
/**
* Custom panel that can receive the focus. Used to implement the
* calendar control.
**/
private static class FocusablePanel extends JPanel
{
/**
* Constructs a new FocusablePanel
with the given
* layout manager.
*
* @param layout layout manager
**/
public FocusablePanel( LayoutManager layout ) {
super( layout );
}
/** * Always returnstrue
, since *FocusablePanel
can receive the focus. * * @returntrue
**/ public boolean isFocusTraversable() { return true; } }
/**
* Initializes this DateChooser
object. Creates the
* controls, registers listeners and initializes the dialog box.
**/
private void construct()
{
calendar = new GregorianCalendar();
month = new JComboBox(MONTHS);
month.addItemListener( this );
year = new JComboBox();
for ( int i=FIRST_YEAR; i<=LAST_YEAR; i++ )
year.addItem( Integer.toString(i) );
year.addItemListener( this );
days = new JLabel[7][7];
for ( int i=0; i<7; i++ ) {
days[0][i] = new JLabel(DAYS[i],JLabel.RIGHT);
days[0][i].setForeground( WEEK_DAYS_FOREGROUND );
}
for ( int i=1; i<7; i++ )
for ( int j=0; j<7; j++ )
{
days[i][j] = new JLabel(" ",JLabel.RIGHT);
days[i][j].setForeground( DAYS_FOREGROUND );
days[i][j].setBackground( SELECTED_DAY_BACKGROUND );
days[i][j].setBorder( EMPTY_BORDER );
days[i][j].addMouseListener( this );
}
ok = new JButton("Ok");
ok.addActionListener( this );
cancel = new JButton("Cancel");
cancel.addActionListener( this );
JPanel monthYear = new JPanel();
monthYear.add( month );
monthYear.add( year );
daysGrid = new FocusablePanel(new GridLayout(7,7,5,0));
daysGrid.addFocusListener( this );
daysGrid.addKeyListener( this );
for ( int i=0; i<7; i++ )
for ( int j=0; j<7; j++ )
daysGrid.add( days[i][j] );
daysGrid.setBackground( Color.white );
daysGrid.setBorder( BorderFactory.createLoweredBevelBorder() );
JPanel daysPanel = new JPanel();
daysPanel.add( daysGrid );
JPanel buttons = new JPanel();
buttons.add( ok );
buttons.add( cancel );
Container dialog = getContentPane();
dialog.add( "North", monthYear );
dialog.add( "Center", daysPanel );
dialog.add( "South", buttons );
pack();
setResizable( false );
}
/**
* Gets the selected day, as an int
. Parses the text
* of the selected label in the calendar to get the day.
*
* @return the selected day or -1 if there is no day selected
**/
private int getSelectedDay()
{
if ( day == null )
return -1 ;
try {
return Integer.parseInt(day.getText());
} catch ( NumberFormatException e ) {
}
return -1;
}
/** * Sets the selected day. The day is specified as the label * control, in the calendar, corresponding to the day to select. * * @param newDay day to select **/ private void setSelected( JLabel newDay ) { if ( day != null ) { day.setForeground( DAYS_FOREGROUND ); day.setOpaque( false ); day.setBorder( EMPTY_BORDER ); } day = newDay; day.setForeground( SELECTED_DAY_FOREGROUND ); day.setOpaque( true ); if ( daysGrid.hasFocus() ) day.setBorder( FOCUSED_BORDER ); }
/** * Sets the selected day. The day is specified as the number of * the day, in the month, to selected. The function compute the * corresponding control to select. * * @param newDay day to select **/ private void setSelected( int newDay ) { setSelected( days[(newDay+offset-1)/7+1][(newDay+offset-1)%7] ); }
/** * Updates the calendar. This function updates the calendar panel * to reflect the month and year selected. It keeps the same day * of the month that was selected, except if it is beyond the last * day of the month. In this case, the last day of the month is * selected. **/ private void update() { int iday = getSelectedDay(); for ( int i=0; i<7; i++ ) { days[1][i].setText( " " ); days[5][i].setText( " " ); days[6][i].setText( " " ); } calendar.set( Calendar.DATE, 1 ); calendar.set( Calendar.MONTH, month.getSelectedIndex()+Calendar.JANUARY ); calendar.set( Calendar.YEAR, year.getSelectedIndex()+FIRST_YEAR ); offset = calendar.get(Calendar.DAY_OF_WEEK)-Calendar.SUNDAY; lastDay = calendar.getActualMaximum(Calendar.DATE); for ( int i=0; i<lastDay; i++ ) days[(i+offset)/7+1][(i+offset)%7].setText( String.valueOf(i+1) ); if ( iday != -1 ) { if ( iday > lastDay ) iday = lastDay; setSelected( iday ); } }
/** * Called when the "Ok" button is pressed. Just sets a flag and * hides the dialog box. **/ public void actionPerformed( ActionEvent e ) { if ( e.getSource() == ok ) okClicked = true; hide(); } /** * Called when the calendar gains the focus. Just re-sets the * selected day so that it is redrawn with the border that * indicate focus. **/ public void focusGained( FocusEvent e ) { setSelected( day ); } /** * Called when the calendar loses the focus. Just re-sets the * selected day so that it is redrawn without the border that * indicate focus. **/ public void focusLost( FocusEvent e ) { setSelected( day ); } /** * Called when a new month or year is selected. Updates the calendar * to reflect the selection. **/ public void itemStateChanged( ItemEvent e ) { update(); } /** * Called when a key is pressed and the calendar has the * focus. Handles the arrow keys so that the user can select a day * using the keyboard. **/ public void keyPressed( KeyEvent e ) { int iday = getSelectedDay(); switch ( e.getKeyCode() ) { case KeyEvent.VK_LEFT: if ( iday > 1 ) setSelected( iday-1 ); break; case KeyEvent.VK_RIGHT: if ( iday < lastDay ) setSelected( iday+1 ); break; case KeyEvent.VK_UP: if ( iday > 7 ) setSelected( iday-7 ); break; case KeyEvent.VK_DOWN: if ( iday <= lastDay-7 ) setSelected( iday+7 ); break; } } /** * Called when the mouse is clicked on a day in the * calendar. Selects the clicked day. **/ public void mouseClicked( MouseEvent e ) { JLabel day = (JLabel)e.getSource(); if ( !day.getText().equals(" ") ) setSelected( day ); daysGrid.requestFocus(); } public void keyReleased( KeyEvent e ) {} public void keyTyped( KeyEvent e ) {} public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e) {} public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e) {}
/**
* Constructs a new DateChooser
with the given title.
*
* @param owner owner dialog
*
* @param title dialog title
**/
public DateChooser( Dialog owner, String title )
{
super( owner, title, true );
construct();
}
/**
* Constructs a new DateChooser
.
*
* @param owner owner dialog
**/
public DateChooser( Dialog owner )
{
super( owner, true );
construct();
}
/**
* Constructs a new DateChooser
with the given title.
*
* @param owner owner frame
*
* @param title dialog title
**/
public DateChooser( Frame owner, String title )
{
super( owner, title, true );
construct();
}
/**
* Constructs a new DateChooser
.
*
* @param owner owner frame
**/
public DateChooser( Frame owner )
{
super( owner, true );
construct();
}
/**
* Selects a date. Displays the dialog box, with a given date as
* the selected date, and allows the user select a new date.
*
* @param date initial date
*
* @return the new date selected or null
if the user
* press "Cancel" or closes the dialog box
**/
public Date select( Date date )
{
calendar.setTime( date );
int _day = calendar.get(Calendar.DATE);
int _month = calendar.get(Calendar.MONTH);
int _year = calendar.get(Calendar.YEAR);
year.setSelectedIndex( _year-FIRST_YEAR );
month.setSelectedIndex( _month-Calendar.JANUARY );
setSelected( _day );
okClicked = false;
show();
if ( !okClicked )
return null;
calendar.set( Calendar.DATE, getSelectedDay() );
calendar.set( Calendar.MONTH, month.getSelectedIndex()+Calendar.JANUARY );
calendar.set( Calendar.YEAR, year.getSelectedIndex()+FIRST_YEAR );
return calendar.getTime();
}
/** * Selects new date. Just calls {@link #select(Date)} with the * system date as the parameter. * * @return the same as the function {@link #select(Date)} **/ public Date select() { return select(new Date()); }
}
</source>
Dialog Panel
<source lang="java">
/*
* Enhydra Java Application Server Project * * The contents of this file are subject to the Enhydra Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License on * the Enhydra web site ( http://www.enhydra.org/ ). * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific terms governing rights and limitations * under the License. * * The Initial Developer of the Enhydra Application Server is Lutris * Technologies, Inc. The Enhydra Application Server and portions created * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc. * All Rights Reserved. * * Contributor(s): * */
// Standard imports import java.awt.BorderLayout; import java.awt.Window; import java.awt.Dialog; import java.awt.Frame; import java.awt.Point; import java.awt.event.WindowEvent; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JOptionPane; // public class DialogPanel extends JPanel {
public final static int CANCEL_OPTION = JOptionPane.CANCEL_OPTION; public final static int OK_OPTION = JOptionPane.OK_OPTION; // private int option = DialogPanel.CANCEL_OPTION; private LocalDialog dialog = null; private Window owner = null; private boolean windowClose = false; private boolean standalone = false; private boolean modal = true; private String title = new String(); public Window getOwner() { return owner; } public void setOwner(Window w) { owner = w; } public String getTitle() { return title; } public void setTitle(String t) { title = t; } public boolean isModal() { return modal; } public void setModal(boolean b) { modal = b; } public int getOption() { return option; } public void setOption(int o) { option = o; } public LocalDialog getDialog() { return dialog; } public void startDialogThread() { Thread dialogThread = new Thread() { public void run() { showDialog(); } }; dialogThread.start(); } public int showDialog() { BorderLayout layout = null; Point cp = null; if (dialog == null) { if (getOwner() == null) { dialog = new LocalDialog(); } else if (getOwner() instanceof Frame) { dialog = new LocalDialog((Frame) getOwner()); } else if (getOwner() instanceof Dialog) { dialog = new LocalDialog((Dialog) getOwner()); } else { dialog = new LocalDialog(); } } dialog.setModal(isModal()); dialog.setTitle(getTitle()); layout = new BorderLayout(); dialog.getRootPane().setLayout(layout); dialog.getRootPane().add(this, BorderLayout.CENTER); dialog.pack(); dialog.show(); return option; } // // PROTECTED // protected void hideDialog() { if (dialog != null) { dialog.setVisible(false); } } protected void clearDialog() { if (dialog != null) { dialog.setVisible(false); dialog.getRootPane().removeAll(); dialog.removeAll(); dialog.dispose(); } if (isStandalone()) { System.exit(0); } } protected boolean isWindowClose() { return windowClose; } protected void setWindowClose(boolean b) { windowClose = b; } protected boolean isStandalone() { return standalone; } protected void setStandalone(boolean b) { standalone = b; } private class LocalDialog extends JDialog { public LocalDialog() { super(); } public LocalDialog(Dialog owner) { super(owner); } public LocalDialog(Frame owner) { super(owner); } protected void processWindowEvent(WindowEvent e) { if (isWindowClose()) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { clearDialog(); } super.processWindowEvent(e); } } }
}
</source>
Login Dialog
Password Dialog
<source lang="java">
/*
* Copyright (C) 2001-2007 Stephen Ostermiller * http://ostermiller.org/contact.pl?regarding=Java+Utilities * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * See COPYING.TXT for details. */
import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; /**
* A modal dialog that asks the user for a user name and password.
* More information about this class is available from .
*
*
* * PasswordDialog p = new PasswordDialog(null, "Test"); * if(p.showDialog()){ * System.out.println("Name: " + p.getName()); * System.out.println("Pass: " + p.getPass()); * } else { * System.out.println("User selected cancel"); * } *
* * * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities * @since ostermillerutils 1.00.00 */
public class PasswordDialog extends JDialog {
/** * Serial version id */ private static final long serialVersionUID = -832548326686122133L; /** * Locale specific strings displayed to the user. * * @since ostermillerutils 1.00.00 */ protected ResourceBundle labels; /** * Set the locale used for getting localized * strings. * * @param locale Locale used to for i18n. * * @since ostermillerutils 1.00.00 */ @Override public void setLocale(Locale locale){ labels = ResourceBundle.getBundle("com.Ostermiller.util.PasswordDialog", locale); } /** * Where the name is typed. * * @since ostermillerutils 1.00.00 */ protected JTextField name; /** * Where the password is typed. * * @since ostermillerutils 1.00.00 */ protected JPasswordField pass; /** * The OK button. * * @since ostermillerutils 1.00.00 */ protected JButton okButton; /** * The cancel button. * * @since ostermillerutils 1.00.00 */ protected JButton cancelButton; /** * The label for the field in which the name is typed. * * @since ostermillerutils 1.00.00 */ protected JLabel nameLabel; /** * The label for the field in which the password is typed. * * @since ostermillerutils 1.00.00 */ protected JLabel passLabel; /** * Set the name that appears as the default * An empty string will be used if this in not specified * before the dialog is displayed. * * @param name default name to be displayed. * * @since ostermillerutils 1.00.00 */ @Override public void setName(String name){ this.name.setText(name); } /** * Set the password that appears as the default * An empty string will be used if this in not specified * before the dialog is displayed. * * @param pass default password to be displayed. * * @since ostermillerutils 1.00.00 */ public void setPass(String pass){ this.pass.setText(pass); } /** * Set the label on the OK button. * The default is a localized string. * * @param ok label for the ok button. * * @since ostermillerutils 1.00.00 */ public void setOKText(String ok){ this.okButton.setText(ok); pack(); } /** * Set the label on the cancel button. * The default is a localized string. * * @param cancel label for the cancel button. * * @since ostermillerutils 1.00.00 */ public void setCancelText(String cancel){ this.cancelButton.setText(cancel); pack(); } /** * Set the label for the field in which the name is entered. * The default is a localized string. * * @param name label for the name field. * * @since ostermillerutils 1.00.00 */ public void setNameLabel(String name){ this.nameLabel.setText(name); pack(); } /** * Set the label for the field in which the password is entered. * The default is a localized string. * * @param pass label for the password field. * * @since ostermillerutils 1.00.00 */ public void setPassLabel(String pass){ this.passLabel.setText(pass); pack(); } /** * Get the name that was entered into the dialog before * the dialog was closed. * * @return the name from the name field. * * @since ostermillerutils 1.00.00 */ @Override public String getName(){ return name.getText(); } /** * Get the password that was entered into the dialog before * the dialog was closed. * * @return the password from the password field. * * @since ostermillerutils 1.00.00 */ public String getPass(){ return new String(pass.getPassword()); } /** * Finds out if user used the OK button or an equivalent action * to close the dialog. * Pressing enter in the password field may be the same as * "OK" but closing the dialog and pressing the cancel button * are not. * * @return true if the the user hit OK, false if the user canceled. * * @since ostermillerutils 1.00.00 */ public boolean okPressed(){ return pressed_OK; } /** * update this variable when the user makes an action * * @since ostermillerutils 1.00.00 */ private boolean pressed_OK = false; /** * Create this dialog with the given parent and title. * * @param parent window from which this dialog is launched * @param title the title for the dialog box window * * @since ostermillerutils 1.00.00 */ public PasswordDialog(Frame parent, String title) { super(parent, title, true); setLocale(Locale.getDefault()); if (title==null){ setTitle(labels.getString("dialog.title")); } if (parent != null){ setLocationRelativeTo(parent); } // super calls dialogInit, so we don"t need to do it again. } /** * Create this dialog with the given parent and the default title. * * @param parent window from which this dialog is launched * * @since ostermillerutils 1.00.00 */ public PasswordDialog(Frame parent) { this(parent, null); } /** * Create this dialog with the default title. * * @since ostermillerutils 1.00.00 */ public PasswordDialog() { this(null, null); } /** * Called by constructors to initialize the dialog. * * @since ostermillerutils 1.00.00 */ @Override protected void dialogInit(){ if (labels == null){ setLocale(Locale.getDefault()); } name = new JTextField("", 20); pass = new JPasswordField("", 20); okButton = new JButton(labels.getString("dialog.ok")); cancelButton = new JButton(labels.getString("dialog.cancel")); nameLabel = new JLabel(labels.getString("dialog.name") + " "); passLabel = new JLabel(labels.getString("dialog.pass") + " "); super.dialogInit(); KeyListener keyListener = (new KeyAdapter() { @Override public void keyPressed(KeyEvent e){ if (e.getKeyCode() == KeyEvent.VK_ESCAPE || (e.getSource() == cancelButton && e.getKeyCode() == KeyEvent.VK_ENTER)){ pressed_OK = false; PasswordDialog.this.setVisible(false); } if (e.getSource() == okButton && e.getKeyCode() == KeyEvent.VK_ENTER){ pressed_OK = true; PasswordDialog.this.setVisible(false); } } }); addKeyListener(keyListener); ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e){ Object source = e.getSource(); if (source == name){ // the user pressed enter in the name field. name.transferFocus(); } else { // other actions close the dialog. pressed_OK = (source == pass || source == okButton); PasswordDialog.this.setVisible(false); } } }; GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.insets.top = 5; c.insets.bottom = 5; JPanel pane = new JPanel(gridbag); pane.setBorder(BorderFactory.createEmptyBorder(10, 20, 5, 20)); c.anchor = GridBagConstraints.EAST; gridbag.setConstraints(nameLabel, c); pane.add(nameLabel); gridbag.setConstraints(name, c); name.addActionListener(actionListener); name.addKeyListener(keyListener); pane.add(name); c.gridy = 1; gridbag.setConstraints(passLabel, c); pane.add(passLabel); gridbag.setConstraints(pass, c); pass.addActionListener(actionListener); pass.addKeyListener(keyListener); pane.add(pass); c.gridy = 2; c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.CENTER; JPanel panel = new JPanel(); okButton.addActionListener(actionListener); okButton.addKeyListener(keyListener); panel.add(okButton); cancelButton.addActionListener(actionListener); cancelButton.addKeyListener(keyListener); panel.add(cancelButton); gridbag.setConstraints(panel, c); pane.add(panel); getContentPane().add(pane); pack(); } /** * Shows the dialog and returns true if the user pressed ok. * * @return true if the the user hit OK, false if the user canceled. * * @since ostermillerutils 1.00.00 */ public boolean showDialog(){ setVisible(true); return okPressed(); }
}
</source>
Shake a dialog
<source lang="java">
import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.Timer; public class Main {
JDialog dialog; Point naturalLocation; Timer shakeTimer; public Main(JDialog d) { dialog = d; } public void startShake() { final long startTime; naturalLocation = dialog.getLocation(); startTime = System.currentTimeMillis(); shakeTimer = new Timer(5, new ActionListener() { public void actionPerformed(ActionEvent e) { double TWO_PI = Math.PI * 2.0; double SHAKE_CYCLE = 50; long elapsed = System.currentTimeMillis() - startTime; double waveOffset = (elapsed % SHAKE_CYCLE) / SHAKE_CYCLE; double angle = waveOffset * TWO_PI; int SHAKE_DISTANCE = 10; int shakenX = (int) ((Math.sin(angle) * SHAKE_DISTANCE) + naturalLocation.x); dialog.setLocation(shakenX, naturalLocation.y); dialog.repaint(); int SHAKE_DURATION = 1000; if (elapsed >= SHAKE_DURATION) stopShake(); } }); shakeTimer.start(); } public void stopShake() { shakeTimer.stop(); dialog.setLocation(naturalLocation); dialog.repaint(); } public static void main(String[] args) { JOptionPane pane = new JOptionPane("your message",JOptionPane.ERROR_MESSAGE, JOptionPane.OK_OPTION); JDialog d = pane.createDialog(null, "title"); Main dec = new Main(d); d.pack(); d.setModal(false); d.setVisible(true); dec.startShake(); }
}
</source>
Swing error dialog (Exception dialog)
Swing Login Domain Dialog with animation
The base class for standard dialogs.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ------------------- * StandardDialog.java * ------------------- * (C) Copyright 2000-2008, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): Arnaud Lelievre; * * $Id: StandardDialog.java,v 1.7 2008/12/18 09:57:32 mungady Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.ui.*; * 08-Sep-2003 : Added internationalization via use of properties * resourceBundle (RFE 690236) (AL); * 18-Dec-2008 : Use ResourceBundleWrapper - see JFreeChart patch 1607918 by * Jess Thrysoee (DG); * */
import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.Frame; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JPanel;
/**
* The base class for standard dialogs. * * @author David Gilbert */
public class StandardDialog extends JDialog implements ActionListener {
/** Flag that indicates whether or not the dialog was cancelled. */ private boolean cancelled;
/** * Standard constructor - builds a dialog... * * @param owner the owner. * @param title the title. * @param modal modal? */ public StandardDialog(final Frame owner, final String title, final boolean modal) { super(owner, title, modal); this.cancelled = false; } /** * Standard constructor - builds a dialog... * * @param owner the owner. * @param title the title. * @param modal modal? */ public StandardDialog(final Dialog owner, final String title, final boolean modal) { super(owner, title, modal); this.cancelled = false; } /** * Returns a flag that indicates whether or not the dialog has been * cancelled. * * @return boolean. */ public boolean isCancelled() { return this.cancelled; } /** * Handles clicks on the standard buttons. * * @param event the event. */ public void actionPerformed(final ActionEvent event) { final String command = event.getActionCommand(); if (command.equals("helpButton")) { // display help information } else if (command.equals("okButton")) { this.cancelled = false; setVisible(false); } else if (command.equals("cancelButton")) { this.cancelled = true; setVisible(false); } } /** * Builds and returns the user interface for the dialog. This method is * shared among the constructors. * * @return the button panel. */ protected JPanel createButtonPanel() { final L1R2ButtonPanel buttons = new L1R2ButtonPanel( "Help", "OK", "Cancel"); final JButton helpButton = buttons.getLeftButton(); helpButton.setActionCommand("helpButton"); helpButton.addActionListener(this); final JButton okButton = buttons.getRightButton1(); okButton.setActionCommand("okButton"); okButton.addActionListener(this); final JButton cancelButton = buttons.getRightButton2(); cancelButton.setActionCommand("cancelButton"); cancelButton.addActionListener(this); buttons.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0)); return buttons; }
} /*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * -------------------- * L1R2ButtonPanel.java * -------------------- * (C) Copyright 2000-2004, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: L1R2ButtonPanel.java,v 1.4 2007/11/02 17:50:36 taqua Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.ui.*; * 26-Jun-2002 : Removed unnecessary import (DG); * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG); * */
/**
* A "ready-made" panel that has one button on the left and two buttons on the right - nested * panels and layout managers take care of resizing. * * @author David Gilbert */
class L1R2ButtonPanel extends JPanel {
/** The left button. */ private JButton left; /** The first button on the right of the panel. */ private JButton right1; /** The second button on the right of the panel. */ private JButton right2; /** * Standard constructor - creates a three button panel with the specified button labels. * * @param label1 the label for button 1. * @param label2 the label for button 2. * @param label3 the label for button 3. */ public L1R2ButtonPanel(final String label1, final String label2, final String label3) { setLayout(new BorderLayout()); // create the pieces... this.left = new JButton(label1); final JPanel rightButtonPanel = new JPanel(new GridLayout(1, 2)); this.right1 = new JButton(label2); this.right2 = new JButton(label3); rightButtonPanel.add(this.right1); rightButtonPanel.add(this.right2); // ...and put them together add(this.left, BorderLayout.WEST); add(rightButtonPanel, BorderLayout.EAST); } /** * Returns a reference to button 1, allowing the caller to set labels, action-listeners etc. * * @return the left button. */ public JButton getLeftButton() { return this.left; } /** * Returns a reference to button 2, allowing the caller to set labels, action-listeners etc. * * @return the right button 1. */ public JButton getRightButton1() { return this.right1; } /** * Returns a reference to button 3, allowing the caller to set labels, action-listeners etc. * * @return the right button 2. */ public JButton getRightButton2() { return this.right2; }
}
</source>
Tip Of Day Dialog
<source lang="java">
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextPane; public class TipOfDay {
public static void main(String[] args) { JDialog d = new JDialog((Frame)null,"Tip of the Day"); JPanel basic = new JPanel(); basic.setLayout(new BoxLayout(basic, BoxLayout.Y_AXIS)); d.add(basic); JPanel topPanel = new JPanel(new BorderLayout(0, 0)); topPanel.setMaximumSize(new Dimension(450, 0)); JLabel hint = new JLabel("This is the tip"); hint.setBorder(BorderFactory.createEmptyBorder(10, 25, 10, 10)); topPanel.add(hint); JSeparator separator = new JSeparator(); separator.setForeground(Color.gray); topPanel.add(separator, BorderLayout.SOUTH); basic.add(topPanel); JPanel textPanel = new JPanel(new BorderLayout()); textPanel.setBorder(BorderFactory.createEmptyBorder(15, 25, 15, 25)); JTextPane pane = new JTextPane(); pane.setContentType("text/html");String text = "
Content
";pane.setText(text); pane.setEditable(false); textPanel.add(new JScrollPane(pane)); basic.add(textPanel); JPanel boxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0)); JCheckBox box = new JCheckBox("Show Tips at startup"); box.setMnemonic(KeyEvent.VK_S); boxPanel.add(box); basic.add(boxPanel); JPanel bottom = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton ntip = new JButton("Next Tip"); ntip.setMnemonic(KeyEvent.VK_N); JButton close = new JButton("Close"); close.setMnemonic(KeyEvent.VK_C); bottom.add(ntip); bottom.add(close); basic.add(bottom); bottom.setMaximumSize(new Dimension(450, 0)); d.setSize(new Dimension(450, 350)); d.setResizable(false); d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); d.setVisible(true); }
}
</source>
Use this modal dialog to let the user choose one string from a long list
<source lang="java">
/*
* 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.ruponent; 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.ru/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); }
}
</source>
Vista Transparent Dialog
<source lang="java">
/*
* Copyright (c) 2007, Romain Guy * 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 the TimingFramework project 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.Color; import java.awt.ruponent; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.util.HashMap; import java.util.Map; import javax.swing.UIManager; import javax.swing.border.Border; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ColorModel; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.awt.GraphicsConfiguration; import java.awt.Transparency; import java.awt.Graphics; import java.awt.GraphicsEnvironment; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; /**
* * @author Romain Guy <romain.guy@mac.ru> */
public class TextHighlightingDemo extends JFrame {
private VistaSearchDialog dialog; public TextHighlightingDemo() { super("Text Highlighting"); add(new DummyPanel()); JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING)); JButton button = new JButton("Show Dialog"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dialog = new VistaSearchDialog(TextHighlightingDemo.this); installInLayeredPane(dialog); dialog.setVisible(true); } }); panel.add(button); add(panel, BorderLayout.SOUTH); pack(); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void installInLayeredPane(JComponent component) { JLayeredPane layeredPane = getRootPane().getLayeredPane(); layeredPane.add(component, JLayeredPane.PALETTE_LAYER, 20); Dimension size = component.getPreferredSize(); component.setSize(size); component.setLocation((getWidth() - size.width) / 2, (getHeight() - size.height) / 2); component.revalidate(); component.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new TextHighlightingDemo().setVisible(true); } }); }
} /*
* Copyright (c) 2007, Romain Guy * 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 the TimingFramework project 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. */
class VistaSearchDialog extends JComponent {
private static final int BLUR_SIZE = 7; private BufferedImage image; private float alpha = 0.0f; public VistaSearchDialog(JFrame frame) { Container contentPane = frame.getRootPane(); image = GraphicsUtilities.createCompatibleTranslucentImage(contentPane.getWidth() + 2 * (int) BLUR_SIZE, contentPane.getHeight() + 2 * (int) BLUR_SIZE); Graphics2D g2 = image.createGraphics(); g2.translate(BLUR_SIZE, BLUR_SIZE); contentPane.paint(g2); g2.translate(-BLUR_SIZE, -BLUR_SIZE); g2.dispose(); // 1.5 second vs 0.3 second
// long start = System.currentTimeMillis();
image = changeImageWidth(image, image.getWidth() / 2); ConvolveOp gaussianFilter = getGaussianBlurFilter(BLUR_SIZE, true); image = gaussianFilter.filter(image, null); gaussianFilter = getGaussianBlurFilter(BLUR_SIZE, false); image = gaussianFilter.filter(image, null); ColorTintFilter colorMixFilter = new ColorTintFilter(Color.WHITE, 0.4f); image = colorMixFilter.filter(image, null); image = changeImageWidth(image, image.getWidth() * 2);
// System.out.println("time = " + // ((System.currentTimeMillis() - start) / 1000.0f));
setBorder(new DropShadowBorder(Color.BLACK, 0, 11, .2f, 16, false, true, true, true)); setLayout(new BorderLayout()); initComponents(); } public static BufferedImage changeImageWidth(BufferedImage image, int width) { float ratio = (float) image.getWidth() / (float) image.getHeight(); int height = (int) (width / ratio); BufferedImage temp = new BufferedImage(width, height, image.getType()); Graphics2D g2 = temp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); g2.dispose(); return temp; } public static ConvolveOp getGaussianBlurFilter(int radius, boolean horizontal) { if (radius < 1) { throw new IllegalArgumentException("Radius must be >= 1"); } int size = radius * 2 + 1; float[] data = new float[size]; float sigma = radius / 3.0f; float twoSigmaSquare = 2.0f * sigma * sigma; float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI); float total = 0.0f; for (int i = -radius; i <= radius; i++) { float distance = i * i; int index = i + radius; data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot; total += data[index]; } for (int i = 0; i < data.length; i++) { data[i] /= total; } Kernel kernel = null; if (horizontal) { kernel = new Kernel(size, 1, data); } else { kernel = new Kernel(1, size, data); } return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); } private void initComponents() { TitleBar titleBar = new TitleBar("Search in this Message"); add(titleBar, BorderLayout.NORTH); SearchPanel contentPane = new SearchPanel(); contentPane.setOpaque(false); contentPane.setBorder(BorderFactory.createEmptyBorder(16, 2, 16, 2)); add(contentPane); } @Override public boolean isOpaque() { return false; } @Override protected void paintComponent(Graphics g) { setupGraphics((Graphics2D) g); Point location = getLocation(); location.x = (int) (-location.x - BLUR_SIZE); location.y = (int) (-location.y - BLUR_SIZE); Insets insets = getInsets(); Shape oldClip = g.getClip(); g.setClip(insets.left, insets.top, getWidth() - insets.left - insets.right, getHeight() - insets.top - insets.bottom); g.drawImage(image, location.x, location.y, null); g.setClip(oldClip); } public float getAlpha() { return alpha; } public void setAlpha(float alpha) { this.alpha = alpha; repaint(); } private static void setupGraphics(Graphics2D g2) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Toolkit tk = Toolkit.getDefaultToolkit(); Map desktopHints = (Map) (tk.getDesktopProperty("awt.font.desktophints")); if (desktopHints != null) { g2.addRenderingHints(desktopHints); } } private class TitleBar extends JComponent { private String title; private TitleBar(String title) { this.title = title; setName("vistaTitleBar"); setFont(new Font("Dialog", Font.BOLD, 12)); setLayout(new GridBagLayout()); JButton button = new JButton(); button.setMargin(new Insets(0, 0, 0, 0)); button.setBorder(null); button.setIconTextGap(0); button.setVerticalAlignment(SwingConstants.TOP); button.setContentAreaFilled(false); button.setBorderPainted(false); button.setFocusPainted(false); button.setIcon(new ImageIcon(getClass().getResource("close-title-bar.png"))); button.setRolloverIcon(new ImageIcon(getClass().getResource("close-title-bar-rollover.png"))); button.setOpaque(false); button.setName("vistaCloseButton"); add(Box.createVerticalStrut(24), new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); add(button, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.FIRST_LINE_END, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0, 0)); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { VistaSearchDialog.this.setVisible(false); } }); Locator locator = new Locator(); addMouseListener(locator); addMouseMotionListener(locator); } @Override public boolean isOpaque() { return false; } @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; setupGraphics(g2); Paint oldPaint = g2.getPaint(); float rgb[] = new Color(0xe9efff).getRGBColorComponents(null); g2.setPaint(new GradientPaint(0.0f, 0.0f, new Color(rgb[0], rgb[1], rgb[2], 0.2f * getAlpha()), 0.0f, getHeight(), new Color(rgb[0], rgb[1], rgb[2], 0.8f * getAlpha()))); g2.fillRect(0, 0, getWidth(), getHeight()); drawText(g2, 3, 0.8f); g2.setPaint(oldPaint); g2.setColor(new Color(rgb[0], rgb[1], rgb[2], 0.6f * getAlpha())); g2.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); g2.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2); } private void drawText(Graphics2D g2, int size, float opacity) { Composite oldComposite = g2.getComposite(); float preAlpha = 1.0f; if (oldComposite instanceof AlphaComposite && ((AlphaComposite) oldComposite).getRule() == AlphaComposite.SRC_OVER) { preAlpha = ((AlphaComposite) oldComposite).getAlpha(); } g2.setFont(getFont()); FontMetrics metrics = g2.getFontMetrics(); int ascent = metrics.getAscent(); int heightDiff = (metrics.getHeight() - ascent) / 2; g2.setColor(Color.BLACK); double tx = 2.0; double ty = 2.0 + heightDiff - size; g2.translate(tx, ty); for (int i = -size; i <= size; i++) { for (int j = -size; j <= size; j++) { double distance = i * i + j * j; float alpha = opacity; if (distance > 0.0d) { alpha = (float) (1.0f / ((distance * size) * opacity)); } alpha *= preAlpha; if (alpha > 1.0f) { alpha = 1.0f; } g2.setComposite(AlphaComposite.SrcOver.derive(alpha)); g2.drawString(title, i + size, j + size + ascent); } } g2.setComposite(oldComposite); g2.setColor(Color.WHITE); g2.drawString(title, size, size + ascent); g2.translate(-tx, -ty); } } private class Locator extends MouseAdapter { private Point startPoint; @Override public void mousePressed(MouseEvent e) { startPoint = e.getPoint(); SwingUtilities.convertPointToScreen(startPoint, (Component) e.getSource()); } @Override public void mouseReleased(MouseEvent e) { VistaSearchDialog.this.setCursor(Cursor.getDefaultCursor()); } @Override public void mouseDragged(MouseEvent e) { Point point = e.getPoint(); SwingUtilities.convertPointToScreen(point, (Component) e.getSource()); int distance_x = point.x - startPoint.x; int distance_y = point.y - startPoint.y; VistaSearchDialog.this.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); Point location = VistaSearchDialog.this.getLocation(); Point oldLocation = (Point) location.clone(); location.x += distance_x; location.y += distance_y; VistaSearchDialog.this.setLocation(location); Rectangle clip = new Rectangle(oldLocation.x, oldLocation.y, VistaSearchDialog.this.getWidth(), VistaSearchDialog.this.getHeight()); clip.intersects(new Rectangle(location.x, location.y, VistaSearchDialog.this.getWidth(), VistaSearchDialog.this.getHeight())); VistaSearchDialog.this.getParent().repaint(clip.x, clip.y, clip.width, clip.height); startPoint = point; } }
} /*
* Copyright (c) 2007, Romain Guy * 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 the TimingFramework project 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. */
/**
* * @author Romain Guy */
class SearchPanel extends javax.swing.JPanel {
/** Creates new form SearchPanel */ public SearchPanel() { initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; jRadioButton2 = new javax.swing.JRadioButton(); jLabel1 = new javax.swing.JLabel(); jTextField1 = new javax.swing.JTextField(); jButton1 = new javax.swing.JButton(); jCheckBox1 = new javax.swing.JCheckBox(); jLabel2 = new javax.swing.JLabel(); jRadioButton1 = new javax.swing.JRadioButton(); jButton2 = new javax.swing.JButton(); jCheckBox2 = new javax.swing.JCheckBox(); jRadioButton3 = new javax.swing.JRadioButton(); jRadioButton2.setText("jRadioButton2"); jRadioButton2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jRadioButton2.setMargin(new java.awt.Insets(0, 0, 0, 0)); jLabel1.setText("Find what:"); jTextField1.setColumns(15); jButton1.setText("Search Next"); jButton1.setOpaque(false); jCheckBox1.setText("Match case"); jCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0)); jCheckBox1.setOpaque(false); jLabel2.setText("Direction:"); jRadioButton1.setSelected(true); jRadioButton1.setText("Up"); jRadioButton1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jRadioButton1.setMargin(new java.awt.Insets(0, 0, 0, 0)); jRadioButton1.setOpaque(false); jButton2.setText("Cancel"); jButton2.setOpaque(false); jButton2.setPreferredSize(new java.awt.Dimension(91, 23)); jCheckBox2.setText("Wrap"); jCheckBox2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox2.setMargin(new java.awt.Insets(0, 0, 0, 0)); jCheckBox2.setOpaque(false); jRadioButton3.setText("Down"); jRadioButton3.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jRadioButton3.setMargin(new java.awt.Insets(0, 0, 0, 0)); jRadioButton3.setOpaque(false); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .add(jLabel1) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jTextField1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE) .addContainerGap()) .add(layout.createSequentialGroup() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .add(jCheckBox1) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 26, Short.MAX_VALUE) .add(jLabel2)) .add(jCheckBox2)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jRadioButton3) .add(jRadioButton1)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(org.jdesktop.layout.GroupLayout.TRAILING, jButton2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 75, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(org.jdesktop.layout.GroupLayout.TRAILING, jButton1)) .add(23, 23, 23)))) ); layout.linkSize(new java.awt.ruponent[] {jButton1, jButton2}, org.jdesktop.layout.GroupLayout.HORIZONTAL); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel1) .add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(8, 8, 8) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jButton1) .add(jRadioButton1) .add(jLabel2) .add(jCheckBox1)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jButton2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 29, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(jRadioButton3) .add(jCheckBox2)) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JCheckBox jCheckBox1; private javax.swing.JCheckBox jCheckBox2; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JRadioButton jRadioButton1; private javax.swing.JRadioButton jRadioButton2; private javax.swing.JRadioButton jRadioButton3; private javax.swing.JTextField jTextField1; // End of variables declaration//GEN-END:variables
} /*
* Copyright (c) 2007, Romain Guy * 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 the TimingFramework project 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. */
/**
* * @author Romain Guy <romain.guy@mac.ru> */ class DummyPanel extends javax.swing.JPanel { /** Creates new form DummyPanel */ public DummyPanel() { initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); jTextField1 = new javax.swing.JTextField(); jScrollPane1 = new javax.swing.JScrollPane(); jTable1 = new javax.swing.JTable(); jScrollPane2 = new javax.swing.JScrollPane(); jTree1 = new javax.swing.JTree(); jScrollPane3 = new javax.swing.JScrollPane(); jList1 = new javax.swing.JList(); jScrollPane4 = new javax.swing.JScrollPane(); jList2 = new javax.swing.JList(); jLabel1.setText("Filter:"); jTable1.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null} }, new String [] { "Title 1", "Title 2", "Title 3", "Title 4" } )); jScrollPane1.setViewportView(jTable1); jScrollPane2.setViewportView(jTree1); jList1.setModel(new javax.swing.AbstractListModel() { String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); jScrollPane3.setViewportView(jList1); jList2.setModel(new javax.swing.AbstractListModel() { String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); jScrollPane4.setViewportView(jList2); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 181, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ruponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ruponentPlacement.RELATED) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE)) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 386, Short.MAX_VALUE))) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ruponentPlacement.RELATED) .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ruponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ruponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE))) .addComponent(jScrollPane2)) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel jLabel1; private javax.swing.JList jList1; private javax.swing.JList jList2; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JTable jTable1; private javax.swing.JTextField jTextField1; private javax.swing.JTree jTree1; // End of variables declaration//GEN-END:variables
} /*
* $Id: GraphicsUtilities.java,v 1.1 2007/01/16 18:31:51 gfx Exp $ * * Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy). * * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * Copyright (c) 2006 Romain Guy <romain.guy@mac.ru> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */
/**
*GraphicsUtilities
contains a set of tools to perform
* common graphics operations easily. These operations are divided into
* several themes, listed below.
Compatible Images
*Compatible images can, and should, be used to increase drawing * performance. This class provides a number of methods to load compatible * images directly from files or to convert existing images to compatibles * images.
*Creating Thumbnails
*This class provides a number of methods to easily scale down images. * Some of these methods offer a trade-off between speed and result quality and * shouuld be used all the time. They also offer the advantage of producing * compatible images, thus automatically resulting into better runtime * performance.
*All these methodes are both faster than
* {@link java.awt.Image#getScaledInstance(int, int, int)} and produce
* better-looking results than the various drawImage()
methods
* in {@link java.awt.Graphics}, which can be used for image scaling.
Image Manipulation
*This class provides two methods to get and set pixels in a buffered image. * These methods try to avoid unmanaging the image in order to keep good * performance.
* * @author Romain Guy <romain.guy@mac.ru> */
class GraphicsUtilities {
private GraphicsUtilities() { } // Returns the graphics configuration for the primary screen private static GraphicsConfiguration getGraphicsConfiguration() { return GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); } /***
Returns a new BufferedImage
using the same color model
* as the image passed as a parameter. The returned image is only compatible
* with the image passed as a parameter. This does not mean the returned
* image is compatible with the hardware.
* * @param image the reference image from which the color model of the new * image is obtained * @return a new*BufferedImage
, compatible with the color model * ofimage
*/ public static BufferedImage createColorModelCompatibleImage(BufferedImage image) { ColorModel cm = image.getColorModel(); return new BufferedImage(cm, cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), cm.isAlphaPremultiplied(), null); } /**
Returns a new compatible image with the same width, height and * transparency as the image specified as a parameter.
* * @see java.awt.Transparency * @see #createCompatibleImage(int, int) * @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) * @see #createCompatibleTranslucentImage(int, int) * @see #loadCompatibleImage(java.net.URL) * @see #toCompatibleImage(java.awt.image.BufferedImage) * @param image the reference image from which the dimension and the * transparency of the new image are obtained * @return a new compatible*BufferedImage
with the same * dimension and transparency asimage
*/ public static BufferedImage createCompatibleImage(BufferedImage image) { return createCompatibleImage(image, image.getWidth(), image.getHeight()); } /**
Returns a new compatible image of the specified width and height, and * the same transparency setting as the image specified as a parameter.
* * @see java.awt.Transparency * @see #createCompatibleImage(java.awt.image.BufferedImage) * @see #createCompatibleImage(int, int) * @see #createCompatibleTranslucentImage(int, int) * @see #loadCompatibleImage(java.net.URL) * @see #toCompatibleImage(java.awt.image.BufferedImage) * @param width the width of the new image * @param height the height of the new image * @param image the reference image from which the transparency of the new * image is obtained * @return a new compatible*BufferedImage
with the same * transparency asimage
and the specified dimension */ public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) { return getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency()); } /**
Returns a new opaque compatible image of the specified width and * height.
*
* @see #createCompatibleImage(java.awt.image.BufferedImage)
* @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
* @see #createCompatibleTranslucentImage(int, int)
* @see #loadCompatibleImage(java.net.URL)
* @see #toCompatibleImage(java.awt.image.BufferedImage)
* @param width the width of the new image
* @param height the height of the new image
* @return a new opaque compatible BufferedImage
of the
* specified width and height
*/
public static BufferedImage createCompatibleImage(int width, int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height);
}
/**
* Returns a new translucent compatible image of the specified width * and height.
*
* @see #createCompatibleImage(java.awt.image.BufferedImage)
* @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
* @see #createCompatibleImage(int, int)
* @see #loadCompatibleImage(java.net.URL)
* @see #toCompatibleImage(java.awt.image.BufferedImage)
* @param width the width of the new image
* @param height the height of the new image
* @return a new translucent compatible BufferedImage
of the
* specified width and height
*/
public static BufferedImage createCompatibleTranslucentImage(int width,
int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height,
Transparency.TRANSLUCENT);
}
/**
* Returns a new compatible image from a URL. The image is loaded from the * specified location and then turned, if necessary into a compatible * image.
*
* @see #createCompatibleImage(java.awt.image.BufferedImage)
* @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
* @see #createCompatibleImage(int, int)
* @see #createCompatibleTranslucentImage(int, int)
* @see #toCompatibleImage(java.awt.image.BufferedImage)
* @param resource the URL of the picture to load as a compatible image
* @return a new translucent compatible BufferedImage
of the
* specified width and height
* @throws java.io.IOException if the image cannot be read or loaded
*/
public static BufferedImage loadCompatibleImage(URL resource)
throws IOException {
BufferedImage image = ImageIO.read(resource);
return toCompatibleImage(image);
}
/**
* Return a new compatible image that contains a copy of the specified * image. This method ensures an image is compatible with the hardware, * and therefore optimized for fast blitting operations.
*
* @see #createCompatibleImage(java.awt.image.BufferedImage)
* @see #createCompatibleImage(java.awt.image.BufferedImage, int, int)
* @see #createCompatibleImage(int, int)
* @see #createCompatibleTranslucentImage(int, int)
* @see #loadCompatibleImage(java.net.URL)
* @param image the image to copy into a new compatible image
* @return a new compatible copy, with the
* same width and height and transparency and content, of image
*/
public static BufferedImage toCompatibleImage(BufferedImage image) {
if (image.getColorModel().equals(
getGraphicsConfiguration().getColorModel())) {
return image;
}
BufferedImage compatibleImage =
getGraphicsConfiguration().createCompatibleImage(
image.getWidth(), image.getHeight(),
image.getTransparency());
Graphics g = compatibleImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return compatibleImage;
}
/**
* Returns a thumbnail of a source image. newSize
defines
* the length of the longest dimension of the thumbnail. The other
* dimension is then computed according to the dimensions ratio of the
* original picture.
This method favors speed over quality. When the new size is less than * half the longest dimension of the source image, * {@link #createThumbnail(BufferedImage, int)} or * {@link #createThumbnail(BufferedImage, int, int)} should be used instead * to ensure the quality of the result without sacrificing too much * performance.
* * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int) * @see #createThumbnail(java.awt.image.BufferedImage, int) * @see #createThumbnail(java.awt.image.BufferedImage, int, int) * @param image the source image * @param newSize the length of the largest dimension of the thumbnail * @return a new compatible*BufferedImage
containing a * thumbnail ofimage
* @throws IllegalArgumentException ifnewSize
is larger than * the largest dimension ofimage
or <= 0 */ public static BufferedImage createThumbnailFast(BufferedImage image, int newSize) { float ratio; int width = image.getWidth(); int height = image.getHeight(); if (width > height) { if (newSize >= width) { throw new IllegalArgumentException("newSize must be lower than" + " the image width"); } else if (newSize <= 0) { throw new IllegalArgumentException("newSize must" + " be greater than 0"); } ratio = (float) width / (float) height; width = newSize; height = (int) (newSize / ratio); } else { if (newSize >= height) { throw new IllegalArgumentException("newSize must be lower than" + " the image height"); } else if (newSize <= 0) { throw new IllegalArgumentException("newSize must" + " be greater than 0"); } ratio = (float) height / (float) width; height = newSize; width = (int) (newSize / ratio); } BufferedImage temp = createCompatibleImage(image, width, height); Graphics2D g2 = temp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); g2.dispose(); return temp; } /**
Returns a thumbnail of a source image.
*This method favors speed over quality. When the new size is less than * half the longest dimension of the source image, * {@link #createThumbnail(BufferedImage, int)} or * {@link #createThumbnail(BufferedImage, int, int)} should be used instead * to ensure the quality of the result without sacrificing too much * performance.
* * @see #createThumbnailFast(java.awt.image.BufferedImage, int) * @see #createThumbnail(java.awt.image.BufferedImage, int) * @see #createThumbnail(java.awt.image.BufferedImage, int, int) * @param image the source image * @param newWidth the width of the thumbnail * @param newHeight the height of the thumbnail * @return a new compatible*BufferedImage
containing a * thumbnail ofimage
* @throws IllegalArgumentException ifnewWidth
is larger than * the width ofimage
or if code>newHeight</code> is larger * than the height ofimage
or if one of the dimensions * is <= 0 */ public static BufferedImage createThumbnailFast(BufferedImage image, int newWidth, int newHeight) { if (newWidth >= image.getWidth() || newHeight >= image.getHeight()) { throw new IllegalArgumentException("newWidth and newHeight cannot" + " be greater than the image" + " dimensions"); } else if (newWidth <= 0 || newHeight <= 0) { throw new IllegalArgumentException("newWidth and newHeight must" + " be greater than 0"); } BufferedImage temp = createCompatibleImage(image, newWidth, newHeight); Graphics2D g2 = temp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); g2.dispose(); return temp; } /**
Returns a thumbnail of a source image. newSize
defines
* the length of the longest dimension of the thumbnail. The other
* dimension is then computed according to the dimensions ratio of the
* original picture.
This method offers a good trade-off between speed and quality. * The result looks better than * {@link #createThumbnailFast(java.awt.image.BufferedImage, int)} when * the new size is less than half the longest dimension of the source * image, yet the rendering speed is almost similar.
* * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int) * @see #createThumbnailFast(java.awt.image.BufferedImage, int) * @see #createThumbnail(java.awt.image.BufferedImage, int, int) * @param image the source image * @param newSize the length of the largest dimension of the thumbnail * @return a new compatibleBufferedImage
containing a * thumbnail ofimage
* @throws IllegalArgumentException ifnewSize
is larger than * the largest dimension ofimage
or <= 0 */ public static BufferedImage createThumbnail(BufferedImage image, int newSize) { int width = image.getWidth(); int height = image.getHeight(); boolean isWidthGreater = width > height; if (isWidthGreater) { if (newSize >= width) { throw new IllegalArgumentException("newSize must be lower than" + " the image width"); } } else if (newSize >= height) { throw new IllegalArgumentException("newSize must be lower than" + " the image height"); } if (newSize <= 0) { throw new IllegalArgumentException("newSize must" + " be greater than 0"); } float ratioWH = (float) width / (float) height; float ratioHW = (float) height / (float) width; BufferedImage thumb = image; do { if (isWidthGreater) { width /= 2; if (width < newSize) { width = newSize; } height = (int) (width / ratioWH); } else { height /= 2; if (height < newSize) { height = newSize; } width = (int) (height / ratioHW); }
BufferedImage temp = createCompatibleImage(image, width, height); Graphics2D g2 = temp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); g2.dispose(); thumb = temp; } while (newSize != (isWidthGreater ? width : height)); return thumb; } /***
Returns a thumbnail of a source image.
*This method offers a good trade-off between speed and quality. * The result looks better than * {@link #createThumbnailFast(java.awt.image.BufferedImage, int)} when * the new size is less than half the longest dimension of the source * image, yet the rendering speed is almost similar.
* * @see #createThumbnailFast(java.awt.image.BufferedImage, int) * @see #createThumbnailFast(java.awt.image.BufferedImage, int, int) * @see #createThumbnail(java.awt.image.BufferedImage, int) * @param image the source image * @param newWidth the width of the thumbnail * @param newHeight the height of the thumbnail * @return a new compatible*BufferedImage
containing a * thumbnail ofimage
* @throws IllegalArgumentException ifnewWidth
is larger than * the width ofimage
or if code>newHeight</code> is larger * than the height ofimage or if one the dimensions is not > 0
*/ public static BufferedImage createThumbnail(BufferedImage image, int newWidth, int newHeight) { int width = image.getWidth(); int height = image.getHeight(); if (newWidth >= width || newHeight >= height) { throw new IllegalArgumentException("newWidth and newHeight cannot" + " be greater than the image" + " dimensions"); } else if (newWidth <= 0 || newHeight <= 0) { throw new IllegalArgumentException("newWidth and newHeight must" + " be greater than 0"); } BufferedImage thumb = image; do { if (width > newWidth) { width /= 2; if (width < newWidth) { width = newWidth; } } if (height > newHeight) { height /= 2; if (height < newHeight) { height = newHeight; } } BufferedImage temp = createCompatibleImage(image, width, height); Graphics2D g2 = temp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); g2.dispose(); thumb = temp; } while (width != newWidth || height != newHeight); return thumb; } /**
Returns an array of pixels, stored as integers, from a
* BufferedImage
. The pixels are grabbed from a rectangular
* area defined by a location and two dimensions. Calling this method on
* an image of type different from BufferedImage.TYPE_INT_ARGB
* and BufferedImage.TYPE_INT_RGB
will unmanage the image.
* * @param img the source image * @param x the x location at which to start grabbing pixels * @param y the y location at which to start grabbing pixels * @param w the width of the rectangle of pixels to grab * @param h the height of the rectangle of pixels to grab * @param pixels a pre-allocated array of pixels of size w*h; can be null * @return*pixels
if non-null, a new array of integers * otherwise * @throws IllegalArgumentException ispixels
is non-null and * of length < w*h */ public static int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { if (w == 0 || h == 0) { return new int[0]; } if (pixels == null) { pixels = new int[w * h]; } else if (pixels.length < w * h) { throw new IllegalArgumentException("pixels array must have a length" + " >= w*h"); } int imageType = img.getType(); if (imageType == BufferedImage.TYPE_INT_ARGB || imageType == BufferedImage.TYPE_INT_RGB) { Raster raster = img.getRaster(); return (int[]) raster.getDataElements(x, y, w, h, pixels); } // Unmanages the image return img.getRGB(x, y, w, h, pixels, 0, w); } /**
Writes a rectangular area of pixels in the destination
* BufferedImage
. Calling this method on
* an image of type different from BufferedImage.TYPE_INT_ARGB
* and BufferedImage.TYPE_INT_RGB
will unmanage the image.
*
* @param img the destination image
* @param x the x location at which to start storing pixels
* @param y the y location at which to start storing pixels
* @param w the width of the rectangle of pixels to store
* @param h the height of the rectangle of pixels to store
* @param pixels an array of pixels, stored as integers
* @throws IllegalArgumentException is pixels
is non-null and
* of length < w*h
*/
public static void setPixels(BufferedImage img,
int x, int y, int w, int h, int[] pixels) {
if (pixels == null || w == 0 || h == 0) {
return;
} else if (pixels.length < w * h) {
throw new IllegalArgumentException("pixels array must have a length" +
" >= w*h");
}
int imageType = img.getType();
if (imageType == BufferedImage.TYPE_INT_ARGB ||
imageType == BufferedImage.TYPE_INT_RGB) {
WritableRaster raster = img.getRaster();
raster.setDataElements(x, y, w, h, pixels);
} else {
// Unmanages the image
img.setRGB(x, y, w, h, pixels, 0, w);
}
}
} /*
* $Id: AbstractFilter.java,v 1.1 2007/01/16 18:31:50 gfx Exp $ * * Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy). * * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * Copyright (c) 2006 Romain Guy <romain.guy@mac.ru> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */
/**
*Provides an abstract implementation of the BufferedImageOp
* interface. This class can be used to created new image filters based
* on BufferedImageOp
.
* * @author Romain Guy <romain.guy@mac.ru> */ abstract class AbstractFilter implements BufferedImageOp { public abstract BufferedImage filter(BufferedImage src, BufferedImage dest); /** * {@inheritDoc} */ public Rectangle2D getBounds2D(BufferedImage src) { return new Rectangle(0, 0, src.getWidth(), src.getHeight()); } /** * {@inheritDoc} */ public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { if (destCM == null) { destCM = src.getColorModel(); } return new BufferedImage(destCM, destCM.createCompatibleWritableRaster( src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); } /** * {@inheritDoc} */ public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { return (Point2D) srcPt.clone(); } /** * {@inheritDoc} */ public RenderingHints getRenderingHints() { return null; }
} /*
* $Id: ColorTintFilter.java,v 1.2 2007/01/28 01:45:47 gfx Exp $ * * Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy). * * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * Copyright (c) 2006 Romain Guy <romain.guy@mac.ru> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */
/**
*A color tint filter can be used to mix a solid color to an image. The
* result is an image tinted by the specified color. The force of the effect
* can be controlled with the mixValue
, a number between 0.0 and
* 1.0 that can be seen as the percentage of the mix (0.0 does not affect the
* source image and 1.0 replaces all the pixels by the solid color).
The color of the pixels in the resulting image is computed as follows:
** cR = cS * (1 - mixValue) + cM * mixValue **
Definition of the parameters:
*-
*
cR
: color of the resulting pixel
* cS
: color of the source pixel
* cM
: the solid color to mix with the source image
* mixValue
: strength of the mix, a value between 0.0 and 1.0
*
* * @author Romain Guy <romain.guy@mac.ru> */
class ColorTintFilter extends AbstractFilter {
private final Color mixColor; private final float mixValue; private int[] preMultipliedRed; private int[] preMultipliedGreen; private int[] preMultipliedBlue; /***
Creates a new color mixer filter. The specified color will be used
* to tint the source image, with a mixing strength defined by
* mixValue
.
*
* @param mixColor the solid color to mix with the source image
* @param mixValue the strength of the mix, between 0.0 and 1.0; if the
* specified value lies outside this range, it is clamped
* @throws IllegalArgumentException if mixColor
is null
*/
public ColorTintFilter(Color mixColor, float mixValue) {
if (mixColor == null) {
throw new IllegalArgumentException("mixColor cannot be null");
}
this.mixColor = mixColor;
if (mixValue < 0.0f) {
mixValue = 0.0f;
} else if (mixValue > 1.0f) {
mixValue = 1.0f;
}
this.mixValue = mixValue;
int mix_r = (int) (mixColor.getRed() * mixValue);
int mix_g = (int) (mixColor.getGreen() * mixValue);
int mix_b = (int) (mixColor.getBlue() * mixValue);
// Since we use only lookup tables to apply the filter, this filter
// could be implemented as a LookupOp.
float factor = 1.0f - mixValue;
preMultipliedRed = new int[256];
preMultipliedGreen = new int[256];
preMultipliedBlue = new int[256];
for (int i = 0; i < 256; i++) {
int value = (int) (i * factor);
preMultipliedRed[i] = value + mix_r;
preMultipliedGreen[i] = value + mix_g;
preMultipliedBlue[i] = value + mix_b;
}
}
/**
* Returns the mix value of this filter.
* * @return the mix value, between 0.0 and 1.0 */ public float getMixValue() { return mixValue; } /***
Returns the solid mix color of this filter.
* * @return the solid color used for mixing */ public Color getMixColor() { return mixColor; } /** * {@inheritDoc} */ @Override public BufferedImage filter(BufferedImage src, BufferedImage dst) { if (dst == null) { dst = createCompatibleDestImage(src, null); } int width = src.getWidth(); int height = src.getHeight(); int[] pixels = new int[width * height]; GraphicsUtilities.getPixels(src, 0, 0, width, height, pixels); mixColor(pixels); GraphicsUtilities.setPixels(dst, 0, 0, width, height, pixels); return dst; } private void mixColor(int[] pixels) { for (int i = 0; i < pixels.length; i++) { int argb = pixels[i]; pixels[i] = (argb & 0xFF000000) | preMultipliedRed[(argb >> 16) & 0xFF] << 16 | preMultipliedGreen[(argb >> 8) & 0xFF] << 8 | preMultipliedBlue[argb & 0xFF]; } }
} /*
* $Id: DropShadowBorder.java,v 1.1 2007/01/16 18:31:49 gfx Exp $ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
* Implements a DropShadow for components. In general, the DropShadowBorder will * work with any rectangular components that do not have a default border installed * as part of the look and feel, or otherwise. For example, DropShadowBorder works * wonderfully with JPanel, but horribly with JComboBox. * * @author rbair */
class DropShadowBorder implements Border {
private static enum Position {TOP, TOP_LEFT, LEFT, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT, RIGHT, TOP_RIGHT}; private static final Map<Integer,Map<Position,BufferedImage>> CACHE = new HashMap<Integer,Map<Position,BufferedImage>>(); private final Color lineColor; private final int lineWidth; private final int shadowSize; private final float shadowOpacity; private final int cornerSize; private final boolean showTopShadow; private final boolean showLeftShadow; private final boolean showBottomShadow; private final boolean showRightShadow; public DropShadowBorder() { this(UIManager.getColor("Control"), 1, 5); } public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize) { this(lineColor, lineWidth, shadowSize, .5f, 12, false, false, true, true); } public DropShadowBorder(Color lineColor, int lineWidth, boolean showLeftShadow) { this(lineColor, lineWidth, 5, .5f, 12, false, showLeftShadow, true, true); } public DropShadowBorder(Color lineColor, int lineWidth, int shadowSize, float shadowOpacity, int cornerSize, boolean showTopShadow, boolean showLeftShadow, boolean showBottomShadow, boolean showRightShadow) { this.lineColor = lineColor; this.lineWidth = lineWidth; this.shadowSize = shadowSize; this.shadowOpacity = shadowOpacity; this.cornerSize = cornerSize; this.showTopShadow = showTopShadow; this.showLeftShadow = showLeftShadow; this.showBottomShadow = showBottomShadow; this.showRightShadow = showRightShadow; } /** * @inheritDoc */ public void paintBorder(Component c, Graphics graphics, int x, int y, int width, int height) { /* * 1) Get images for this border * 2) Paint the images for each side of the border that should be painted */ Map<Position,BufferedImage> images = getImages((Graphics2D)graphics); //compute the edges of the component -- not including the border
// Insets borderInsets = getBorderInsets(c); // int leftEdge = x + borderInsets.left; // int rightEdge = x + width - borderInsets.right; // int topEdge = y + borderInsets.top; // int bottomEdge = y + height - borderInsets.bottom;
Graphics2D g2 = (Graphics2D)graphics.create(); g2.setColor(lineColor); //The location and size of the shadows depends on which shadows are being //drawn. For instance, if the left & bottom shadows are being drawn, then //the left shadow extends all the way down to the corner, a corner is drawn, //and then the bottom shadow begins at the corner. If, however, only the //bottom shadow is drawn, then the bottom-left corner is drawn to the //right of the corner, and the bottom shadow is somewhat shorter than before. Point topLeftShadowPoint = null; if (showLeftShadow || showTopShadow) { topLeftShadowPoint = new Point(); if (showLeftShadow && !showTopShadow) { topLeftShadowPoint.setLocation(x, y + shadowSize); } else if (showLeftShadow && showTopShadow) { topLeftShadowPoint.setLocation(x, y); } else if (!showLeftShadow && showTopShadow) { topLeftShadowPoint.setLocation(x + shadowSize, y); } } Point bottomLeftShadowPoint = null; if (showLeftShadow || showBottomShadow) { bottomLeftShadowPoint = new Point(); if (showLeftShadow && !showBottomShadow) { bottomLeftShadowPoint.setLocation(x, y + height - shadowSize - shadowSize); } else if (showLeftShadow && showBottomShadow) { bottomLeftShadowPoint.setLocation(x, y + height - shadowSize); } else if (!showLeftShadow && showBottomShadow) { bottomLeftShadowPoint.setLocation(x + shadowSize, y + height - shadowSize); } } Point bottomRightShadowPoint = null; if (showRightShadow || showBottomShadow) { bottomRightShadowPoint = new Point(); if (showRightShadow && !showBottomShadow) { bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize - shadowSize); } else if (showRightShadow && showBottomShadow) { bottomRightShadowPoint.setLocation(x + width - shadowSize, y + height - shadowSize); } else if (!showRightShadow && showBottomShadow) { bottomRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y + height - shadowSize); } } Point topRightShadowPoint = null; if (showRightShadow || showTopShadow) { topRightShadowPoint = new Point(); if (showRightShadow && !showTopShadow) { topRightShadowPoint.setLocation(x + width - shadowSize, y + shadowSize); } else if (showRightShadow && showTopShadow) { topRightShadowPoint.setLocation(x + width - shadowSize, y); } else if (!showRightShadow && showTopShadow) { topRightShadowPoint.setLocation(x + width - shadowSize - shadowSize, y); } } g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); if (showLeftShadow) { Rectangle leftShadowRect = new Rectangle(x, topLeftShadowPoint.y + shadowSize, shadowSize, bottomLeftShadowPoint.y - topLeftShadowPoint.y - shadowSize); g2.drawImage(images.get(Position.LEFT), leftShadowRect.x, leftShadowRect.y, leftShadowRect.width, leftShadowRect.height, null); } if (showBottomShadow) { Rectangle bottomShadowRect = new Rectangle(bottomLeftShadowPoint.x + shadowSize, y + height - shadowSize, bottomRightShadowPoint.x - bottomLeftShadowPoint.x - shadowSize, shadowSize); g2.drawImage(images.get(Position.BOTTOM), bottomShadowRect.x, bottomShadowRect.y, bottomShadowRect.width, bottomShadowRect.height, null); } if (showRightShadow) { Rectangle rightShadowRect = new Rectangle(x + width - shadowSize, topRightShadowPoint.y + shadowSize, shadowSize, bottomRightShadowPoint.y - topRightShadowPoint.y - shadowSize); g2.drawImage(images.get(Position.RIGHT), rightShadowRect.x, rightShadowRect.y, rightShadowRect.width, rightShadowRect.height, null); } if (showTopShadow) { Rectangle topShadowRect = new Rectangle(topLeftShadowPoint.x + shadowSize, y, topRightShadowPoint.x - topLeftShadowPoint.x - shadowSize, shadowSize); g2.drawImage(images.get(Position.TOP), topShadowRect.x, topShadowRect.y, topShadowRect.width, topShadowRect.height, null); } if (showLeftShadow || showTopShadow) { g2.drawImage(images.get(Position.TOP_LEFT), topLeftShadowPoint.x, topLeftShadowPoint.y, null); } if (showLeftShadow || showBottomShadow) { g2.drawImage(images.get(Position.BOTTOM_LEFT), bottomLeftShadowPoint.x, bottomLeftShadowPoint.y, null); } if (showRightShadow || showBottomShadow) { g2.drawImage(images.get(Position.BOTTOM_RIGHT), bottomRightShadowPoint.x, bottomRightShadowPoint.y, null); } if (showRightShadow || showTopShadow) { g2.drawImage(images.get(Position.TOP_RIGHT), topRightShadowPoint.x, topRightShadowPoint.y, null); } g2.dispose(); } private Map<Position,BufferedImage> getImages(Graphics2D g2) { //first, check to see if an image for this size has already been rendered //if so, use the cache. Else, draw and save Map<Position,BufferedImage> images = CACHE.get(shadowSize); if (images == null) { images = new HashMap<Position,BufferedImage>(); /* * Do draw a drop shadow, I have to: * 1) Create a rounded rectangle * 2) Create a BufferedImage to draw the rounded rect in * 3) Translate the graphics for the image, so that the rectangle * is centered in the drawn space. The border around the rectangle * needs to be shadowWidth wide, so that there is space for the * shadow to be drawn. * 4) Draw the rounded rect as black, with an opacity of 50% * 5) Create the BLUR_KERNEL * 6) Blur the image * 7) copy off the corners, sides, etc into images to be used for * drawing the Border */ int rectWidth = cornerSize + 1; RoundRectangle2D rect = new RoundRectangle2D.Double(0, 0, rectWidth, rectWidth, cornerSize, cornerSize); int imageWidth = rectWidth + shadowSize * 2; BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(imageWidth, imageWidth); Graphics2D buffer = (Graphics2D)image.getGraphics(); buffer.setColor(new Color(0.0f, 0.0f, 0.0f, shadowOpacity)); buffer.translate(shadowSize, shadowSize); buffer.fill(rect); buffer.dispose(); float blurry = 1.0f / (float)(shadowSize * shadowSize); float[] blurKernel = new float[shadowSize * shadowSize]; for (int i=0; i<blurKernel.length; i++) { blurKernel[i] = blurry; } ConvolveOp blur = new ConvolveOp(new Kernel(shadowSize, shadowSize, blurKernel)); BufferedImage targetImage = GraphicsUtilities.createCompatibleTranslucentImage(imageWidth, imageWidth); ((Graphics2D)targetImage.getGraphics()).drawImage(image, blur, -(shadowSize/2), -(shadowSize/2)); int x = 1; int y = 1; int w = shadowSize; int h = shadowSize; images.put(Position.TOP_LEFT, getSubImage(targetImage, x, y, w, h)); x = 1; y = h; w = shadowSize; h = 1; images.put(Position.LEFT, getSubImage(targetImage, x, y, w, h)); x = 1; y = rectWidth; w = shadowSize; h = shadowSize; images.put(Position.BOTTOM_LEFT, getSubImage(targetImage, x, y, w, h)); x = cornerSize + 1; y = rectWidth; w = 1; h = shadowSize; images.put(Position.BOTTOM, getSubImage(targetImage, x, y, w, h)); x = rectWidth; y = x; w = shadowSize; h = shadowSize; images.put(Position.BOTTOM_RIGHT, getSubImage(targetImage, x, y, w, h)); x = rectWidth; y = cornerSize + 1; w = shadowSize; h = 1; images.put(Position.RIGHT, getSubImage(targetImage, x, y, w, h)); x = rectWidth; y = 1; w = shadowSize; h = shadowSize; images.put(Position.TOP_RIGHT, getSubImage(targetImage, x, y, w, h)); x = shadowSize; y = 1; w = 1; h = shadowSize; images.put(Position.TOP, getSubImage(targetImage, x, y, w, h)); image.flush(); CACHE.put(shadowSize, images); } return images; } /** * Returns a new BufferedImage that represents a subregion of the given * BufferedImage. (Note that this method does not use * BufferedImage.getSubimage(), which will defeat image acceleration * strategies on later JDKs.) */ private BufferedImage getSubImage(BufferedImage img, int x, int y, int w, int h) { BufferedImage ret = GraphicsUtilities.createCompatibleTranslucentImage(w, h); Graphics2D g2 = ret.createGraphics(); g2.drawImage(img, 0, 0, w, h, x, y, x+w, y+h, null); g2.dispose(); return ret; } /** * @inheritDoc */ public Insets getBorderInsets(Component c) { int top = showTopShadow ? lineWidth + shadowSize : lineWidth; int left = showLeftShadow ? lineWidth + shadowSize : lineWidth; int bottom = showBottomShadow ? lineWidth + shadowSize : lineWidth; int right = showRightShadow ? lineWidth + shadowSize : lineWidth; return new Insets(top, left, bottom, right); } /** * @inheritDoc */ public boolean isBorderOpaque() { return false; } public boolean isShowTopShadow() { return showTopShadow; } public boolean isShowLeftShadow() { return showLeftShadow; } public boolean isShowRightShadow() { return showRightShadow; } public boolean isShowBottomShadow() { return showBottomShadow; } public int getLineWidth() { return lineWidth; } public Color getLineColor() { return lineColor; } public int getShadowSize() { return shadowSize; } public float getShadowOpacity() { return shadowOpacity; } public int getCornerSize() { return cornerSize; }
}
</source>