Browse Source

Tow Antidote patches:

*) Design document.

*) can now write BuildEvents to console.

Submitted by:	Simeon Fitch <metasim@yahoo.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268152 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 24 years ago
parent
commit
c70641243c
27 changed files with 1429 additions and 78 deletions
  1. +2
    -0
      WHATSNEW
  2. +40
    -0
      src/antidote/ChangeLog
  3. +2
    -2
      src/antidote/build.xml
  4. +258
    -0
      src/antidote/docs/design-overview.html
  5. +42
    -5
      src/antidote/org/apache/tools/ant/gui/ActionManager.java
  6. +2
    -0
      src/antidote/org/apache/tools/ant/gui/AntEditor.java
  7. +12
    -10
      src/antidote/org/apache/tools/ant/gui/Antidote.java
  8. +151
    -0
      src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java
  9. +106
    -11
      src/antidote/org/apache/tools/ant/gui/Console.java
  10. +3
    -0
      src/antidote/org/apache/tools/ant/gui/EventResponder.java
  11. +163
    -0
      src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java
  12. +11
    -2
      src/antidote/org/apache/tools/ant/gui/Main.java
  13. +1
    -1
      src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java
  14. +92
    -20
      src/antidote/org/apache/tools/ant/gui/ProjectProxy.java
  15. +21
    -0
      src/antidote/org/apache/tools/ant/gui/ResourceManager.java
  16. +90
    -0
      src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java
  17. +1
    -1
      src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java
  18. +138
    -0
      src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java
  19. +208
    -0
      src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java
  20. +48
    -22
      src/antidote/org/apache/tools/ant/gui/event/EventBus.java
  21. +19
    -2
      src/antidote/org/apache/tools/ant/gui/resources/action.properties
  22. +7
    -1
      src/antidote/org/apache/tools/ant/gui/resources/antidote.properties
  23. BIN
      src/antidote/org/apache/tools/ant/gui/resources/default.gif
  24. BIN
      src/antidote/org/apache/tools/ant/gui/resources/icon-small.gif
  25. BIN
      src/antidote/org/apache/tools/ant/gui/resources/start.gif
  26. BIN
      src/antidote/org/apache/tools/ant/gui/resources/stop.gif
  27. +12
    -1
      src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java

+ 2
- 0
WHATSNEW View File

@@ -4,6 +4,8 @@ Changes from Ant 1.2 to the current sources
Other changes: Other changes:
-------------- --------------


* A GUI Frontend: Antidote

* New tasks: propertyfile, depend, antlr * New tasks: propertyfile, depend, antlr


* Added output attribute to <java>. * Added output attribute to <java>.


+ 40
- 0
src/antidote/ChangeLog View File

@@ -1,3 +1,43 @@
2000-11-05 Simeon H.K. Fitch <simeon@fitch.net>

* org/apache/tools/ant/gui/LogLevelEnum.java: Added log level
enumeration for use with combo boxes (drops nicely into default model).

* org/apache/tools/ant/gui/event/BuildEventType.java: Added
delivering of event to a BuildListener based on enumeration value.

* org/apache/tools/ant/gui/ProjectProxy.java: Added generation of
BuildEvent on project start and finish, as the project itself
doesn't generate theses events (unfortunately).

* org/apache/tools/ant/gui/Console.java: Added filtering level,
and clearing of buffer when a new build starts.

* org/apache/tools/ant/gui/AntEditor.java: Added automatic border
for all subclasses.

2000-11-04 Simeon H.K. Fitch <simeon@fitch.net>

* org/apache/tools/ant/gui/ProjectProxy.java: Added inner class to
execute the build in a separate thread.

* org/apache/tools/ant/gui/event/EventBus.java: Added check to see
if postEvent() is being called on the AWTEvent thread, and if not,
post the dispatching of the event to that thread. This is needed
as most of the listeners will be bound to GUI components and will
be updating their state (which must occur on the event thread).

* org/apache/tools/ant/gui/ProjectProxy.java: Added a
BuildListener to forward events to the EventBus.

2000-11-03 Simeon H.K. Fitch <simeon@fitch.net>

* org/apache/tools/ant/gui/Antidote.java: Removed hard-coded
Console class.

* org/apache/tools/ant/gui/Console.java: Changed to a real
AntEditor class, initialized by the config file.

2000-11-02 Simeon H.K. Fitch <simeon@fitch.net> 2000-11-02 Simeon H.K. Fitch <simeon@fitch.net>


* org/apache/tools/ant/gui/event/EventBus.java: Added interrupt * org/apache/tools/ant/gui/event/EventBus.java: Added interrupt


+ 2
- 2
src/antidote/build.xml View File

@@ -50,8 +50,8 @@
<javac srcdir="${src.dir}" <javac srcdir="${src.dir}"
destdir="${build.classes}" destdir="${build.classes}"
debug="on" debug="on"
deprecation="off"
optimize="on" >
deprecation="on"
optimize="off" >
<classpath refid="classpath" /> <classpath refid="classpath" />
</javac> </javac>


+ 258
- 0
src/antidote/docs/design-overview.html View File

@@ -0,0 +1,258 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "strict.dtd">
<HTML>
<HEAD>
<TITLE>Antidote Design Overview</TITLE>
</HEAD>

<BODY>

<H1>Antidote Design Overview</H1>

<P>Version 0.1 (2000/11/02)</P>

<P>Authors:
<A HREF="mailto:simeon@fitch.net">Simeon H.K. Fitch</A>
</P>

<H2>Introduction</H2>

<P>The purpose of this document is to communicate the overall
structure and design patters used in Antidote, the GUI for
Ant. This document is a work in progress, as well as a living
document, and it is most likely not be in full synchronization with
the source code. Therefore, if there is any doubt, view the source
;-)</P>

<H2>Overview</H2>
<P>The Antidote architecture design aims to provide a high level
of modularity and extensibility. Ideally the components of
Antidote will be able to be assembled in different configurations
to provide the type of application or plug-in desired.</P>

<P>To acheive this modularity, a high level of decoupling is
necessary. The standard UI design approach of providing separation
of view (presentation) from model (data) is applied, leveraging
the built-in Ant data model where possible, as well as the
predifined Swing model interfaces. Furthermore, the architecture
is highly event driven, whereby modules communicate via a shared
communications channel.</P>
<P>To a large extent, the configuration of application modules is
driven by localized configuration files, allowing new editors or
data views to be added, as well as providing multi-language
support.</P>

