From c70641243c667093d23f689c7c28866fa661b1af Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Mon, 6 Nov 2000 12:52:51 +0000 Subject: [PATCH] Tow Antidote patches: *) Design document. *) can now write BuildEvents to console. Submitted by: Simeon Fitch git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268152 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 2 + src/antidote/ChangeLog | 40 +++ src/antidote/build.xml | 4 +- src/antidote/docs/design-overview.html | 258 ++++++++++++++++++ .../apache/tools/ant/gui/ActionManager.java | 47 +++- .../org/apache/tools/ant/gui/AntEditor.java | 2 + .../org/apache/tools/ant/gui/Antidote.java | 22 +- .../tools/ant/gui/BuildEventForwarder.java | 151 ++++++++++ .../org/apache/tools/ant/gui/Console.java | 117 +++++++- .../apache/tools/ant/gui/EventResponder.java | 3 + .../apache/tools/ant/gui/LogLevelEnum.java | 163 +++++++++++ .../org/apache/tools/ant/gui/Main.java | 13 +- .../tools/ant/gui/ProjectNavigator.java | 2 +- .../apache/tools/ant/gui/ProjectProxy.java | 112 ++++++-- .../apache/tools/ant/gui/ResourceManager.java | 21 ++ .../tools/ant/gui/command/BuildCmd.java | 90 ++++++ .../tools/ant/gui/command/LoadFileCmd.java | 2 +- .../tools/ant/gui/event/AntBuildEvent.java | 138 ++++++++++ .../tools/ant/gui/event/BuildEventType.java | 208 ++++++++++++++ .../apache/tools/ant/gui/event/EventBus.java | 70 +++-- .../tools/ant/gui/resources/action.properties | 21 +- .../ant/gui/resources/antidote.properties | 8 +- .../tools/ant/gui/resources/default.gif | Bin 0 -> 1212 bytes .../tools/ant/gui/resources/icon-small.gif | Bin 0 -> 3791 bytes .../apache/tools/ant/gui/resources/start.gif | Bin 0 -> 888 bytes .../apache/tools/ant/gui/resources/stop.gif | Bin 0 -> 888 bytes .../tools/ant/gui/util/WindowUtils.java | 13 +- 27 files changed, 1429 insertions(+), 78 deletions(-) create mode 100644 src/antidote/docs/design-overview.html create mode 100644 src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java create mode 100644 src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java create mode 100644 src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java create mode 100644 src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java create mode 100644 src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java create mode 100644 src/antidote/org/apache/tools/ant/gui/resources/default.gif create mode 100644 src/antidote/org/apache/tools/ant/gui/resources/icon-small.gif create mode 100644 src/antidote/org/apache/tools/ant/gui/resources/start.gif create mode 100644 src/antidote/org/apache/tools/ant/gui/resources/stop.gif diff --git a/WHATSNEW b/WHATSNEW index 35f9b32e0..dc8eca047 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -4,6 +4,8 @@ Changes from Ant 1.2 to the current sources Other changes: -------------- +* A GUI Frontend: Antidote + * New tasks: propertyfile, depend, antlr * Added output attribute to . diff --git a/src/antidote/ChangeLog b/src/antidote/ChangeLog index c491cd8cb..76657e1ab 100644 --- a/src/antidote/ChangeLog +++ b/src/antidote/ChangeLog @@ -1,3 +1,43 @@ +2000-11-05 Simeon H.K. Fitch + + * 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 + + * 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 + + * 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 * org/apache/tools/ant/gui/event/EventBus.java: Added interrupt diff --git a/src/antidote/build.xml b/src/antidote/build.xml index 8a37bc514..58141d0f3 100644 --- a/src/antidote/build.xml +++ b/src/antidote/build.xml @@ -50,8 +50,8 @@ + deprecation="on" + optimize="off" > diff --git a/src/antidote/docs/design-overview.html b/src/antidote/docs/design-overview.html new file mode 100644 index 000000000..bed6d8ee6 --- /dev/null +++ b/src/antidote/docs/design-overview.html @@ -0,0 +1,258 @@ + + + + Antidote Design Overview + + + + +

Antidote Design Overview

+ +

Version 0.1 (2000/11/02)

+ +

Authors: + Simeon H.K. Fitch +

+ +

Introduction

+ +

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 + ;-)

+ +

Overview

+ +

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.

+ +

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.

+ +

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.

+ +

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 EventBus. + +

