All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jidesoft.swing.LegacyTristateCheckBox Maven / Gradle / Ivy

There is a newer version: 3.6.18
Show newest version
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