<P>The diagram below conveys a high altitude view of the
application's structure. As the application grows, new components
will be plugged in to what will be described as the <TT>EventBus</TT>.

<TT><PRE>

Antidote Component Architecture

+---------------+ +----------------+ +-------------+ +-------------+
| | | | | | | |
| ActionManager | | EventResponder | | AntEditor | | AntEditor |
| | | | |(ProjectNav) | |(SourceEdit) |
+---------------+ +----------------+ +-------------+ +-------------+
| ^ ^ ^
| | | |
ActionEvent EventObject AntEvent AntEvent
| | | |
v v v v
/---------------------------------------------------------------------\
/ \
< EventBus >
\ /
\---------------------------------------------------------------------/
| ^ ^ ^
| | | |
EventObject ChangeEvent BuildEvent EventObject
| | | |
v | | v
+---------------+ +----------------+ +-------------+ +--------------+
| | | | | | | |
| Console | | ProjectProxy | | Ant | | (Your Module)|
| | | | | | | |
+---------------+ +----------------+ +-------------+ +--------------+

</TT></PRE>

<H2>Event Bus</H2>

<P>The backbone of the application is the <TT>EventBus</TT>. Any
component of the application can post events to the
<TT>EventBus</TT>. Components that wish to receive events are
called <TT>BusMember</TT>s.</P>

<P>The <TT>EventBus</TT> will dispatch any object of type
<TT>java.util.EventBus</TT>, which means that Ant <TT>BuildEvent</TT>
objects, as well as <TT>AWTEvent</TT> objects can be posted (if desired). A
new class of events called <TT>AntEvent</TT> is defined for Antidote
specific events, which have the additional capability of being
cancelled mid-dispatch.</P>

<P>Each <TT>BusMember</TT> must provide a <TT>BusFilter</TT> instance,
which is the members' means of telling the bus which
events it is interested in. This allows a <TT>BusMember</TT> to,
say, only receive <TT>AntEvent</TT> objects.</P>

<P>When a <TT>BusMember</TT> registers itself with the
<TT>EventBus</TT>, it must provide a (so called) <I>interrupt
level</I> which is a integer value defining a relative ordering
for dispatching <TT>EventObject</TT>s to <TT>BusMember</TT>s. The
purpose of this is to allow certain <TT>BusMember</TT> instances
to see an event before others, and in the case of <TT>AntEvent</TT
objects, keep the event from propogating onward. The
<TT>EventBus</TT> class defines the interrupt level constants
<TT>MONITORING=1</TT>, <TT>VETOING=5</TT>, and <TT>RESPONDING=10</TT> to
help define categories of members. The implied purpose being that:
<UL>

<LI><TT>MONITORING</TT>: Just listens for events, like a logger
or status monitor.</LI>

<LI><TT>VETOING</TT>: Listens for certain types of events, and
may process them in a non-default manner to determine if the
event should be cancelled before being dispatched to the
<TT>RESPONDING</TT> group. An example of this might be to handle
a <I>SaveAs</I> event, whereby a <TT>VETOING</TT> member will
check to see if the file exists, and ask the user if they are
sure they want to overwrite the existing file. The <I>SaveAs</I>
event could then be cancelled before the operation is executed.</LI>

<LI><TT>RESPONDING</TT>: Process events in a default manner,
knowing that the event has passed any <TT>VETOING</TT> members.</LI>

</UL>

Within a specific interrupt level, the order in which members will
receive events is undefied. A <TT>BusMember</TT> may be registered
at a level that is +/- of one of the defined levels, as long as it
follows the constraint <TT>MONITORING <= interruptLevel <=
MAX_INTERRUPT</TT>.</P>


<H2>Actions and ActionManager</H2>

<P>Extensive use of the <TT>javax.swing.Action</TT> interface is
made for defining the set of menu and tool bar options that are
available. The configuration file <TT>action.properties</TT>
exists to define what should appear in the menu and toolbar, how
it is displayed, and the <TT>Action</TT> command name that is
dispatched when the user invokes that action. A class called
<TT>ActionManager</TT> exists for not only processing the
configuration file, but also for dispatching invoked action events
to the <TT>EventBus</TT>, and for controlling the enabled state of
an <TT>Action</TT>. When a new menu item or toolbar button is
desired, first it is added to the <TT>action.properties</TT> file,
and then the code to respond to it is added to the
<TT>EventResponder</TT> (see below).


<H2>Commands and EventResponder</H2>

<P>At some point in the stages of event processing, an event may
require the data model to be modified, or some other task be
performed. The <TT>Command</TT> interface is defined to classify
code which performs some task or operation. This is distinct from
an <TT>Action</TT>, which is a user request for an operation. A
<TT>Command</TT> class is the encapsulation of the operation
itself.</P>

<P>When an <TT>Action</TT> generates an <TT>ActionEvent</TT>, the
event is posted to the <TT>EventBus</TT> which delivers the event
to all interested <TT>BusMember</TT>s. It eventually makes it to
the <TT>EventResponder</TT> instance (registered at the
<TT>RESPONDING</TT> interrupt level), which is responsible for
translating specific events into <TT>Command</TT> objects, and
then executing the <TT>Command</TT> object. For example, when the
user selects the "Open..." menu option, an <TT>ActionEvent</TT> is
generated by the Swing <TT>MenuItem</TT> class, which is then
posted to the <TT>EventBus</TT> by the <TT>ActionManager</TT>. The
<TT>ActionEvent</TT> is delivered to the <TT>EventResponder</TT>,
which converts the <TT>ActionEvent</TT> into a <TT>Command</TT>
instance. The <TT>EventResponder</TT> then calls the method
<TT>Command.execute()</TT> to invoke the command (which displays a
dialog for selecting a file to open).</P>

<P>When adding new <TT>Action</TT>s or general tasks to the
application, a <TT>Command</TT> object should be created to
encapsulate the behavior. This includes most operations which
modify the state of the data model.</P>

<P>The purpose of this encapsulation is to allow the clean
separation of making a request, and servicing a request. Due to
various conditions in the application state, the actualy response
to a request may change, as well as who services it. This
design approach facilitates that.</P>

<H2>Data Model and Views</H2>