+
+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)|
+   |               | |                | |             | |              |  
+   +---------------+ +----------------+ +-------------+ +--------------+
+
+    
+ +

Event Bus

+ +

The backbone of the application is the EventBus. Any + component of the application can post events to the + EventBus. Components that wish to receive events are + called BusMembers.

+ +

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

+ +

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

+ +

When a BusMember registers itself with the + EventBus, it must provide a (so called) interrupt + level which is a integer value defining a relative ordering + for dispatching EventObjects to BusMembers. The + purpose of this is to allow certain BusMember instances + to see an event before others, and in the case of AntEventEventBus class defines the interrupt level constants + MONITORING=1, VETOING=5, and RESPONDING=10 to + help define categories of members. The implied purpose being that: +

    + +
  • MONITORING: Just listens for events, like a logger + or status monitor.
  • + +
  • VETOING: 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 + RESPONDING group. An example of this might be to handle + a SaveAs event, whereby a VETOING 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 SaveAs + event could then be cancelled before the operation is executed.
  • + +
  • RESPONDING: Process events in a default manner, + knowing that the event has passed any VETOING members.
  • + +
+ + Within a specific interrupt level, the order in which members will + receive events is undefied. A BusMember may be registered + at a level that is +/- of one of the defined levels, as long as it + follows the constraint MONITORING <= interruptLevel <= + MAX_INTERRUPT.

+ + +

Actions and ActionManager

+ +

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

Commands and EventResponder

+ +

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 Command interface is defined to classify + code which performs some task or operation. This is distinct from + an Action, which is a user request for an operation. A + Command class is the encapsulation of the operation + itself.

+ +

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

+ +

When adding new Actions or general tasks to the + application, a Command object should be created to + encapsulate the behavior. This includes most operations which + modify the state of the data model.

+ +

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.

+ +

Data Model and Views

+ +

The data model is mainly defined by the Ant application, + primarily through the Project, Target, and + Task classes.

However, Antidote defines the class + ProjectProxy to act not only as a proxy to the real + Project class, but also as creator of GUI views of + the Project. A view is essentially a flyweight or + data proxy; it provides an orgainizational perspective on the actual + Project structure. For example, to render a + JTree version of the Project, one would call the + method ProjectProxy.getTreeModel(). Similarly, to get a + Document version of the Project, the + ProjectProxy,getDocument() method is used.

+ +

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.

+ +

Application Context

+ +

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 AppContext is the catch-all + class for containing the application state. Most modules and + Command classes require an instance of the + AppContext class. Because all state information in + contained in an AppContext instance, multiple instances + of Antidote can run inside the same JVM as long as each has it's + own AppContext. (Interestingly, two instances of the + Antidote could conceivably share an AppContext instance + through RMI, allowing remote interaction/collaboration.)

+ +

Configuration and ResourceManager

+ +

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 + antidote.properties, which is located (with other UI + resources) in the subpackage "resources".

+ +

To aid in the lookup of text properties, as well as other + resources like icons, a class called ResourceManager 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.

+ +

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 "org.apache.tools.ant.gui.About.message" for the text + message it should display. Therefore, the ResourceManager + method getString() takes a Class instance as + well as a String key. Please see the + ResourceManager documentation for more information. Given + this support, no user visible strings should appear in the source + code itself.

