/* * Copyright 2006,2007 Enrico Boldrini, Lorenzo Bigagli This file is part of * CheckboxTree. CheckboxTree 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 2 of the License, or (at your * option) any later version. CheckboxTree 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 CheckboxTree; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA */ package net.sourceforge.pmd.jedit.checkboxtree; import net.sourceforge.pmd.jedit.checkboxtree.QuadristateButtonModel.State; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.JCheckBox; import javax.swing.SwingUtilities; import javax.swing.plaf.ActionMapUIResource; /** * Checkbox with four states. Available states are UNCHECKED, CHECKED, * GREY_CHECKED, GREY_UNCHECKED. The rendering is obtained via a visualization * hack. The checkbox exploits the different rendering (greyed) of checkbox * pressed, thus the press, arm, rollover events are not available. Maintenance * tip - There were some tricks to getting this code working: 1. You have to * overwite 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. * * @author boldrini * @author bigagli */ public class QuadristateCheckbox extends JCheckBox { public QuadristateCheckbox(String text, Icon icon, State state) { super(text, icon); // Add a listener for when the mouse is pressed super.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { grabFocus(); getModel().nextState(); } }); // Reset the keyboard action map ActionMap map = new ActionMapUIResource(); map.put("pressed", new AbstractAction() { public void actionPerformed(ActionEvent e) { grabFocus(); getModel().nextState(); } }); map.put("released", null); SwingUtilities.replaceUIActionMap(this, map); setState(state); } public QuadristateCheckbox(String text, State initial) { this(text, null, initial); } public QuadristateCheckbox(String text) { this(text, State.UNCHECKED); } public QuadristateCheckbox() { this(null); } @Override protected void init(String text, Icon icon) { // substitutes the underlying checkbox model: // if we had call setModel an exception would be raised // because setModel calls a getModel that return a // QuadristateButtonModel, but at this point we // have a JToggleButtonModel this.model = new QuadristateButtonModel(); super.setModel(this.model); // side effect: set listeners super.init(text, icon); } @Override public QuadristateButtonModel getModel() { return (QuadristateButtonModel) super.getModel(); } public void setModel(QuadristateButtonModel model) { super.setModel(model); } @Override @Deprecated public void setModel(ButtonModel model) { // if (!(model instanceof TristateButtonModel)) // useless: Java always calls the most specific method super.setModel(model); } /** No one may add mouse listeners, not even Swing! */ @Override public void addMouseListener(MouseListener l) { } /** * Set the new state to either CHECKED, UNCHECKED or GREY_CHECKED. If * state == null, it is treated as GREY_CHECKED. */ public void setState(State state) { getModel().setState(state); } /** * Return the current state, which is determined by the selection status * of the model. */ public State getState() { return getModel().getState(); } }