<P>The data model is mainly defined by the Ant application,
primarily through the <TT>Project</TT>, <TT>Target</TT>, and
<TT>Task</TT> classes.<P> However, Antidote defines the class
<TT>ProjectProxy</TT> to act not only as a proxy to the real
<TT>Project</TT> class, but also as creator of GUI <I>views</I> of
the <TT>Project</TT>. A <I>view</I> is essentially a flyweight or
data proxy; it provides an orgainizational perspective on the actual
<TT>Project</TT> structure. For example, to render a
<TT>JTree</TT> version of the <TT>Project</TT>, one would call the
method <TT>ProjectProxy.getTreeModel()</TT>. Similarly, to get a
<TT>Document</TT> version of the <TT>Project</TT>, the
<TT>ProjectProxy,getDocument()</TT> method is used.</P>

<P><I>NB: This part of the architecture is not fleshed out very
well. There needs to be a discussion of the degree to which the
Antidote development should be able to impose changes on the Ant
data model, and to what level that model should be mirrored in the
Antidote code base. The coupling between them should be kept low,
and at the same time changes to one should affect the other
minimally. Still, features like property change events and bean
introspection (or BeanInfo) may be needed to be added to the Ant
data model. Having each view into the data go to the ProjectProxy
for its data model may not be the best approach. In other words,
lots of thought needs to occur here.</I></P>

<H2>Application Context</H2>

<P>In order to keep the coupling amoung application modules to a
minimum, a single point of reference is needed for coordination
and data sharing. The class <TT>AppContext</TT> is the catch-all
class for containing the application state. Most modules and
<TT>Command</TT> classes require an instance of the
<TT>AppContext</TT> class. Because all state information in
contained in an <TT>AppContext</TT> instance, multiple instances
of Antidote can run inside the same JVM as long as each has it's
own <TT>AppContext</TT>. (Interestingly, two instances of the
Antidote could conceivably share an <TT>AppContext</TT> instance
through RMI, allowing remote interaction/collaboration.)</P>

<H2>Configuration and ResourceManager</H2>
<P>Full "i18n" support should be assumed in modern applications,
and all user viewable strings should be defined in a configuration
file. For Antidote this configuraiton file is
<TT>antidote.properties</TT>, which is located (with other UI
resources) in the subpackage "resources".</P>

<P>To aid in the lookup of text properties, as well as other
resources like icons, a class called <TT>ResourceManager</TT> is
defined. There are various convenience methods attached to this
class, which will likely grow to make looking up configuration
values as easy as possible.</P>

<P>The organization of configuration properties is based on the
fully qualifed path of the class that requires the property. For
example, the "about" box contains a messages, so it looks for the
property "<TT>org.apache.tools.ant.gui.About.message</TT>" for the text
message it should display. Therefore, the <TT>ResourceManager</TT>
method <TT>getString()</TT> takes a <TT>Class</TT> instance as
well as a <TT>String</TT> key. Please see the
<TT>ResourceManager</TT> documentation for more information. Given
this support, no user visible strings should appear in the source
code itself.</P>

</BODY>
</HTML>

+ 42
- 5
src/antidote/org/apache/tools/ant/gui/ActionManager.java View File

@@ -113,7 +113,24 @@ public class ActionManager {
while(tok.hasMoreTokens()) { while(tok.hasMoreTokens()) {
String name = tok.nextToken(); String name = tok.nextToken();
JMenu menu = new JMenu(name); JMenu menu = new JMenu(name);
retval.add(menu);

// XXX should be in config file
menu.setMnemonic(name.charAt(0));

// XXX need to i18n here...
if(name.equalsIgnoreCase("help")) {
try {
retval.setHelpMenu(menu);
}
catch(Error err) {
// Catch the "not implemented" error in
// some (all?) Swing implementations
retval.add(menu);
}
}
else {
retval.add(menu);
}
menus.put(name, menu); menus.put(name, menu);
} }


@@ -130,10 +147,13 @@ public class ActionManager {
menus.put(parent, menu); menus.put(parent, menu);
} }


if(action.isPreceededBySeparator()) {
// See if we should add a separator.
if(action.isPreceededBySeparator() &&
menu.getMenuComponentCount() > 0) {
menu.addSeparator(); menu.addSeparator();
} }
JMenuItem item = menu.add(action); JMenuItem item = menu.add(action);
item.setAccelerator(action.getAccelerator());
addNiceStuff(item, action); addNiceStuff(item, action);
} }
} }
@@ -171,6 +191,13 @@ public class ActionManager {
// Set the action command so that it is consitent // Set the action command so that it is consitent
// no matter what language the display is in. // no matter what language the display is in.
button.setActionCommand(action.getID()); button.setActionCommand(action.getID());

// XXX this should be moved to the config file.
String label = button.getText();
if(label != null) {
button.setMnemonic(label.charAt(0));
}

String tip = action.getShortDescription(); String tip = action.getShortDescription();
if(tip != null) { if(tip != null) {
button.setToolTipText(tip); button.setToolTipText(tip);
@@ -202,6 +229,7 @@ public class ActionManager {
/** Property name for the parent menu item. */ /** Property name for the parent menu item. */
public static final String PARENT_MENU_NAME = "parentMenuName"; public static final String PARENT_MENU_NAME = "parentMenuName";
public static final String SEPARATOR = "separator"; public static final String SEPARATOR = "separator";
public static final String ACCELERATOR = "accelerator";


/** Unique id. */ /** Unique id. */
private String _id = null; private String _id = null;
@@ -215,8 +243,14 @@ public class ActionManager {
_id = id; _id = id;
putValue(NAME, getString(id, "name")); putValue(NAME, getString(id, "name"));
putValue(SHORT_DESCRIPTION, getString(id, "shortDescription")); putValue(SHORT_DESCRIPTION, getString(id, "shortDescription"));
putValue(PARENT_MENU_NAME, getString(id, "parentMenuName"));
putValue(SEPARATOR, getString(id, "separator"));
putValue(PARENT_MENU_NAME, getString(id, PARENT_MENU_NAME));
putValue(SEPARATOR, getString(id, SEPARATOR));

String accelerator = getString(id, ACCELERATOR);

if(accelerator != null) {
putValue(ACCELERATOR, KeyStroke.getKeyStroke(accelerator));
}


String iconName = getString(id, "icon"); String iconName = getString(id, "icon");
if(iconName != null) { if(iconName != null) {
@@ -232,7 +266,6 @@ public class ActionManager {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
} }
/** /**
@@ -291,6 +324,10 @@ public class ActionManager {
return (Icon) getValue(SMALL_ICON); return (Icon) getValue(SMALL_ICON);
} }


public KeyStroke getAccelerator() {
return (KeyStroke) getValue(ACCELERATOR);
}

/** /**
* Pass the action on to the EventBus. * Pass the action on to the EventBus.
* *


+ 2
- 0
src/antidote/org/apache/tools/ant/gui/AntEditor.java View File

@@ -54,6 +54,7 @@
package org.apache.tools.ant.gui; package org.apache.tools.ant.gui;


import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.BorderFactory;


/** /**
* Abstract base class for an "editor", which is really anything that * Abstract base class for an "editor", which is really anything that
@@ -78,6 +79,7 @@ public abstract class AntEditor extends JPanel {
*/ */
protected AntEditor(AppContext context) { protected AntEditor(AppContext context) {
_context = context; _context = context;
setBorder(BorderFactory.createTitledBorder(getName()));
} }


/** /**


+ 12
- 10
src/antidote/org/apache/tools/ant/gui/Antidote.java View File

@@ -66,11 +66,6 @@ import java.lang.reflect.Constructor;
* @author Simeon Fitch * @author Simeon Fitch
*/ */
public class Antidote extends JPanel { public class Antidote extends JPanel {


/** Logging console. */
private Console _console = null;

/** Source of application state data. */ /** Source of application state data. */
private AppContext _context = null; private AppContext _context = null;


@@ -83,18 +78,25 @@ public class Antidote extends JPanel {


_context = context; _context = context;


_console = new Console(_context);


// Add the various editors/views to the editing area. // Add the various editors/views to the editing area.
JSplitPane splitter = new JSplitPane(); JSplitPane splitter = new JSplitPane();
splitter.add(JSplitPane.LEFT, populateEditors("left")); splitter.add(JSplitPane.LEFT, populateEditors("left"));
splitter.add(JSplitPane.RIGHT, populateEditors("right")); splitter.add(JSplitPane.RIGHT, populateEditors("right"));
// This is necessary because, frankly, the JSplitPane widget
// sucks, and doesn't provide enought (working) control over the
// initial size of it's subcomponents. setDividerLocation(double)
// doesn't seem to work until after the widget is visible.
splitter.setPreferredSize(new Dimension(500, 300));


add(BorderLayout.CENTER, splitter);
// Top bottom splitter.
JSplitPane splitter2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitter2.setOneTouchExpandable(true);


add(BorderLayout.SOUTH, _console);
splitter2.add(JSplitPane.TOP, splitter);
splitter2.add(JSplitPane.BOTTOM, populateEditors("bottom"));


add(BorderLayout.CENTER, splitter2);
splitter2.resetToPreferredSizes();
setPreferredSize(new Dimension(640, 480)); setPreferredSize(new Dimension(640, 480));
} }




+ 151
- 0
src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java View File

@@ -0,0 +1,151 @@
/*
* 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", "Tomcat", 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui;
import org.apache.tools.ant.gui.event.*;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.BuildEvent;

/**
* BuildListener for forwarding events to the EventBus.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class BuildEventForwarder implements BuildListener {

/** Application context. */
private AppContext _context = null;

public BuildEventForwarder(AppContext context) {
_context = context;
}

/**
* Fired before any targets are started.
*/
public void buildStarted(BuildEvent event){
postEvent(event, BuildEventType.BUILD_STARTED);
}

/**
* Fired after the last target has finished. This event
* will still be thrown if an error occured during the build.
*
* @see BuildEvent#getException()
*/
public void buildFinished(BuildEvent event) {
postEvent(event, BuildEventType.BUILD_FINISHED);
}

/**
* Fired when a target is started.
*
* @see BuildEvent#getTarget()
*/
public void targetStarted(BuildEvent event) {
postEvent(event, BuildEventType.TARGET_STARTED);
}

/**
* Fired when a target has finished. This event will
* still be thrown if an error occured during the build.
*
* @see BuildEvent#getException()
*/
public void targetFinished(BuildEvent event) {
postEvent(event, BuildEventType.TARGET_FINISHED);
}

/**
* Fired when a task is started.
*
* @see BuildEvent#getTask()
*/
public void taskStarted(BuildEvent event) {
postEvent(event, BuildEventType.TASK_STARTED);
}

/**
* Fired when a task has finished. This event will still
* be throw if an error occured during the build.
*
* @see BuildEvent#getException()
*/
public void taskFinished(BuildEvent event) {
postEvent(event, BuildEventType.TASK_FINISHED);
}

/**
* Fired whenever a message is logged.
*
* @see BuildEvent#getMessage()
* @see BuildEvent#getPriority()
*/
public void messageLogged(BuildEvent event) {
postEvent(event, BuildEventType.MESSAGE_LOGGED);
}

/**
* Forward the event.
*
* @param event Event to forward.
* @param type Description of how the event came in.
*/
private void postEvent(BuildEvent event, BuildEventType type) {
_context.getEventBus().postEvent(
new AntBuildEvent(_context, event, type));
}


}

+ 106
- 11
src/antidote/org/apache/tools/ant/gui/Console.java View File

@@ -52,10 +52,13 @@
* <http://www.apache.org/>. * <http://www.apache.org/>.
*/ */
package org.apache.tools.ant.gui; package org.apache.tools.ant.gui;
import org.apache.tools.ant.gui.event.*;
import javax.swing.*; import javax.swing.*;
import java.awt.GridLayout;
import javax.swing.text.Document;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Dimension; import java.awt.Dimension;
import java.util.EventObject;


/** /**
* Logging console display. * Logging console display.
@@ -63,22 +66,114 @@ import java.awt.Dimension;
* @version $Revision$ * @version $Revision$
* @author Simeon Fitch * @author Simeon Fitch
*/ */
public class Console extends JPanel {
private AppContext _context = null;
public class Console extends AntEditor {
/** Area where messages are printed. */
private JTextPane _text = null; private JTextPane _text = null;

/** Selection of logging levels. */
private JComboBox _logLevel = null;
/**
* Standard ctor.
*
* @param context Application context;
*/
public Console(AppContext context) { public Console(AppContext context) {
setLayout(new GridLayout(1,1));
_context = context;
super(context);
context.getEventBus().addMember(EventBus.MONITORING, new Handler());
setLayout(new BorderLayout());


_text = new JTextPane(); _text = new JTextPane();
_text.setEditable(false); _text.setEditable(false);
JScrollPane scroller = new JScrollPane(_text); JScrollPane scroller = new JScrollPane(_text);
scroller.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(BorderLayout.CENTER, scroller);

JPanel controls = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel label = new JLabel(
context.getResources().getString(getClass(), "logLevel"));
controls.add(label);
_logLevel = new JComboBox(LogLevelEnum.getValues());
controls.add(_logLevel);
add(scroller);
add(BorderLayout.NORTH, controls);


_text.setText(
"This is the console area. \nLots of stuff to see here...");
setPreferredSize(new Dimension(200, 40));
} }

/** Class for handling project events. */
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.
*/
public void eventPosted(EventObject event) {
AntBuildEvent buildEvent = (AntBuildEvent) event;
String text = null;

Document doc = _text.getDocument();

switch(buildEvent.getType().getValue()) {
case BuildEventType.BUILD_STARTED_VAL:
try {
doc.remove(0, doc.getLength());
}
catch(Exception ex) {
// Intentionally ignored.
}
break;
case BuildEventType.TARGET_STARTED_VAL:
text = buildEvent.getEvent().getTarget().getName() + ":";
break;
case BuildEventType.TARGET_FINISHED_VAL:
case BuildEventType.TASK_STARTED_VAL:
case BuildEventType.TASK_FINISHED_VAL:
break;
case BuildEventType.MESSAGE_LOGGED_VAL:
text = buildEvent.toString();
break;
}

// Filter out events that are below our selected filterint level.
LogLevelEnum level = (LogLevelEnum) _logLevel.getSelectedItem();
if(buildEvent.getEvent().getPriority() > level.getValue()) return;

if(text != null) {
try {
doc.insertString(doc.getLength(), text, null);
doc.insertString(doc.getLength(), "\n", null);
}
catch(Exception ex) {
// XXX log me.
ex.printStackTrace();
}
}
}
}

/** 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.
*/
public boolean accept(EventObject event) {
return event instanceof AntBuildEvent;
}
}

} }

+ 3
- 0
src/antidote/org/apache/tools/ant/gui/EventResponder.java View File

@@ -117,6 +117,9 @@ class EventResponder {
if(command.equals(OpenCmd.ACTION_NAME)) { if(command.equals(OpenCmd.ACTION_NAME)) {
new OpenCmd(_context).execute(); new OpenCmd(_context).execute();
} }
else if(command.equals(BuildCmd.ACTION_NAME)) {
new BuildCmd(_context).execute();
}
else if(command.equals(CloseCmd.ACTION_NAME)) { else if(command.equals(CloseCmd.ACTION_NAME)) {
new CloseCmd(_context).execute(); new CloseCmd(_context).execute();
} }


+ 163
- 0
src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java View File

@@ -0,0 +1,163 @@
/*
* 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", "Tomcat", 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui;

/**
* Enumeration class of the different log levels.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class LogLevelEnum {
/** Enum value. */
private int _value = 0;

/**
* Standard ctor.
*
* @param value Index value.
*/
private LogLevelEnum(int value) {
_value = value;
}

/**
* Get the enumeration value.
*
* @return
*/
public int getValue() {
return _value;
}

/**
* Get the enumeration value with the given index value.
*
* @param value Index value.
* @return Enumeration value.
*/
public static LogLevelEnum fromInt(int value) {
return _objectMap[value];
}

/**
* Get the set of enumeration values.
*
* @return Value set.
*/
public static LogLevelEnum[] getValues() {
return _objectMap;
}

/**
* Determine if the given object is logically equal to this one.
*
* @param o Object to compare to
* @return True if equal, false otherwise.
*/
public boolean equals(Object o) {
if(o instanceof LogLevelEnum) {
return ((LogLevelEnum)o)._value == _value;
}
return false;
}
/**
* Generate a hash value.
*
* @return Hash value.
*/
public int hashValue() {
return _value;
}

/**
* Provide a string representation of this.
*
* @return String representation.
*/
public String toString() {
return _stringMap[_value];
}


/* Index values. */
public static final int ERROR_VAL = 0;
public static final int WARNING_VAL = 1;
public static final int INFO_VAL = 2;
public static final int VERBOSE_VAL = 3;
public static final int DEBUG_VAL = 4;

/* Enumeration values. */
public static final LogLevelEnum ERROR =
new LogLevelEnum(ERROR_VAL);
public static final LogLevelEnum WARNING =
new LogLevelEnum(WARNING_VAL);
public static final LogLevelEnum INFO =
new LogLevelEnum(INFO_VAL);
public static final LogLevelEnum VERBOSE =
new LogLevelEnum(VERBOSE_VAL);
public static final LogLevelEnum DEBUG =
new LogLevelEnum(DEBUG_VAL);

/** Index to object mapping. */
private static final LogLevelEnum[] _objectMap = {
ERROR, WARNING, INFO, VERBOSE, DEBUG
};

/** String map. XXX needs to be localized. */
private static final String[] _stringMap = {
"Error", "Warning", "Info", "Verbose", "Debug"
};

}

+ 11
- 2
src/antidote/org/apache/tools/ant/gui/Main.java View File

@@ -52,7 +52,7 @@
* <http://www.apache.org/>. * <http://www.apache.org/>.
*/ */
package org.apache.tools.ant.gui; package org.apache.tools.ant.gui;
import org.apache.tools.ant.gui.util.WindowUtils;
import javax.swing.*; import javax.swing.*;
import java.awt.BorderLayout; import java.awt.BorderLayout;


@@ -82,10 +82,19 @@ public class Main {
f.getContentPane().add(BorderLayout.NORTH, f.getContentPane().add(BorderLayout.NORTH,
context.getActions().createToolBar()); context.getActions().createToolBar());


ImageIcon icon =
context.getResources().getImageIcon("icon-small.gif");
if(icon != null) {
f.setIconImage(icon.getImage());
}
else {
System.out.println("Application icon not found.");
}
f.pack(); f.pack();

f.setVisible(true); f.setVisible(true);
// Hack around linux window placement annoyance. // Hack around linux window placement annoyance.
f.setLocation(100, 100);
WindowUtils.centerWindow(f);


} }
catch(Exception ex) { catch(Exception ex) {


+ 1
- 1
src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java View File

@@ -85,7 +85,7 @@ class ProjectNavigator extends AntEditor {
JScrollPane scroller = new JScrollPane(_tree); JScrollPane scroller = new JScrollPane(_tree);
add(scroller); add(scroller);


setPreferredSize(new Dimension(100, 100));
setPreferredSize(new Dimension(150, 100));


} }




+ 92
- 20
src/antidote/org/apache/tools/ant/gui/ProjectProxy.java View File

@@ -54,10 +54,15 @@
package org.apache.tools.ant.gui; package org.apache.tools.ant.gui;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper; import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.gui.event.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import javax.swing.tree.TreeModel; import javax.swing.tree.TreeModel;
import javax.swing.text.Document; import javax.swing.text.Document;
import java.util.Enumeration;


/** /**
* This class provides the gateway interface to the data model for * This class provides the gateway interface to the data model for
@@ -70,44 +75,59 @@ import javax.swing.text.Document;
*/ */
public class ProjectProxy { public class ProjectProxy {


/** Application context */
private AppContext _context = null;
/** The file where the project was last saved. */ /** The file where the project was last saved. */
private File _file = null; private File _file = null;

/** The real Ant Project instance. */ /** The real Ant Project instance. */
private Project _project = null; private Project _project = null;

/**
* Default constructor. NB: right now it is private, but
* will be opened up once the gui supports creating new projects.
*
*/
private ProjectProxy() {
}
/** Private the current thread executing a build. */
private Thread _buildThread = null;


/** /**
* File loading ctor. * File loading ctor.
* *
* @param file File containing build file to load. * @param file File containing build file to load.
*/ */
public ProjectProxy(File file) throws IOException {
this();
public ProjectProxy(AppContext context, File file) throws IOException {
_file = file; _file = file;
_context = context;
loadProject(); loadProject();
} }



/**
* Load the project from the build file.
*
*/
private void loadProject() throws IOException { private void loadProject() throws IOException {
_project = new Project(); _project = new Project();
_project.init();
synchronized(_project) {
_project.init();


// XXX there is a bunch of stuff in the class org.apache.tools.ant.Main
// that needs to be abstracted out so that it doesn't
// have to be replicated here.
// XXX there is a bunch of stuff in the class
// org.apache.tools.ant.Main that needs to be
// abstracted out so that it doesn't have to be
// replicated here.
// XXX need to provide a way to pass in externally defined properties.
// Perhaps define an external Antidote properties file.
_project.setUserProperty("ant.file" , _file.getAbsolutePath());
ProjectHelper.configureProject(_project, _file);
// XXX need to provide a way to pass in externally
// defined properties. Perhaps define an external
// Antidote properties file.
_project.setUserProperty("ant.file" , _file.getAbsolutePath());
ProjectHelper.configureProject(_project, _file);
}
}

/**
* Build the project with the current target (or the default target
* if none is selected. Build occurs on a separate thread, so method
* returns immediately.
*
*/
public void build() throws BuildException {
if(_project == null) return;

_buildThread = new Thread(new BuildRunner());
_buildThread.start();
} }


/** /**
@@ -146,4 +166,56 @@ public class ProjectProxy {
} }
return null; return null;
} }

/**
* Convenience method for causeing the project to fire a build event.
* Implemented because the corresponding method in the Project class
* is not publically accessible.
*
* @param event Event to fire.
*/
private void fireBuildEvent(BuildEvent event, BuildEventType type) {
synchronized(_project) {
Enumeration enum = _project.getBuildListeners().elements();
while(enum.hasMoreElements()) {
BuildListener l = (BuildListener) enum.nextElement();
type.fireEvent(event, l);
}
}
}

/** Class for executing the build in a separate thread. */
private class BuildRunner implements Runnable {
public void run() {
synchronized(_project) {
// Add the build listener for
// dispatching BuildEvent objects to the
// EventBus.
BuildEventForwarder handler =
new BuildEventForwarder(_context);
_project.addBuildListener(handler);
try {
fireBuildEvent(new BuildEvent(
_project), BuildEventType.BUILD_STARTED);
// XXX add code to indicate target execution
// on the targets that are selected.
_project.executeTarget(
_project.getDefaultTarget());
}
catch(BuildException ex) {
BuildEvent errorEvent = new BuildEvent(_project);
errorEvent.setException(ex);
errorEvent.setMessage(ex.getMessage(), Project.MSG_ERR);
fireBuildEvent(errorEvent, BuildEventType.MESSAGE_LOGGED);
}
finally {
fireBuildEvent(new BuildEvent(
_project), BuildEventType.BUILD_FINISHED);
_project.removeBuildListener(handler);
_buildThread = null;
}
}
}
}

} }

+ 21
- 0
src/antidote/org/apache/tools/ant/gui/ResourceManager.java View File

@@ -55,6 +55,9 @@ package org.apache.tools.ant.gui;


import java.util.*; import java.util.*;
import java.text.MessageFormat; import java.text.MessageFormat;
import javax.swing.ImageIcon;
import java.net.URL;
import java.io.File;


/** /**
* Singleton class for accessing various resources by the application. * Singleton class for accessing various resources by the application.
@@ -143,4 +146,22 @@ public class ResourceManager {
return MessageFormat.format(format, arguments); return MessageFormat.format(format, arguments);
} }


/**
* Get the image as an ImageIcon with the given file name.
* For example "open.gif". The image is loaded from the resources package.
*
* @param fileName Image file to load.
* @return Image as an ImageIcon, or null if not found.
*/
public ImageIcon getImageIcon(String fileName) {
ImageIcon icon = null;

URL location = getClass().getResource("resources/" + fileName);

if(location != null) {
icon = new ImageIcon(location);
}
return icon;
}

} }

+ 90
- 0
src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java View File

@@ -0,0 +1,90 @@
/*
* 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.
q *
* 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", "Tomcat", 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui.command;
import org.apache.tools.ant.gui.AppContext;
import org.apache.tools.ant.gui.ProjectProxy;

/**
* Starts an Ant build.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class BuildCmd implements Command {
/** Name of the action the command maps to. */
public static final String ACTION_NAME = "startBuild";

/** The application context */
private AppContext _context = null;

/**
* Standard ctor.
*
* @param context Application context.
*/
public BuildCmd(AppContext context) {
_context = context;
}

/**
* Start the Ant build.
*
*/
public void execute() {
ProjectProxy project = _context.getProject();
if(project != null) {
project.build();
}
}
}

+ 1
- 1
src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java View File

@@ -95,7 +95,7 @@ public class LoadFileCmd implements Command {
} }
else { else {
try { try {
ProjectProxy project = new ProjectProxy(_file);
ProjectProxy project = new ProjectProxy(_context, _file);
_context.setProject(project); _context.setProject(project);
} }
catch(IOException ex) { catch(IOException ex) {


+ 138
- 0
src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java View File

@@ -0,0 +1,138 @@
/*
* 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", "Tomcat", 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui.event;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.gui.util.StackFrame;
import org.apache.tools.ant.gui.command.Command;
import org.apache.tools.ant.gui.command.NoOpCmd;
import org.apache.tools.ant.gui.AppContext;
import java.util.EventObject;

/**
* Wrapper event for the events generated during an Ant build.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class AntBuildEvent extends AntEvent {

/** The original event we are wrapping. */
private BuildEvent _buildEvent = null;
/** The type of event we are wrapping. */
private BuildEventType _type = null;

/**
* Standard ctor.
*
* @param context application context.
*/
public AntBuildEvent(AppContext context,
BuildEvent buildEvent, BuildEventType type) {
super(context);
_buildEvent = buildEvent;
_type = type;

if(_buildEvent == null || _type == null) {
throw new IllegalArgumentException("Null parameter passed");
}
}

/**
* Get the wrapped build event.
*
* @return Build event.
*/
public BuildEvent getEvent() {
return _buildEvent;
}

/**
* Get the build event type.
*
* @return Event type.
*/
public BuildEventType getType() {
return _type;
}

/**
* Create the appropriate default response command to this event.
*
* @return Command representing an appropriate response to this event.
*/
public Command createDefaultCmd() {
return new NoOpCmd();
}
/**
* Create a string representation of this.
*
* @return String representation.
*/
public String toString() {
StringBuffer buf = new StringBuffer();

if(_buildEvent.getMessage() != null) {
buf.append(_buildEvent.getMessage());
buf.append('\n');
}

if(_buildEvent.getException() != null) {
buf.append(StackFrame.toString(_buildEvent.getException()));
}

return buf.toString();
}

}

+ 208
- 0
src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java View File

@@ -0,0 +1,208 @@
/*
* 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", "Tomcat", 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui.event;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.BuildEvent;
import java.lang.reflect.Method;

/**
* Enumeration class of the different contexts in which Ant will generate
* a BuildEvent.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class BuildEventType {
/** Enum value. */
private int _value = 0;

/**
* Standard ctor.
*
* @param value Index value.
*/
private BuildEventType(int value) {
_value = value;
}

/**
* Get the enumeration value.
*
* @return
*/
public int getValue() {
return _value;
}

/**
* Pseudo abstract method for firing an event to a build listener
* based on our enumation value. I overridded by the individual instances.
*
* @param e Event to fire.
* @param l Listener to send event to.
*/
public void fireEvent(BuildEvent e, BuildListener l) {
try {
Method method =
BuildListener.class.getMethod(_methodNameMap[_value],
_listenerMethodParam);
method.invoke(l, new Object[] { e });
}
catch(Exception ex) {
// XXX log me.
ex.printStackTrace();
}
}

/**
* Get the enumeration value with the given index value.
*
* @param value Index value.
* @return Enumeration value.
*/
public static BuildEventType fromInt(int value) {
return _objectMap[value];
}

/**
* Determine if the given object is logically equal to this one.
*
* @param o Object to compare to
* @return True if equal, false otherwise.
*/
public boolean equals(Object o) {
if(o instanceof BuildEventType) {
return ((BuildEventType)o)._value == _value;
}
return false;
}
/**
* Generate a hash value.
*
* @return Hash value.
*/
public int hashValue() {
return _value;
}

/**
* Provide a string representation of this.
*
* @return String representation.
*/
public String toString() {
return _stringMap[_value];
}


/* Index values. */
public static final int BUILD_STARTED_VAL = 0;
public static final int BUILD_FINISHED_VAL = 1;
public static final int TARGET_STARTED_VAL = 2;
public static final int TARGET_FINISHED_VAL = 3;
public static final int TASK_STARTED_VAL = 4;
public static final int TASK_FINISHED_VAL = 5;
public static final int MESSAGE_LOGGED_VAL = 6;

/* Enumeration values. */
public static final BuildEventType BUILD_STARTED =
new BuildEventType(BUILD_STARTED_VAL);
public static final BuildEventType BUILD_FINISHED =
new BuildEventType(BUILD_FINISHED_VAL);
public static final BuildEventType TARGET_STARTED =
new BuildEventType(TARGET_STARTED_VAL);
public static final BuildEventType TARGET_FINISHED =
new BuildEventType(TARGET_FINISHED_VAL);
public static final BuildEventType TASK_STARTED =
new BuildEventType(TASK_STARTED_VAL);
public static final BuildEventType TASK_FINISHED =
new BuildEventType(TASK_FINISHED_VAL);
public static final BuildEventType MESSAGE_LOGGED =
new BuildEventType(MESSAGE_LOGGED_VAL);

/** Index to object mapping. */
private static final BuildEventType[] _objectMap = {
BUILD_STARTED,
BUILD_FINISHED,
TARGET_STARTED,
TARGET_FINISHED,
TASK_STARTED,
TASK_FINISHED,
MESSAGE_LOGGED
};

/** String map. XXX needs to be localized. */
private static final String[] _stringMap = {
"Build Started",
"Build Finished",
"Target Started",
"Target Finished",
"Task Started",
"Task Finished",
"Message Logged"
};

/** Map of corresponding method names in the BuildListener intereface. */
private static final String[] _methodNameMap = {
"buildStarted",
"buildFinished",
"targetStarted",
"targetFinished",
"taskStarted",
"taskFinished",
"messageLogged"
};

private static final Class[] _listenerMethodParam = { BuildEvent.class };
}

+ 48
- 22
src/antidote/org/apache/tools/ant/gui/event/EventBus.java View File

@@ -54,7 +54,7 @@
package org.apache.tools.ant.gui.event; package org.apache.tools.ant.gui.event;


import java.util.*; import java.util.*;
import javax.swing.SwingUtilities;
/** /**
* An event "bus" providing a centralized place for posting * An event "bus" providing a centralized place for posting
* and recieving generic application events. To receive events a class must * and recieving generic application events. To receive events a class must
@@ -142,29 +142,55 @@ public class EventBus {
* @param event Event to post. * @param event Event to post.
*/ */
public void postEvent(EventObject event) { public void postEvent(EventObject event) {
synchronized(_memberSet) {
// XXX need to insert code here to test whether we are being
// executed by the AWTEventQueue, or some other thread. If
// the latter, then we need to insert our execution on the
// AWTEventQueue thread as all code executing commands assumes
// that context.
EventDispatcher disp = new EventDispatcher(event);


for(int i = 0; i < _memberSet.length; i++) {
if(_memberSet[i] == null) continue;
// Events need to be dispatched on the AWTEvent thread, as the UI
// components assume that.
if(SwingUtilities.isEventDispatchThread()) {
disp.run();
}
else {
SwingUtilities.invokeLater(disp);
}
}


Iterator it = _memberSet[i].iterator();
while(it.hasNext()) {
BusMember next = (BusMember) it.next();
BusFilter filter = next.getBusFilter();
if(filter == null || filter.accept(event)) {
next.eventPosted(event);
}
// Check to see if the member cancelled the event. If so
// then don't send it on to the other members.
if(event instanceof AntEvent &&
((AntEvent)event).isCancelled()) break;
}
}
/** Class that performs the duty of dispatching events to the members. */
private class EventDispatcher implements Runnable {
/** Event to dispatch. */
private EventObject _event = null;
/**
* Standard ctor.
*
* @param event Event to dispatch.
*/
public EventDispatcher(EventObject event) {
_event = event;
}

/**
* Perform dispatching.
*
*/
public void run() {
synchronized(_memberSet) {
for(int i = 0; i < _memberSet.length; i++) {
if(_memberSet[i] == null) continue;
Iterator it = _memberSet[i].iterator();
while(it.hasNext()) {
BusMember next = (BusMember) it.next();
BusFilter filter = next.getBusFilter();
if(filter == null || filter.accept(_event)) {
next.eventPosted(_event);
}
// Check to see if the member cancelled the event. If so
// then don't send it on to the other members.
if(_event instanceof AntEvent &&
((AntEvent)_event).isCancelled()) break;
}
}
}
} }
} }
} }

