com.jidesoft.swing.LegacyTristateCheckBox Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jide-oss Show documentation
Show all versions of jide-oss Show documentation
JIDE Common Layer (Professional Swing Components)
package com.jidesoft.swing;
import com.jidesoft.plaf.LookAndFeelFactory;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ActionMapUIResource;
import java.awt.event.*;
/**
* This class is deprecated and replaced by {@link TristateCheckBox}. We will no longer provide support for this
* class.
*
* Maintenance tip - There were some tricks to getting this code working:
*
* 1. You have to overwrite addMouseListener() to do nothing 2. You have to add a mouse event on mousePressed by calling
* super.addMouseListener() 3. You have to replace the UIActionMap for the keyboard event "pressed" with your own one.
* 4. You have to remove the UIActionMap for the keyboard event "released". 5. You have to grab focus when the next
* state is entered, otherwise clicking on the component won't get the focus. 6. You have to make a TristateDecorator as
* a button model that wraps the original button model and does state management.
*
* To get notified for the state change, usually people use itemChange listener for a regular JCheckBox but for
* TristateCheckBox, it doesn't work very well. It would be better to use addPropertyChangeListener on PROPERTY_STATE
* property. It will be fired whenever the state is changed.
*
* @author Dr. Heinz M. Kabutz
* @author JIDE Software
* @deprecated Replaced by {@link TristateCheckBox}.
*/
public class LegacyTristateCheckBox extends JCheckBox {
/**
* Property name for the state. Listen to this property change if you want to get notified for the state change.
*/
public final static String PROPERTY_STATE = "state";
/**
* This is a type-safe enumerated type
*/
public static class State {
private State() {
}
}
public static final State NOT_SELECTED = new State();
public static final State SELECTED = new State();
public static final State DONT_CARE = new State();
private final TristateDecorator model;
public LegacyTristateCheckBox(String text, Icon icon, State initial) {
super(text, icon);
// Add a listener for when the mouse is pressed
super.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
grabFocus();
setState(getNextState(getState()));
}
});
// Reset the keyboard action map
ActionMap map = new ActionMapUIResource();
map.put("pressed", new AbstractAction() {
private static final long serialVersionUID = 7121802319351334948L;
public void actionPerformed(ActionEvent e) {
grabFocus();
setState(getNextState(getState()));
}
});
map.put("released", null);
SwingUtilities.replaceUIActionMap(this, map);
// set the model to the adapted model
model = new TristateDecorator(getModel());
setModel(model);
setState(initial);
}
public LegacyTristateCheckBox(String text, State initial) {
this(text, null, initial);
}
public LegacyTristateCheckBox(String text) {
this(text, DONT_CARE);
}
public LegacyTristateCheckBox() {
this(null);
}
/**
* No one may add mouse listeners, not even Swing!
*/
@Override
public void addMouseListener(MouseListener l) {
}
/**
* Set the new state to either SELECTED, NOT_SELECTED or DONT_CARE. If state == null, it is treated as DONT_CARE.
*
* @param state the new state
*/
public void setState(State state) {
State old = model.getState();
model.setState(state);
if (old != state) {
firePropertyChange(PROPERTY_STATE, old, state);
}
// for Synthetica
if (LookAndFeelFactory.isSyntheticaLnfInstalled()
&& (UIManager.getLookAndFeel().getClass().getName().startsWith(LookAndFeelFactory.SYNTHETICA_LNF_PREFIX) || LookAndFeelFactory.isLnfInUse(LookAndFeelFactory.SYNTHETICA_LNF))) {
if (state == DONT_CARE) {
setName("HalfSelected");
}
else {
setName("");
}
}
}
/**
* Return the current state, which is determined by the selection status of the model.
*
* @return the current state.
*/
public State getState() {
return model.getState();
}
@Override
public void setSelected(boolean b) {
if (b) {
setState(SELECTED);
}
else {
setState(NOT_SELECTED);
}
}
/**
* Exactly which Design Pattern is this? Is it an Adapter, a Proxy or a Decorator? In this case, my vote lies with
* the Decorator, because we are extending functionality and "decorating" the original model with a more powerful
* model.
*/
private class TristateDecorator implements ButtonModel {
private final ButtonModel other;
private State _state;
private TristateDecorator(ButtonModel other) {
this.other = other;
}
private void setState(State state) {
if (state == NOT_SELECTED) {
other.setArmed(false);
setPressed(false);
setSelected(false);
}
else if (state == SELECTED) {
other.setArmed(false);
setPressed(false);
setSelected(true);
}
else { // either "null" or DONT_CARE
other.setArmed(true);
setPressed(true);
setSelected(true);
}
_state = state;
}
/*
* The current state is embedded in the selection / armed state of the model.
*
* We return the SELECTED state when the checkbox is selected but not armed, DONT_CARE state when the checkbox is selected and armed (grey) and NOT_SELECTED when the checkbox is deselected.
*/
private State getState() {
return _state == null ? DONT_CARE : _state;
// if (isSelected() && !isArmed()) {
// // normal black tick
// return SELECTED;
// }
// else if (isSelected() && isArmed()) {
// // don't care grey tick
// return DONT_CARE;
// }
// else {
// // normal deselected
// return NOT_SELECTED;
// }
}
/**
* Filter: No one may change the armed status except us.
*/
public void setArmed(boolean b) {
}
/**
* We disable focusing on the component when it is not enabled.
*/
public void setEnabled(boolean b) {
setFocusable(b);
other.setEnabled(b);
}
/**
* All these methods simply delegate to the "other" model that is being decorated.
*/
public boolean isArmed() {
return other.isArmed();
}
public boolean isSelected() {
return other.isSelected();
}
public boolean isEnabled() {
return other.isEnabled();
}
public boolean isPressed() {
return other.isPressed();
}
public boolean isRollover() {
return other.isRollover();
}
public void setSelected(boolean b) {
other.setSelected(b);
}
public void setPressed(boolean b) {
other.setPressed(b);
}
public void setRollover(boolean b) {
other.setRollover(b);
}
public void setMnemonic(int key) {
other.setMnemonic(key);
}
public int getMnemonic() {
return other.getMnemonic();
}
public void setActionCommand(String s) {
other.setActionCommand(s);
}
public String getActionCommand() {
return other.getActionCommand();
}
public void setGroup(ButtonGroup group) {
other.setGroup(group);
}
public void addActionListener(ActionListener l) {
other.addActionListener(l);
}
public void removeActionListener(ActionListener l) {
other.removeActionListener(l);
}
public void addItemListener(ItemListener l) {
other.addItemListener(l);
}
public void removeItemListener(ItemListener l) {
other.removeItemListener(l);
}
public void addChangeListener(ChangeListener l) {
other.addChangeListener(l);
}
public void removeChangeListener(ChangeListener l) {
other.removeChangeListener(l);
}
public Object[] getSelectedObjects() {
return other.getSelectedObjects();
}
}
/**
* We rotate between NOT_SELECTED, SELECTED and DONT_CARE. Subclass can override this method to tell the check box
* what next state is. Here is the default implementation.
*
* if (current == NOT_SELECTED) {
* return SELECTED;
* }
* else if (current == SELECTED) {
* return DONT_CARE;
* }
* else {
* return NOT_SELECTED;
* }
*
*
* @param current the current state
* @return the next state of the current state.
*/
protected State getNextState(State current) {
if (current == NOT_SELECTED) {
return SELECTED;
}
else if (current == SELECTED) {
return DONT_CARE;
}
else /*if (current == DONT_CARE)*/ {
return NOT_SELECTED;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy