/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.tools.gui.historybutton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import de.cismet.tools.gui.JPopupMenuButton;
/**
* The implementation of the JHistoryButton. See a short <a href="http://flexo.cismet.de/gadgets/JHistory/">description
* and demo</a> on the website.
*
* <p>License: <a href="http://www.gnu.org/copyleft/lesser.html#TOC1">GNU LESSER GENERAL PUBLIC LICENSE</a><br>
* <img src="http://opensource.org/trademarks/osi-certified/web/osi-certified-60x50.gif"> <img
* src="http://opensource.org/trademarks/opensource/web/opensource-55x48.gif"></p>
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public class JHistoryButton extends JPopupMenuButton implements ActionListener, HistoryModelListener {
//~ Static fields/initializers ---------------------------------------------
public static final int DIRECTION_FORWARD = 1;
public static final int DIRECTION_BACKWARD = 2;
public static final int ICON_SIZE_16 = 4;
public static final int ICON_SIZE_22 = 8;
public static final int ICON_SIZE_32 = 16;
public static final int ICON_SIZE_64 = 32;
public static final int ICON_SIZE_128 = 64;
//~ Instance fields --------------------------------------------------------
private int maxHistoryMenuLength = 10;
private JPopupMenu popupMenu = new JPopupMenu();
private int direction = 1;
private boolean localEnabled = true;
private HistoryModel historyModel = null;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new instance of JHistoryButton.
*/
public JHistoryButton() {
this(true);
}
/**
* Creates a new instance of JHistoryButton.
*
* @param showPopupMenu do not use the popup menu funtionality
*/
public JHistoryButton(final boolean showPopupMenu) {
super(showPopupMenu);
super.setEnabled(false);
this.setPopupMenu(popupMenu);
this.addActionListener(this);
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param direction DOCUMENT ME!
* @param iconSize DOCUMENT ME!
* @param model DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public static JHistoryButton getDefaultJHistoryButton(final int direction,
final int iconSize,
final HistoryModel model) {
final JHistoryButton ret = new JHistoryButton();
ret.setDirection(direction);
ret.setHistoryModel(model);
final String ressourcePath = "/de/cismet/tools/gui/historybutton/res/"; // NOI18N
final String forward = "forward"; // NOI18N
final String back = "back"; // NOI18N
String name;
final String filetype = ".png"; // NOI18N
if (direction == DIRECTION_FORWARD) {
name = forward;
} else {
name = back;
}
switch (iconSize) {
case ICON_SIZE_16: {
ret.setIcon(new javax.swing.ImageIcon(
ret.getClass().getResource(ressourcePath + name + "16" + filetype))); // NOI18N
break;
}
case ICON_SIZE_22: {
ret.setIcon(new javax.swing.ImageIcon(
ret.getClass().getResource(ressourcePath + name + "22" + filetype))); // NOI18N
break;
}
case ICON_SIZE_32: {
ret.setIcon(new javax.swing.ImageIcon(
ret.getClass().getResource(ressourcePath + name + "32" + filetype))); // NOI18N
break;
}
case ICON_SIZE_64: {
ret.setIcon(new javax.swing.ImageIcon(
ret.getClass().getResource(ressourcePath + name + "64" + filetype))); // NOI18N
break;
}
case ICON_SIZE_128: {
ret.setIcon(new javax.swing.ImageIcon(
ret.getClass().getResource(ressourcePath + name + "128" + filetype))); // NOI18N
break;
}
}
return ret;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public HistoryModel getHistoryModel() {
return historyModel;
}
/**
* DOCUMENT ME!
*
* @param historyModel DOCUMENT ME!
*/
public void setHistoryModel(final HistoryModel historyModel) {
this.historyModel = historyModel;
historyModel.addHistoryModelListener(this);
setEnabled(localEnabled);
if (localEnabled && (direction == DIRECTION_FORWARD)) {
forwardStatusChanged();
} else {
backStatusChanged();
}
}
@Override
public void historyChanged() {
}
@Override
public void forwardStatusChanged() {
// you have to check whether the component is enabled
// if you have to disable the component due to history reasons
// you have to modify the super component directly
// otherwise there would be no chance to disable the component permanently
if (localEnabled && (direction == DIRECTION_FORWARD)) {
if (historyModel.isForwardPossible()) {
setEnabled(true);
final Vector poss = historyModel.getForwardPossibilities();
refreshPopup(poss);
} else {
super.setEnabled(false);
}
}
}
@Override
public void backStatusChanged() {
// you have to check whether the component is enabled
// if you have to disable the component due to history reasons
// you have to modify the super component directly
// otherwise there would be no chance to disable the component permanently
if (localEnabled && (direction == DIRECTION_BACKWARD)) {
if (historyModel.isBackPossible()) {
setEnabled(true);
final Vector poss = historyModel.getBackPossibilities();
refreshPopup(poss);
} else {
super.setEnabled(false);
refreshPopup(null);
}
}
}
/**
* DOCUMENT ME!
*
* @param possibilities DOCUMENT ME!
*/
private void refreshPopup(Vector possibilities) {
if (showPopupMenu) {
if (possibilities == null) {
possibilities = new Vector();
}
popupMenu.removeAll();
for (int i = possibilities.size() - 1; i >= 0; --i) {
final Object o = possibilities.get(i);
final JHistoryMenuItem item = new JHistoryMenuItem(o, possibilities.size() - i);
popupMenu.add(item);
item.addActionListener(this);
}
if (possibilities.size() > maxHistoryMenuLength) {
final int tooMuch = possibilities.size() - maxHistoryMenuLength;
for (int i = 0; i < tooMuch; ++i) {
popupMenu.remove(possibilities.size() - 1 - i);
}
}
}
}
@Override
public void setEnabled(final boolean enabled) {
localEnabled = enabled;
if (historyModel != null) {
super.setEnabled(localEnabled);
} else {
super.setEnabled(false);
}
}
@Override
public void actionPerformed(final java.awt.event.ActionEvent e) {
if ((e != null) && (e.getSource() instanceof JHistoryMenuItem)) {
final JHistoryMenuItem source = (JHistoryMenuItem)e.getSource();
for (int i = 0; i < (source.getPosition() - 1); ++i) {
if (direction == DIRECTION_BACKWARD) {
historyModel.back(false);
} else if (direction == DIRECTION_FORWARD) {
historyModel.forward(false);
}
}
fireActionPerformed(new ActionEvent(this, 0, "JHistoryButtonMenuActionPerformed")); // NOI18N
} else if ((e != null) && (e.getSource() instanceof JHistoryButton)) { // &&e.getActionCommand()!="JHistoryButtonMenuActionPerformed"
Object o = null;
if (direction == DIRECTION_BACKWARD) {
o = historyModel.back(true);
} else if (direction == DIRECTION_FORWARD) {
o = historyModel.forward(true);
}
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getDirection() {
return direction;
}
/**
* DOCUMENT ME!
*
* @param direction DOCUMENT ME!
*
* @beaninfo
* attribute: visualUpdate true
* bound: true
* description: The alignment of the label's content along the X axis.
* enum: DIRECTION_FORWARD JHistoryButton.DIRECTION_FORWARD
* DIRECTION_BACKWARD JHistoryButton.DIRECTION_BACKWARD
*/
public void setDirection(final int direction) {
this.direction = direction;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public JLabel getJHistoryLabel() {
return new JHistoryLabel();
}
@Override
public void historyActionPerformed() {
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class JHistoryLabel extends JLabel implements HistoryModelListener {
//~ Instance fields ----------------------------------------------------
String text;
//~ Constructors -------------------------------------------------------
/**
* Creates a new JHistoryLabel object.
*/
public JHistoryLabel() {
historyModel.addHistoryModelListener(this);
}
//~ Methods ------------------------------------------------------------
@Override
public void historyChanged() {
text = historyModel.getCurrentElement().toString();
setText(text);
}
@Override
public void forwardStatusChanged() {
}
@Override
public void backStatusChanged() {
}
@Override
public String getText() {
if ((text != null) && (text.length() > 0)) {
return text;
} else {
historyChanged();
return text;
}
}
@Override
public void historyActionPerformed() {
}
}
}