+ 19
- 2
src/antidote/org/apache/tools/ant/gui/resources/action.properties View File

@@ -1,21 +1,24 @@
menus=File, Help
menus=File, Build, Help


actions=open, close, exit, about
actions=open, close, exit, about, startBuild, stopBuild


new.name=New new.name=New
new.shortDescription=Create a new project new.shortDescription=Create a new project
new.parentMenuName=File new.parentMenuName=File
new.icon=new.gif new.icon=new.gif
new.accelerator=control N


open.name=Open open.name=Open
open.shortDescription=Open an existing project open.shortDescription=Open an existing project
open.parentMenuName=File open.parentMenuName=File
open.icon=open.gif open.icon=open.gif
open.accelerator=control O


save.name=Save save.name=Save
save.shortDescription=Save the current project save.shortDescription=Save the current project
save.parentMenuName=File save.parentMenuName=File
save.icon=save.gif save.icon=save.gif
save.accelerator=control S


close.name=Close close.name=Close
close.shortDescription=Close the current project close.shortDescription=Close the current project
@@ -30,3 +33,17 @@ about.name=About
about.shortDescription=About this application about.shortDescription=About this application
about.parentMenuName=Help about.parentMenuName=Help
about.separator=true; about.separator=true;

startBuild.name=Start
startBuild.shortDescription=Start build of selected target
startBuild.parentMenuName=Build
startBuild.icon=start.gif
startBuild.separator=true
startBuild.accelerator=control B

