/*
Wotonomy: OpenStep design patterns for pure Java applications.
Copyright (C) 2000 Blacksmith, Inc.
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, see http://www.gnu.org
*/
package net.wotonomy.ui.swing.components;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.lang.reflect.Method;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
/**
* StatusButtonPanel extends ButtonPanel to provide a space to display status
* messages in a consistent manner.
*
* Messages are erased after a certain predefined interval, defaulting to 10
* seconds.
*
* @author michael@mpowers.net
* @author $Author: cgruber $
* @version $Revision: 904 $
*/
public class StatusButtonPanel extends ButtonPanel {
/**
* This is the action command to all listeners when the status text is changed.
*/
public static final String STATUS_CHANGED = "STATUS_CHANGED";
// note: weirdness happens if you initialize
// this variable. Because it is set by initLayout
// and initLayout is called by the superclass constructor,
// this variable would get initialized after initLayout
// is called...
protected Component statusComponent; // = null;
protected Timer timer = null;
protected int interval = 10000; // adjust as needed
/**
* Constructs a StatusButtonPanel. Three buttons are created so the panel is
* filled when used in a GUI-builder environment.
*/
public StatusButtonPanel() {
super();
setupTimer();
}
/**
* Constructs a StatusButtonPanel using specified buttons.
*
* @param buttonList An array containing the strings to be used in labeling the
* buttons.
*/
public StatusButtonPanel(String[] buttonList) {
super(buttonList);
setupTimer();
}
/**
* Initializes the timer instance variable.
*/
protected void setupTimer() {
timer = new Timer(interval, this);
timer.addActionListener(this);
timer.setRepeats(false);
timer.start();
}
/**
* Returns the number of milliseconds before the status message is cleared. The
* default is 10000.
*
* @return The current delay interval in milliseconds.
*/
public int getDelayInterval() {
return interval;
}
/**
* Sets the number of milliseconds before the status message is cleared.
*
* @param millis The new delay interval in milliseconds.
*/
public void setDelayInterval(int millis) {
interval = millis;
timer.setDelay(interval);
}
/**
* Returns the visual component used to display the status.
*
* @return A component used for displaying status.
*/
public Component getStatusComponent() {
return statusComponent;
}
/**
* Receives ActionEvents from the internal timer.
*
* @param e The action event in question.
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == timer) {
setText("");
return;
}
// otherwise continue with superclass implementation
super.actionPerformed(e);
}
/**
* This method is responsible for the initial layout of the panel. Subclasses
* can implement different layouts, but this method is responsible for
* initializing buttonPanelLayout to a valid layout manager and setting this
* panel to use it. This method must should initialize statusComponent to a
* component that ideally has get/setText methods, although this is not
* required.
*/
protected void initLayout() {
statusComponent = new JTextField();
JTextField textField = (JTextField) statusComponent;
textField.setColumns(20);
textField.setBackground(getBackground());
textField.setEditable(false);
// statusComponent = new PickListPanel(); // for testing
this.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = GridBagConstraints.RELATIVE;
gbc.gridy = GridBagConstraints.RELATIVE;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 0.0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 5, 0, 10);
gbc.ipadx = 0;
gbc.ipady = 0;
//1.2 new GridBagConstraints(GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
//1.2 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 10), 0, 0 );
this.add(statusComponent, gbc);
buttonContainer = new JPanel();
buttonPanelLayout = new BetterFlowLayout();
buttonContainer.setLayout(buttonPanelLayout);
buttonPanelLayout.setAlignment(BetterFlowLayout.RIGHT);
((BetterFlowLayout) buttonPanelLayout).setWidthUniform(true);
gbc.weightx = 0.0;
gbc.insets = new Insets(0, 0, 0, 0);
this.add(buttonContainer, gbc);
}
/**
* Sets the text to appear in the status area.
*
* @param newText A string to appear in the status area. Nulls are allowed.
*/
public void setText(String newText) {
// TODO: should use property introspection instead
// use reflection to call the "setText" method, if any.
try {
Class c = statusComponent.getClass();
Method m = c.getMethod("setText", new Class[] { new String().getClass() });
m.invoke(statusComponent, new Object[] { newText });
broadcastEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, STATUS_CHANGED));
statusComponent.paint(statusComponent.getGraphics());
} catch (Exception exc) {
// "setText" method does not exist; do nothing.
}
// if non-empty string, start the timer
if (!"".equals(newText)) {
timer.restart();
}
}
/**
* Gets the text in the status area.
*
* @return The string being displayed in the status area.
*/
public String getText() {
// TODO: should use property introspection instead
String value = "";
// use reflection to call the "setText" method, if any.
try {
Class c = statusComponent.getClass();
Method m = c.getMethod("getText", (Class[]) null);
value = (String) m.invoke(statusComponent, (Object[]) null);
} catch (Exception exc) {
// "getText" method does not exist; do nothing.
}
return value;
}
// for testing
public static void main(String[] argv) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception exc) {
}
JFrame dialog = new JFrame();
BorderLayout bl = new BorderLayout(20, 20);
// StatusButtonPanel panel = new StatusButtonPanel();
// System.out.println( panel.statusComponent );
StatusButtonPanel panel = new StatusButtonPanel(new String[] { "Okay", "Cancel" });
dialog.getContentPane().setLayout(bl);
dialog.getContentPane().add(panel, BorderLayout.SOUTH);
dialog.setLocation(50, 50);
// dialog.setSize( 450, 150 );
dialog.pack();
dialog.setVisible(true);
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
panel.setAlignment(BetterFlowLayout.RIGHT);
// panel.getButton( "One" ).setEnabled( false );
panel.setText("File saved.");
System.out.println(panel.getText());
}
}