diff --git a/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java b/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java
index 740f9a95b..3be775e49 100644
--- a/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java
+++ b/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java
@@ -56,12 +56,13 @@ import org.apache.tools.ant.gui.core.AppContext;
import org.apache.tools.ant.gui.event.ErrorEvent;
import org.apache.tools.ant.gui.acs.ACSProjectElement;
import org.apache.tools.ant.gui.acs.ACSTargetElement;
+import org.apache.tools.ant.gui.event.ShowConsoleEvent;
/**
* Starts an Ant build.
- *
- * @version $Revision$
- * @author Simeon Fitch
+ *
+ * @version $Revision$
+ * @author Simeon Fitch
*/
public class BuildCmd extends AbstractCommand {
@@ -70,37 +71,42 @@ public class BuildCmd extends AbstractCommand {
/** Targets to build. */
private ACSTargetElement[] _targets = null;
- /**
+ /**
* Standard ctor.
- *
+ *
*/
- public BuildCmd(AppContext context) {
+ public BuildCmd(AppContext context) {
super(context);
}
- /**
+ /**
* Set the specific project to build (instead of the default).
- *
+ *
* @param project Project to build.
*/
public void setProject(ACSProjectElement project) {
_project = project;
}
- /**
+ /**
* Set the specific targets to build (instead of the default).
- *
+ *
* @param targets Array of targets to build.
*/
public void setTargets(ACSTargetElement[] targets) {
_targets = targets;
}
- /**
+ /**
* Start the Ant build.
- *
+ *
*/
public void run() {
+
+ // Show the build console
+ getContext().getEventBus().postEvent(
+ new ShowConsoleEvent(getContext()));
+
if(_project == null) {
_project = getContext().getSelectionManager().getSelectedProject();
}
diff --git a/src/antidote/org/apache/tools/ant/gui/command/ShowOrHideConsoleCmd.java b/src/antidote/org/apache/tools/ant/gui/command/ShowOrHideConsoleCmd.java
new file mode 100644
index 000000000..70aa16754
--- /dev/null
+++ b/src/antidote/org/apache/tools/ant/gui/command/ShowOrHideConsoleCmd.java
@@ -0,0 +1,147 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * Component
+ */
+ private Component findComponent(String name) {
+ JFrame frame = (JFrame) getContext().getParentFrame();
+ JRootPane root = frame.getRootPane();
+ return findChild(root.getContentPane(), name);
+ }
+
+ /**
+ * Search the Container
for a Component
+ * with the input name. The search is recursive.
+ *
+ * @param container The Container
to search
+ * @param name The name of the Component
+ */
+ private Component findChild(Container container, String name) {
+ Component[] components = container.getComponents();
+ for (int i = 0; i < components.length; i++) {
+ Component component = components[i];
+ if ( name.equals(component.getName()) ) {
+ return component;
+ }
+ if (component instanceof java.awt.Container) {
+ Component test = findChild(
+ (java.awt.Container) component, name);
+ if (test != null) {
+ return test;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/antidote/org/apache/tools/ant/gui/core/ActionManager.java b/src/antidote/org/apache/tools/ant/gui/core/ActionManager.java
index b832c297a..0807ba958 100644
--- a/src/antidote/org/apache/tools/ant/gui/core/ActionManager.java
+++ b/src/antidote/org/apache/tools/ant/gui/core/ActionManager.java
@@ -55,16 +55,19 @@ package org.apache.tools.ant.gui.core;
import org.apache.tools.ant.gui.event.*;
import org.apache.tools.ant.gui.command.Command;
+import org.apache.tools.ant.gui.util.CheckableButtonModel;
import javax.swing.*;
+import javax.accessibility.*;
import java.util.*;
+import java.beans.*;
import java.lang.reflect.Constructor;
/**
* Manager of antidote actions. Receives its configuration from the action
* ResourceBundle.
- *
- * @version $Revision$
- * @author Simeon Fitch
+ *
+ * @version $Revision$
+ * @author Simeon Fitch
*/
public class ActionManager {
/** Parameters for the Command constructor. */
@@ -86,9 +89,9 @@ public class ActionManager {
private EventToActionMapper _mapper = null;
- /**
+ /**
* Standard ctor.
- *
+ *
* @param bus Event bus to post events to.
* @param resources Location of resources.
*/
@@ -113,9 +116,9 @@ public class ActionManager {
}
}
- /**
+ /**
* Create a menubar for the application based on the configuration file.
- *
+ *
* @return Menubar.
*/
public JMenuBar createMenuBar() {
@@ -162,7 +165,7 @@ public class ActionManager {
}
// See if we should add a separator.
- if(action.isPreceededBySeparator() &&
+ if(action.isPreceededBySeparator() &&
menu.getMenuComponentCount() > 0) {
menu.addSeparator();
}
@@ -173,10 +176,14 @@ public class ActionManager {
addNiceStuff(item, action);
}
else {
- JCheckBoxMenuItem b =
+ JCheckBoxMenuItem b =
new JCheckBoxMenuItem(action.getName());
b.setActionCommand(action.getID());
b.addActionListener(action);
+
+ action.addPropertyChangeListener(
+ new PropertyWatcher(b));
+
// XXX eck. This is a 1.3 feature. Fix ME!
// Need to provide binding between action and widget.
// b.setAction(action);
@@ -190,14 +197,14 @@ public class ActionManager {
return retval;
}
- /**
+ /**
* Create a tool bar based on the current configuration.
- *
+ *
* @return Toolbar ready for action.
*/
public JToolBar createToolBar() {
JToolBar retval = new JToolBar();
-
+
for(int i = 0; i < _actionIDs.length; i++) {
AntAction action = (AntAction) _actions.get(_actionIDs[i]);
// If it has an icon, then we add it to the toolbar.
@@ -209,6 +216,15 @@ public class ActionManager {
JButton button = retval.add(action);
button.setText(null);
+ // Watch for CHECKED changes
+ action.addPropertyChangeListener(
+ new PropertyWatcher(button));
+
+ if(action.isToggle()) {
+ ButtonModel model = new CheckableButtonModel();
+ button.setModel(model);
+ }
+
addNiceStuff(button, action);
}
}
@@ -216,12 +232,12 @@ public class ActionManager {
return retval;
}
- /**
+ /**
* Create a popup menu with the given actionIDs.
* XXX check this for object leak. Does the button
* get added to the action as a listener? There are also some
* changes to this behavior in 1.3.
- *
+ *
* @param actionIDs List of action IDs for actions
* to appear in popup menu.
* @return Popup menu to display.
@@ -240,9 +256,9 @@ public class ActionManager {
return retval;
}
- /**
+ /**
* Get the command assocaited with the Action with the given id.
- *
+ *
* @param actionID Id of action to get command for.
* @return Command associated with action, or null if none available.
*/
@@ -253,7 +269,7 @@ public class ActionManager {
Class clazz = action.getCommandClass();
if(clazz != null) {
try {
- Constructor ctor =
+ Constructor ctor =
clazz.getConstructor(COMMAND_CTOR_PARAMS);
retval = (Command) ctor.newInstance(
new Object[] { context });
@@ -268,10 +284,10 @@ public class ActionManager {
}
- /**
+ /**
* Add tool tip, Mnemonic, etc.
- *
- * @param button Button to work on.
+ *
+ * @param button Button to work on.
* @param action Associated action.
*/
private void addNiceStuff(AbstractButton button, AntAction action) {
@@ -297,19 +313,19 @@ public class ActionManager {
private class Enabler implements BusMember {
private final Filter _filter = new Filter();
- /**
+ /**
* Get the filter to that is used to determine if an event should
* to to the member.
- *
+ *
* @return Filter to use.
*/
public BusFilter getBusFilter() {
return _filter;
}
-
- /**
+
+ /**
* Receives all events.
- *
+ *
* @param event Event to post.
* @return true if event should be propogated, false if
* it should be cancelled.
@@ -322,9 +338,9 @@ public class ActionManager {
/** Class providing filtering for project events. */
private static class Filter implements BusFilter {
- /**
+ /**
* Determines if the given event should be accepted.
- *
+ *
* @param event Event to test.
* @return True if event should be given to BusMember, false otherwise.
*/
@@ -333,5 +349,31 @@ public class ActionManager {
}
}
+ /** Class which's hooks the action to toggle buttons. */
+ private static class PropertyWatcher implements PropertyChangeListener {
+ private AbstractButton _target;
+ /**
+ * Standard ctor.
+ *
+ * @param target Button to update
+ */
+ public PropertyWatcher(AbstractButton target) {
+ _target = target;
+ }
+
+ /**
+ * Change the Selected stated of the button if the CHECKED
+ * property is set on the action
+ *
+ * @param event Event to test.
+ */
+ public void propertyChange(PropertyChangeEvent e) {
+ String propertyName = e.getPropertyName();
+ if (propertyName.equals(AccessibleState.CHECKED.toString())) {
+ Boolean newValue = (Boolean) e.getNewValue();
+ _target.setSelected(newValue.booleanValue());
+ }
+ }
+ }
}
diff --git a/src/antidote/org/apache/tools/ant/gui/core/AntAction.java b/src/antidote/org/apache/tools/ant/gui/core/AntAction.java
index 8f994d64b..9289f434d 100644
--- a/src/antidote/org/apache/tools/ant/gui/core/AntAction.java
+++ b/src/antidote/org/apache/tools/ant/gui/core/AntAction.java
@@ -54,18 +54,20 @@
package org.apache.tools.ant.gui.core;
import javax.swing.*;
+import javax.accessibility.*;
import java.net.URL;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.*;
import java.util.*;
import org.apache.tools.ant.gui.event.EventBus;
/**
- * Class representing an action in the Antidote application.
- *
- * @version $Revision$
- * @author Simeon Fitch
+ * Class representing an action in the Antidote application.
+ *
+ * @version $Revision$
+ * @author Simeon Fitch
*/
public class AntAction extends AbstractAction {
/** Property name for the parent menu item. */
@@ -76,6 +78,8 @@ public class AntAction extends AbstractAction {
public static final String ENABLE_ON = "enableOn";
public static final String DISABLE_ON = "disableOn";
public static final String TOGGLE = "toggle";
+ public static final String CHECKED_TRUE_ON = "checkedTrueOn";
+ public static final String CHECKED_FALSE_ON = "checkedFalseOn";
public static final String COMMAND = "command";
/** Property resources. */
@@ -85,22 +89,28 @@ public class AntAction extends AbstractAction {
/** Unique id. */
private String _id = null;
- /** Events that the action should cause transition to the
+ /** Events that the action should cause transition to the
* enabled(true) state. */
private Class[] _enableOn = null;
- /** Events that the action should cause transition to the
+ /** Events that the action should cause transition to the
* enabled(false) state. */
private Class[] _disableOn = null;
+ /** Events that the action should cause transition to the
+ * checked state. */
+ private Class[] _checkedTrueOn = null;
+ /** Events that the action should cause transition to the
+ * not checked state. */
+ private Class[] _checkedFalseOn = null;
/** Flag indicating toggle action. */
private boolean _toggle = false;
-
- /**
+ /**
* Standard ctor.
- *
+ *
* @param id Unique id for the action
*/
public AntAction(ResourceManager resources, EventBus bus, String id) {
+
_resources = resources;
_bus = bus;
_id = id;
@@ -149,13 +159,14 @@ public class AntAction extends AbstractAction {
_enableOn = resolveClasses(getString(ENABLE_ON));
_disableOn = resolveClasses(getString(DISABLE_ON));
-
+ _checkedTrueOn = resolveClasses(getString(CHECKED_TRUE_ON));
+ _checkedFalseOn = resolveClasses(getString(CHECKED_FALSE_ON));
}
-
- /**
+
+ /**
* Convenience method for looking put a resource with the name
* "id.key". Will return null if the resource doesn't exist.
- *
+ *
* @param key Key name for the action.
* @return String resource for composite key, or null if not found.
*/
@@ -166,16 +177,16 @@ public class AntAction extends AbstractAction {
}
catch(MissingResourceException ex) {
// Its ok to be missing a resource name...
- // Too bad the API throws an exception in this case.
+ // Too bad the API throws an exception in this case.
}
return retval;
}
- /**
+ /**
* Parse out the list of classes from the given string and
* resolve them into classes.
- *
+ *
* @param classNames Comma delimited list of class names.
*/
private Class[] resolveClasses(String classNames) {
@@ -191,7 +202,7 @@ public class AntAction extends AbstractAction {
catch(ClassNotFoundException ex) {
//XXX log me.
System.err.println(
- "Warning: the event class " + name +
+ "Warning: the event class " + name +
" was not found. Please check config file.");
}
}
@@ -201,46 +212,46 @@ public class AntAction extends AbstractAction {
return retval;
}
- /**
+ /**
* Unique id for the action.
- *
+ *
* @return Action id.
*/
public String getID() {
return _id;
}
- /**
+ /**
* Get the name of the menu in the menu bar that this action shoul
* appear under.
- *
+ *
* @return Menu to appear under, or null if not a menu action.
*/
public String getParentMenuName() {
return (String) getValue(PARENT_MENU_NAME);
}
-
- /**
+
+ /**
* Get the localized name for the action.
- *
+ *
* @return Name
*/
public String getName() {
return (String) getValue(NAME);
}
-
- /**
+
+ /**
* Get the short description. Used in tool tips.
- *
+ *
* @return Short description.
*/
public String getShortDescription() {
return (String) getValue(SHORT_DESCRIPTION);
}
-
- /**
+
+ /**
* Determine if a separator should appear before the action.
- *
+ *
* @return True if add separator, false otherwise.
*/
public boolean isPreceededBySeparator() {
@@ -248,18 +259,18 @@ public class AntAction extends AbstractAction {
String.valueOf(getValue(SEPARATOR))).booleanValue();
}
- /**
+ /**
* Get the icon.
- *
+ *
* @return Icon for action, or null if none.
*/
public Icon getIcon() {
return (Icon) getValue(SMALL_ICON);
}
- /**
+ /**
* Get the accelerator keystroke.
- *
+ *
* @return Accelerator
*/
public KeyStroke getAccelerator() {
@@ -267,27 +278,43 @@ public class AntAction extends AbstractAction {
}
- /**
+ /**
* Get the event types which should cause this to go to the
* enabled state.
- *
+ *
*/
public Class[] getEnableOnEvents() {
return _enableOn;
}
- /**
- * Get the event types which should cause this to go to
+ /**
+ * Get the event types which should cause this to go to
* this disabled state.
- *
+ *
*/
public Class[] getDisableOnEvents() {
return _disableOn;
}
- /**
+ /**
+ * Get the event types which should cause this to go to the
+ * checked state.
+ */
+ public Class[] getCheckedTrueOnEvents() {
+ return _checkedTrueOn;
+ }
+
+ /**
+ * Get the event types which should cause this to go to the
+ * not checked state.
+ */
+ public Class[] getCheckedFalseOnEvents() {
+ return _checkedFalseOn;
+ }
+
+ /**
* True if this is a toggle action, false otherwise.
- *
+ *
* @return True if this is a toggle action, false otherwise.
*/
public boolean isToggle() {
@@ -295,18 +322,18 @@ public class AntAction extends AbstractAction {
}
- /**
+ /**
* Get the assciated command class.
- *
+ *
* @return Command class.
*/
public Class getCommandClass() {
return (Class) getValue(COMMAND);
}
- /**
+ /**
* Pass the action on to the EventBus.
- *
+ *
* @param e Event to forward.
*/
public void actionPerformed(ActionEvent e) {
diff --git a/src/antidote/org/apache/tools/ant/gui/core/EventToActionMapper.java b/src/antidote/org/apache/tools/ant/gui/core/EventToActionMapper.java
index a3d24bde9..0a30c2362 100644
--- a/src/antidote/org/apache/tools/ant/gui/core/EventToActionMapper.java
+++ b/src/antidote/org/apache/tools/ant/gui/core/EventToActionMapper.java
@@ -52,14 +52,16 @@
* ConsoleNotVisibleEvent
or
+ * ConsoleVisibleEvent
events.
+ */
+ addComponentListener(new ComponentAdapter() {
+ public void componentResized(ComponentEvent e) {
+ AppContext c = BuildConsole.this.getContext();
+ if (BuildConsole.this.getHeight() == 0) {
+ c.getEventBus().postEvent(new ConsoleNotVisibleEvent(c));
+ } else {
+ c.getEventBus().postEvent(new ConsoleVisibleEvent(c));
+ }
+ }
+ public void componentHidden(ComponentEvent e) {}
+ public void componentMoved(ComponentEvent e) {}
+ public void componentShown(ComponentEvent e) {}
+ });
+
}
- /**
+ /**
* Clear the contents of the console.
- *
+ *
*/
private void clearDisplay() {
Document doc = _text.getDocument();
@@ -146,19 +166,19 @@ public class BuildConsole extends AntModule {
private class Handler implements BusMember {
private final Filter _filter = new Filter();
- /**
+ /**
* Get the filter to that is used to determine if an event should
* to to the member.
- *
+ *
* @return Filter to use.
*/
public BusFilter getBusFilter() {
return _filter;
}
-
- /**
+
+ /**
* Called when an event is to be posed to the member.
- *
+ *
* @param event Event to post.
* @return true if event should be propogated, false if
* it should be cancelled.
@@ -176,7 +196,7 @@ public class BuildConsole extends AntModule {
case BuildEventType.BUILD_STARTED_VAL:
case BuildEventType.BUILD_FINISHED_VAL:
- text = buildEvent.getType().toString() +
+ text = buildEvent.getType().toString() +
" (" + new Date().toString() + ")";
style = _styles.getHeadingStyle();
break;
@@ -191,7 +211,7 @@ public class BuildConsole extends AntModule {
case BuildEventType.MESSAGE_LOGGED_VAL:
// Filter out events that are below our
// selected filterint level.
- LogLevelEnum level =
+ LogLevelEnum level =
(LogLevelEnum) _logLevel.getSelectedItem();
int priority = buildEvent.getEvent().getPriority();
if(priority <= level.getValue()) {
@@ -226,9 +246,9 @@ public class BuildConsole extends AntModule {
/** Class providing filtering for project events. */
private static class Filter implements BusFilter {
- /**
+ /**
* Determines if the given event should be accepted.
- *
+ *
* @param event Event to test.
* @return True if event should be given to BusMember, false otherwise.
*/
@@ -255,9 +275,9 @@ public class BuildConsole extends AntModule {
Color.blue
};
- /**
+ /**
* Default ctor.
- *
+ *
*/
public ConsoleStyleContext() {
Style defaultStyle = getStyle(DEFAULT_STYLE);
@@ -283,9 +303,9 @@ public class BuildConsole extends AntModule {
StyleConstants.setUnderline(subheading, false);
}
- /**
+ /**
* Get the style to use for the given logging level.
- *
+ *
* @param level Logging level.
* @return Style to use for display.
*/
@@ -294,36 +314,36 @@ public class BuildConsole extends AntModule {
return retval == null ? getDefaultStyle() : retval;
}
- /**
+ /**
* Get the default style.
- *
+ *
* @return Default style.
*/
Style getDefaultStyle() {
return getStyle(DEFAULT_STYLE);
}
- /**
+ /**
* Get the style to use for headings.
- *
+ *
* @return Heading style.
*/
Style getHeadingStyle() {
return getStyle(HEADING_STYLE);
}
- /**
+ /**
* Get the style to use for subheadings.
- *
+ *
* @return Subheading style.
*/
Style getSubheadingStyle() {
return getStyle(SUBHEADING_STYLE);
}
- /**
+ /**
* Get a StyledDocument initialized with this.
- *
+ *
* @return SytledDocument.
*/
StyledDocument getStyledDocument() {
diff --git a/src/antidote/org/apache/tools/ant/gui/resources/action.properties b/src/antidote/org/apache/tools/ant/gui/resources/action.properties
index 8302340dd..c4b59a835 100644
--- a/src/antidote/org/apache/tools/ant/gui/resources/action.properties
+++ b/src/antidote/org/apache/tools/ant/gui/resources/action.properties
@@ -1,11 +1,11 @@
# Define the primary menubar items.
-menus=File, Build, Projects, Help
+menus=File, View, Build, Projects, Help
# Declare the list of known actions.
actions=\
new, open, save, saveas, close, exit, about, \
newTarget, newTask, newProperty \
- startBuild, stopBuild
+ startBuild, stopBuild, viewConsole
# Configure the decalred actions.
new.name=New Project...
@@ -149,3 +149,18 @@ newProperty.disableOn=\
org.apache.tools.ant.gui.event.PropertySelectionEvent, \
org.apache.tools.ant.gui.event.ProjectClosedEvent, \
org.apache.tools.ant.gui.event.NullSelectionEvent
+
+viewConsole.name=console
+viewConsole.shortDescription=Displays or hides the console pane
+viewConsole.parentMenuName=View
+viewConsole.icon=console.gif
+viewConsole.separator=true
+viewConsole.accelerator=control C
+viewConsole.enabled=true
+viewConsole.toggle=true
+viewConsole.initalToggleValue=true
+viewConsole.command=org.apache.tools.ant.gui.command.ShowOrHideConsoleCmd
+viewConsole.checkedTrueOn=\
+ org.apache.tools.ant.gui.event.ConsoleVisibleEvent
+viewConsole.checkedFalseOn=\
+ org.apache.tools.ant.gui.event.ConsoleNotVisibleEvent
diff --git a/src/antidote/org/apache/tools/ant/gui/resources/console.gif b/src/antidote/org/apache/tools/ant/gui/resources/console.gif
new file mode 100644
index 000000000..4fbd3361c
Binary files /dev/null and b/src/antidote/org/apache/tools/ant/gui/resources/console.gif differ
diff --git a/src/antidote/org/apache/tools/ant/gui/util/CheckableButtonModel.java b/src/antidote/org/apache/tools/ant/gui/util/CheckableButtonModel.java
new file mode 100644
index 000000000..21b737ace
--- /dev/null
+++ b/src/antidote/org/apache/tools/ant/gui/util/CheckableButtonModel.java
@@ -0,0 +1,144 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * Call setSelected
to select the button. When the
+ * button is selected, both the PRESSED and ARMED properties are
+ * set which gives the button a pressed appearance.
+ *
+ * @version $Revision$
+ * @author Nick Davisnick_home_account@yahoo.com
+ */
+public class CheckableButtonModel extends DefaultButtonModel {
+
+ boolean _pressed = false;
+ boolean _armed = false;
+
+ /**
+ * Constructs a CheckableButtonModel
+ *
+ */
+ public CheckableButtonModel() {
+ }
+
+ /**
+ * Sets the button to pressed or unpressed.
+ *
+ * @param b true to set the button to "pressed"
+ * @see #isPressed
+ */
+ public void setPressed(boolean b) {
+
+ if((_pressed == b) || !isEnabled()) {
+ return;
+ }
+
+ _pressed = b;
+
+ if(!_pressed && _armed) {
+ fireActionPerformed(
+ new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
+ getActionCommand())
+ );
+ }
+
+ fireStateChanged();
+
+ stateMask |= PRESSED;
+ }
+
+ /**
+ * Marks the button as "armed". If the mouse button is
+ * released while it is over this item, the button's action event
+ * fires. If the mouse button is released elsewhere, the
+ * event does not fire and the button is disarmed.
+ *
+ * @param b true to arm the button so it can be selected
+ */
+ public void setArmed(boolean b) {
+
+ if((_armed == b) || !isEnabled()) {
+ return;
+ }
+
+ _armed = b;
+ fireStateChanged();
+ stateMask |= ARMED;
+ }
+
+ /**
+ * Returns true if the button is selected.
+ *
+ * @return true if the button is "selected"
+ */
+ public boolean isArmed() {
+ return isSelected();
+ }
+
+ /**
+ * Returns true if the button is selected.
+ *
+ * @return true if the button is "selected"
+ */
+ public boolean isPressed() {
+ return isSelected();
+ }
+}