stopBuild.name=Stop
stopBuild.shortDescription=Stop the current build
stopBuild.parentMenuName=Build
stopBuild.icon=stop.gif
stopBuild.accelerator=control K


+ 7
- 1
src/antidote/org/apache/tools/ant/gui/resources/antidote.properties View File

@@ -9,10 +9,16 @@ org.apache.tools.ant.gui.Antidote.right.editors=\
org.apache.tools.ant.gui.Antidote.left.editors=\ org.apache.tools.ant.gui.Antidote.left.editors=\
org.apache.tools.ant.gui.ProjectNavigator org.apache.tools.ant.gui.ProjectNavigator


# Configure the editors that appear on the bottom of the UI.
org.apache.tools.ant.gui.Antidote.bottom.editors=\
org.apache.tools.ant.gui.Console

# Set specific class properties. # Set specific class properties.
org.apache.tools.ant.gui.SourceEditor.name=Source org.apache.tools.ant.gui.SourceEditor.name=Source
org.apache.tools.ant.gui.PropertyEditor.name=Properties org.apache.tools.ant.gui.PropertyEditor.name=Properties
org.apache.tools.ant.gui.ProjectNavigator.name=Task Navigator
org.apache.tools.ant.gui.ProjectNavigator.name=Project
org.apache.tools.ant.gui.Console.name=Console
org.apache.tools.ant.gui.Console.logLevel=Log message level:


