/**
* ThisTime 2.0 (2008-03-30)
* Copyright 2007 Zach Scrivena
* zachscrivena@gmail.com
* http://thistime.sourceforge.net/
*
* Simple clock and timer program.
*
* TERMS AND CONDITIONS:
* 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 3 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thistime;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* Perform miscellaneous Swing-related operations.
*/
class SwingManipulator
{
/**
* Add a standard editing popup menu (Cut, Copy, Paste, Select All)
* to the specified text fields.
*
* @param fields
* array of JTextField's for which to add the popup menu
*/
static void addStandardEditingPopupMenu(
final JTextField[] fields)
{
final JPopupMenu popupMenu = new JPopupMenu();
/* text fields popup menu: "Cut" */
final JMenuItem cutMenuItem = new JMenuItem("Cut", 't');
cutMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
final Component c = popupMenu.getInvoker();
if (c instanceof JTextField)
{
((JTextField) c).cut();
}
}
});
popupMenu.add(cutMenuItem);
/* text fields popup menu: "Copy" */
final JMenuItem copyMenuItem = new JMenuItem("Copy", 'C');
copyMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
final Component c = popupMenu.getInvoker();
if (c instanceof JTextField)
{
((JTextField) c).copy();
}
}
});
popupMenu.add(copyMenuItem);
/* text fields popup menu: "Paste" */
final JMenuItem pasteMenuItem = new JMenuItem("Paste", 'P');
pasteMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
final Component c = popupMenu.getInvoker();
if (c instanceof JTextField)
{
((JTextField) c).paste();
}
}
});
popupMenu.add(pasteMenuItem);
popupMenu.addSeparator();
/* text fields popup menu: "Select All" */
final JMenuItem selectAllMenuItem = new JMenuItem("Select All", 'A');
selectAllMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
final Component c = popupMenu.getInvoker();
if (c instanceof JTextField)
{
((JTextField) c).selectAll();
}
}
});
popupMenu.add(selectAllMenuItem);
/* add mouse listeners to the specified fields */
for (final JTextField f : fields)
{
f.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
processMouseEvent(e);
}
@Override
public void mouseReleased(MouseEvent e)
{
processMouseEvent(e);
}
private void processMouseEvent(MouseEvent e)
{
if (e.isPopupTrigger())
{
popupMenu.show(e.getComponent(), e.getX(), e.getY());
popupMenu.setInvoker(f);
}
}
});
}
}
/**
* Wrapper for the getText() method of a JTextField that always returns a String.
*
* @param f
* JTextField object on which to call getText()
* @return
* String text in the JTextField
*/
static String getTextJTextField(
final JTextField f)
{
try
{
return f.getText();
}
catch (NullPointerException e)
{
return "";
}
}
/**
* Wrapper for the getPassword() method of a JPasswordField that always returns a char array.
*
* @param f
* JPasswordField object on which to call getPassword()
* @return
* char array representing the text in the JPasswordField
*/
static char[] getPasswordJPasswordField(
final JPasswordField f)
{
try
{
return f.getPassword();
}
catch (NullPointerException e)
{
return new char[0];
}
}
/**
* Update progress bar.
*
* @param progressBar
* JProgressBar object to be updated
* @param text
* Text string to be shown on the progress bar
* @param percent
* Percentage of the task completed (if less than 0 or more than 100,
* then indeterminate mode is used)
*/
static void updateProgressBar(
final JProgressBar progressBar,
final String text,
final int percent)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
if ((percent < 0) || (percent > 100))
{
/* indeterminate mode */
progressBar.setString(text);
progressBar.setIndeterminate(true);
}
else
{
/* determinate mode */
progressBar.setValue(percent);
progressBar.setString(text);
progressBar.setIndeterminate(false);
}
}
});
}
/**
* Convenience method to display a JOptionPane option dialog with a label
* and text area.
*
* @param parentComponent
* Frame in which the dialog is to be displayed; if null, or if the
* parentComponent has no Frame, then a default Frame is used
* @param label
* Label String to be displayed
* @param text
* Text String to be displayed in the text area
* @param rows
* Height of the text area in number of rows
* @param title
* Title String for the dialog
* @param optionType
* Options available for the dialog: JOptionPane.DEFAULT_OPTION,
* YES_NO_OPTION, YES_NO_CANCEL_OPTION, or OK_CANCEL_OPTION
* @param messageType
* Type of message; primarily used to determine the icon from the
* pluggable Look and Feel: JOptionPane.ERROR_MESSAGE,
* INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE,
* or PLAIN_MESSAGE
* @param icon
* Icon to be displayed
* @param Object[] options
* Array of objects indicating the possible choices the user can make;
* if the objects are components, they are rendered properly;
* non-String objects are rendered using their toString methods;
* if this parameter is null, the options are determined by the
* Look and Feel
* @param initialValue
* Index of the default selection for the dialog; meaningful
* only if options is used; ignored if negative
* @return
* Index of the option chosen by the user, or JOptionPane.CLOSED_OPTION
* if the user closed the dialog
* @throw HeadlessException
* If GraphicsEnvironment.isHeadless returns true
*/
static int showOptionTextDialog(
final Component parentComponent,
final String label,
final String text,
final int rows,
final String title,
final int optionType,
final int messageType,
final Icon icon,
final Object[] options,
final int initialValue) throws HeadlessException
{
class ChoiceDialog implements Runnable
{
/**
* Index of the option chosen by the user, or CLOSED_OPTION if
* the user closed the dialog.
*/
public int choiceIndex;
@Override
public void run()
{
Object initialOption = null;
if ((options != null) && (initialValue >= 0) && (initialValue < options.length))
initialOption = options[initialValue];
final JPanel panel = new JPanel(new BorderLayout());
panel.add(new JLabel(label + ":"), BorderLayout.NORTH);
final JTextArea textArea = new JTextArea(text, rows, 50);
textArea.setEditable(false);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setToolTipText(label);
textArea.setFont(new Font(
Font.DIALOG,
Font.PLAIN,
textArea.getFont().getSize() - 2));
panel.add(new JScrollPane(
textArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),
BorderLayout.CENTER);
choiceIndex = JOptionPane.showOptionDialog(
parentComponent,
panel,
title,
optionType,
messageType,
icon,
options,
initialOption);
}
}
final ChoiceDialog r = new ChoiceDialog();
if (SwingUtilities.isEventDispatchThread())
{
r.run();
}
else
{
try
{
SwingUtilities.invokeAndWait(r);
}
catch (Exception e)
{
/* ignore */
}
}
return r.choiceIndex;
}
/**
* Display a modal error dialog.
*
* @param parent
* Parent component of this dialog
* @param title
* Title of dialog
* @param message
* Error message to be displayed
*/
static void showErrorDialog(
final Component parent,
final String title,
final String message)
{
showOptionTextDialog(
parent,
"An error has occurred",
message,
5,
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
null,
0);
}
/**
* Display a modal warning dialog.
*
* @param parent
* Parent component of this dialog
* @param title
* Title of dialog
* @param message
* Warning message to be displayed
*/
static void showWarningDialog(
final Component parent,
final String title,
final String message)
{
showOptionTextDialog(
parent,
"A warning has been issued",
message,
5,
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
null,
0);
}
/**
* Display a modal information dialog.
*
* @param parent
* Parent component of this dialog
* @param title
* Title of dialog
* @param label
* Label string to be displayed
* @param message
* Information message to be displayed
* @param rows
* Height of the text area in number of rows
*/
static void showInfoDialog(
final Component parent,
final String title,
final String label,
final String message,
final int rows)
{
showOptionTextDialog(
parent,
label,
message,
rows,
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
null,
0);
}
}