*) 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-ffa450edef68master
| @@ -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>. | ||||
| @@ -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 | ||||
| @@ -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> | ||||
| @@ -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> | |||||
| @@ -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. | ||||
| * | * | ||||
| @@ -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())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -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)); | ||||
| } | } | ||||
| @@ -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)); | |||||
| } | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -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(); | ||||
| } | } | ||||
| @@ -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" | |||||
| }; | |||||
| } | |||||
| @@ -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) { | ||||
| @@ -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)); | |||||
| } | } | ||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -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; | |||||
| } | |||||
| } | } | ||||
| @@ -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(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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) { | ||||
| @@ -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(); | |||||
| } | |||||
| } | |||||
| @@ -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 }; | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -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 | |||||
| @@ -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 | ||||
| @@ -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); | |||||
| } | |||||
| } | } | ||||