org.apache.tools.ant.gui.XMLFileFilter.description=XML Files org.apache.tools.ant.gui.XMLFileFilter.description=XML Files




BIN
src/antidote/org/apache/tools/ant/gui/resources/default.gif View File

Before After
Width: 26  |  Height: 26  |  Size: 1.2 KiB

BIN
src/antidote/org/apache/tools/ant/gui/resources/icon-small.gif View File

Before After
Width: 182  |  Height: 52  |  Size: 3.7 KiB

BIN
src/antidote/org/apache/tools/ant/gui/resources/start.gif View File

Before After
Width: 24  |  Height: 24  |  Size: 888 B

BIN
src/antidote/org/apache/tools/ant/gui/resources/stop.gif View File

Before After
Width: 24  |  Height: 24  |  Size: 888 B

+ 12
- 1
src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java View File

@@ -82,7 +82,7 @@ public class WindowUtils {
} }


/** /**
* Center the given child window with repsect to the child window.
* Center the given child window with repsect to the parent window.
* *
* @param parent Window to base centering on. * @param parent Window to base centering on.
* @param child Window to center. * @param child Window to center.
@@ -94,4 +94,15 @@ public class WindowUtils {
bounds.y + (bounds.height - size.height)/2); bounds.y + (bounds.height - size.height)/2);
} }


/**
* Center the given child window with repsect to the root.
*
* @param child Window to center.
*/
public static void centerWindow(Window child) {
Dimension rsize = child.getToolkit().getScreenSize();
Dimension size = child.getSize();
child.setLocation((rsize.width - size.width)/2,
(rsize.height - size.height)/2);
}
} }

Loading…
Cancel
Save