+ + + diff --git a/src/antidote/org/apache/tools/ant/gui/ActionManager.java b/src/antidote/org/apache/tools/ant/gui/ActionManager.java index 9274cc0a8..921a4979f 100644 --- a/src/antidote/org/apache/tools/ant/gui/ActionManager.java +++ b/src/antidote/org/apache/tools/ant/gui/ActionManager.java @@ -113,7 +113,24 @@ public class ActionManager { while(tok.hasMoreTokens()) { String name = tok.nextToken(); 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); } @@ -130,10 +147,13 @@ public class ActionManager { menus.put(parent, menu); } - if(action.isPreceededBySeparator()) { + // See if we should add a separator. + if(action.isPreceededBySeparator() && + menu.getMenuComponentCount() > 0) { menu.addSeparator(); } JMenuItem item = menu.add(action); + item.setAccelerator(action.getAccelerator()); addNiceStuff(item, action); } } @@ -171,6 +191,13 @@ public class ActionManager { // Set the action command so that it is consitent // no matter what language the display is in. 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(); if(tip != null) { button.setToolTipText(tip); @@ -202,6 +229,7 @@ public class ActionManager { /** Property name for the parent menu item. */ public static final String PARENT_MENU_NAME = "parentMenuName"; public static final String SEPARATOR = "separator"; + public static final String ACCELERATOR = "accelerator"; /** Unique id. */ private String _id = null; @@ -215,8 +243,14 @@ public class ActionManager { _id = id; putValue(NAME, getString(id, "name")); 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"); if(iconName != null) { @@ -232,7 +266,6 @@ public class ActionManager { ex.printStackTrace(); } } - } /** @@ -291,6 +324,10 @@ public class ActionManager { return (Icon) getValue(SMALL_ICON); } + public KeyStroke getAccelerator() { + return (KeyStroke) getValue(ACCELERATOR); + } + /** * Pass the action on to the EventBus. * diff --git a/src/antidote/org/apache/tools/ant/gui/AntEditor.java b/src/antidote/org/apache/tools/ant/gui/AntEditor.java index a9ed5fe87..2fb9a237e 100644 --- a/src/antidote/org/apache/tools/ant/gui/AntEditor.java +++ b/src/antidote/org/apache/tools/ant/gui/AntEditor.java @@ -54,6 +54,7 @@ package org.apache.tools.ant.gui; import javax.swing.JPanel; +import javax.swing.BorderFactory; /** * 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) { _context = context; + setBorder(BorderFactory.createTitledBorder(getName())); } /** diff --git a/src/antidote/org/apache/tools/ant/gui/Antidote.java b/src/antidote/org/apache/tools/ant/gui/Antidote.java index 956bc0fb9..b84c42adc 100644 --- a/src/antidote/org/apache/tools/ant/gui/Antidote.java +++ b/src/antidote/org/apache/tools/ant/gui/Antidote.java @@ -66,11 +66,6 @@ import java.lang.reflect.Constructor; * @author Simeon Fitch */ public class Antidote extends JPanel { - - - /** Logging console. */ - private Console _console = null; - /** Source of application state data. */ private AppContext _context = null; @@ -83,18 +78,25 @@ public class Antidote extends JPanel { _context = context; - _console = new Console(_context); - - // Add the various editors/views to the editing area. JSplitPane splitter = new JSplitPane(); splitter.add(JSplitPane.LEFT, populateEditors("left")); 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)); } diff --git a/src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java b/src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java new file mode 100644 index 000000000..c92b54bec --- /dev/null +++ b/src/antidote/org/apache/tools/ant/gui/BuildEventForwarder.java @@ -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 + * . + */ +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)); + } + + +} diff --git a/src/antidote/org/apache/tools/ant/gui/Console.java b/src/antidote/org/apache/tools/ant/gui/Console.java index defa1947c..7dbcff2cf 100644 --- a/src/antidote/org/apache/tools/ant/gui/Console.java +++ b/src/antidote/org/apache/tools/ant/gui/Console.java @@ -52,10 +52,13 @@ * . */ package org.apache.tools.ant.gui; - +import org.apache.tools.ant.gui.event.*; 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.util.EventObject; /** * Logging console display. @@ -63,22 +66,114 @@ import java.awt.Dimension; * @version $Revision$ * @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; - + /** Selection of logging levels. */ + private JComboBox _logLevel = null; + + /** + * Standard ctor. + * + * @param context Application 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.setEditable(false); 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; + } + } + } diff --git a/src/antidote/org/apache/tools/ant/gui/EventResponder.java b/src/antidote/org/apache/tools/ant/gui/EventResponder.java index 0b32da1b5..3b180cd8f 100644 --- a/src/antidote/org/apache/tools/ant/gui/EventResponder.java +++ b/src/antidote/org/apache/tools/ant/gui/EventResponder.java @@ -117,6 +117,9 @@ class EventResponder { if(command.equals(OpenCmd.ACTION_NAME)) { new OpenCmd(_context).execute(); } + else if(command.equals(BuildCmd.ACTION_NAME)) { + new BuildCmd(_context).execute(); + } else if(command.equals(CloseCmd.ACTION_NAME)) { new CloseCmd(_context).execute(); } diff --git a/src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java b/src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java new file mode 100644 index 000000000..0dd09c4a6 --- /dev/null +++ b/src/antidote/org/apache/tools/ant/gui/LogLevelEnum.java @@ -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 + * . + */ +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" + }; + +} diff --git a/src/antidote/org/apache/tools/ant/gui/Main.java b/src/antidote/org/apache/tools/ant/gui/Main.java index 492d44a34..3283e7ce8 100644 --- a/src/antidote/org/apache/tools/ant/gui/Main.java +++ b/src/antidote/org/apache/tools/ant/gui/Main.java @@ -52,7 +52,7 @@ * . */ package org.apache.tools.ant.gui; - +import org.apache.tools.ant.gui.util.WindowUtils; import javax.swing.*; import java.awt.BorderLayout; @@ -82,10 +82,19 @@ public class Main { f.getContentPane().add(BorderLayout.NORTH, 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.setVisible(true); // Hack around linux window placement annoyance. - f.setLocation(100, 100); + WindowUtils.centerWindow(f); } catch(Exception ex) { diff --git a/src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java b/src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java index 31ff1af89..523a2c5d1 100644 --- a/src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java +++ b/src/antidote/org/apache/tools/ant/gui/ProjectNavigator.java @@ -85,7 +85,7 @@ class ProjectNavigator extends AntEditor { JScrollPane scroller = new JScrollPane(_tree); add(scroller); - setPreferredSize(new Dimension(100, 100)); + setPreferredSize(new Dimension(150, 100)); } diff --git a/src/antidote/org/apache/tools/ant/gui/ProjectProxy.java b/src/antidote/org/apache/tools/ant/gui/ProjectProxy.java index b6979a43e..b2496fee5 100644 --- a/src/antidote/org/apache/tools/ant/gui/ProjectProxy.java +++ b/src/antidote/org/apache/tools/ant/gui/ProjectProxy.java @@ -54,10 +54,15 @@ package org.apache.tools.ant.gui; import org.apache.tools.ant.Project; 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.IOException; import javax.swing.tree.TreeModel; import javax.swing.text.Document; +import java.util.Enumeration; /** * This class provides the gateway interface to the data model for @@ -70,44 +75,59 @@ import javax.swing.text.Document; */ public class ProjectProxy { + /** Application context */ + private AppContext _context = null; /** The file where the project was last saved. */ private File _file = null; - /** The real Ant Project instance. */ 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. * * @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; + _context = context; loadProject(); } - + /** + * Load the project from the build file. + * + */ private void loadProject() throws IOException { _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; } + + /** + * 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; + } + } + } + } + } diff --git a/src/antidote/org/apache/tools/ant/gui/ResourceManager.java b/src/antidote/org/apache/tools/ant/gui/ResourceManager.java index 0ec6a5c87..9b03913f2 100644 --- a/src/antidote/org/apache/tools/ant/gui/ResourceManager.java +++ b/src/antidote/org/apache/tools/ant/gui/ResourceManager.java @@ -55,6 +55,9 @@ package org.apache.tools.ant.gui; import java.util.*; 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. @@ -143,4 +146,22 @@ public class ResourceManager { 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; + } + } diff --git a/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java b/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java new file mode 100644 index 000000000..684fb8859 --- /dev/null +++ b/src/antidote/org/apache/tools/ant/gui/command/BuildCmd.java @@ -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 + * . + */ +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(); + } + } +} diff --git a/src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java b/src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java index 473393c01..3fd3f8fa9 100644 --- a/src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java +++ b/src/antidote/org/apache/tools/ant/gui/command/LoadFileCmd.java @@ -95,7 +95,7 @@ public class LoadFileCmd implements Command { } else { try { - ProjectProxy project = new ProjectProxy(_file); + ProjectProxy project = new ProjectProxy(_context, _file); _context.setProject(project); } catch(IOException ex) { diff --git a/src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java b/src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java new file mode 100644 index 000000000..52f3f9072 --- /dev/null +++ b/src/antidote/org/apache/tools/ant/gui/event/AntBuildEvent.java @@ -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 + * . + */ +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(); + } + +} diff --git a/src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java b/src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java new file mode 100644 index 000000000..be23dada6 --- /dev/null +++ b/src/antidote/org/apache/tools/ant/gui/event/BuildEventType.java @@ -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 + * . + */ +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 }; +} diff --git a/src/antidote/org/apache/tools/ant/gui/event/EventBus.java b/src/antidote/org/apache/tools/ant/gui/event/EventBus.java index 2ab048f78..d5b1d6ea9 100644 --- a/src/antidote/org/apache/tools/ant/gui/event/EventBus.java +++ b/src/antidote/org/apache/tools/ant/gui/event/EventBus.java @@ -54,7 +54,7 @@ package org.apache.tools.ant.gui.event; import java.util.*; - +import javax.swing.SwingUtilities; /** * An event "bus" providing a centralized place for posting * and recieving generic application events. To receive events a class must @@ -142,29 +142,55 @@ public class EventBus { * @param event Event to post. */ 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; + } + } + } } } } 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 03fddbfef..bcf1c8617 100644 --- a/src/antidote/org/apache/tools/ant/gui/resources/action.properties +++ b/src/antidote/org/apache/tools/ant/gui/resources/action.properties @@ -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.shortDescription=Create a new project new.parentMenuName=File new.icon=new.gif +new.accelerator=control N open.name=Open open.shortDescription=Open an existing project open.parentMenuName=File open.icon=open.gif +open.accelerator=control O save.name=Save save.shortDescription=Save the current project save.parentMenuName=File save.icon=save.gif +save.accelerator=control S close.name=Close close.shortDescription=Close the current project @@ -30,3 +33,17 @@ about.name=About about.shortDescription=About this application about.parentMenuName=Help 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 + diff --git a/src/antidote/org/apache/tools/ant/gui/resources/antidote.properties b/src/antidote/org/apache/tools/ant/gui/resources/antidote.properties index 12b8249fb..8b6119161 100644 --- a/src/antidote/org/apache/tools/ant/gui/resources/antidote.properties +++ b/src/antidote/org/apache/tools/ant/gui/resources/antidote.properties @@ -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.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. org.apache.tools.ant.gui.SourceEditor.name=Source 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 diff --git a/src/antidote/org/apache/tools/ant/gui/resources/default.gif b/src/antidote/org/apache/tools/ant/gui/resources/default.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c42bd3ae1268697e3420ad88c83d8ba8dc59422 GIT binary patch literal 1212 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 literal 0 HcmV?d00001 diff --git a/src/antidote/org/apache/tools/ant/gui/resources/start.gif b/src/antidote/org/apache/tools/ant/gui/resources/start.gif new file mode 100644 index 0000000000000000000000000000000000000000..6a67694bed874061c749975414206db30a2f6d07 GIT binary patch literal 888 zcmW+#&8v=a5Ist|N?AzV1sakCvaunlv+}jEko};nC4ayvk&=ytWHmk#rF>+qA>F!m z%2Jt9);<=<;x%)po__B;&&-@T=lq`ICyyOEd~O-b_>BpzJz6`||D^2roR2?zr@;*} zgdq)O0AU0PCqx91L=kY9gARAd5sq|}qvx4G!PSEiLJHMb0ShqT0RTWm%ikK8!%lfr*i)l^DOxM>Y4s4$t%~Z!wy8Q*1V~P$*N4JU7E)^!1o6BQhf^ z8oY6OWOsLA=W_Ayd&DD2i@q!iEY^-b`&Y-#zw6gcdVjy{FJc*3I*Y}|Z6{vD+p9}k z_HKLf{QjG38@8Xivh?H2`G!_#%*>f{&hI&S>co+w=a;dJ-*k7}HqBuI+S(lOlsmvU-5ie6sG8 zGo0xxXOlEdsf!XrOtHjfZZZ8HR4{@WtYFJwIYT|EWF#|L$=1kW;WPvk||7SDiemyEabCJBR5FTQ|oI!Te?fGaHXrfM|O7?c5Wi1luBwR zEYy6wQ=tfDs6uUzrJAI7T`E$Us#JSsrDpEkT#8bbs)V^0O|RYVqV}-uYG=kpv(dtB zCWd8NmbE$U!wBRYm>79liSgTfRC6Ef@J!G07NdDL#bz@Lg)-I1b2BVPUys=`A~Uk0 z!5gPXc6S$cE*Jm4M?8|W=*zOeV*Ti|e|7BsyK%#$5BAIcB9?)rb69NNvGO9`UR&C> zf5*M&=igl4wDa`Ur5|5bZ*ARvVfEhSukWwzI(}ly+Dluzv*pZ#*H3=#d3*QJ*>{ir jT)FiA{^66~K0SSP@yzYL2W~vO`D@?Dhb!ARZN#zvQ?hZ% literal 0 HcmV?d00001 diff --git a/src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java b/src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java index 03bc38cb1..28582272d 100644 --- a/src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java +++ b/src/antidote/org/apache/tools/ant/gui/util/WindowUtils.java @@ -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 child Window to center. @@ -94,4 +94,15 @@ public class WindowUtils { 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); + } }