[kepler-dev] Copies of diva and vergil files?

Christopher Brooks cxh at eecs.berkeley.edu
Tue Feb 10 15:31:02 PST 2009


Hi David,
I don't see it as a problem that there multiple copies of the jar
files, I was really more curious about it.  It would be good to
detect problems with duplicates at the suite level . . .

Java dependency analysis is tricky because of reflection.  Doing
a simple scan of imports will get most of the dependencies though.

I do think that every .java file that is a duplicate is a potential
bug, especially if the file is mostly duplicated.  It is worth
keeping an eye on these files.

_Christopher

David Welker wrote:
> Hi Matt and Christopher and everyone,
> 
> With respect to the issue of multiple copies of the same jar:
> 
> The original idea was that each module should have a copy of all the jar 
> files it uses for management purposes. The idea being that this would 
> increase transparency, since we would know exactly which jars a module 
> depended on. Also, that this would allow for more flexibility, in that 
> you could easily remove a jar from your module without worrying that 
> another module would break as a result. Finally, there was the idea that 
> this would increase, somewhat, the independence of modules. The build 
> system actually has not ever prevented anyone from depending on the jars 
> in another module, certainly not from the command-line. However, back in 
> the day, it used to be that with the IDE files that were generated, each 
> module would not export its jars to other modules by default. Thus, to 
> get everything to look good in your IDE, each module had to have all the 
> jars it depended on. This was quite intentional.
> 
> However, my views, at least, on this issue have shifted. I think what we 
> need is better reporting abilities in order to increase transparency. In 
> much the same way that the build system now has a command "ant 
> report-overrides" that will show all the overrides that exist in a 
> particular suite, we could build a tool that precisely traces particular 
> classes that depend on jars to the jars they depend on. This would allow 
> us to increase our transparency goals without duplicating jars. Also, as 
> is, any change to a module might disturb another module that depends on 
> the trunk of that module (as opposed to a tag of the module that is 
> frozen) anyway. Given this, module developers should not worry about the 
> impact of removing a jar from a module for modules that depend on them 
> anymore than they worry about changing source code. In general, if you 
> depend on the trunk of a module, you have to be aware that it could 
> change and adapt accordingly. (In this case, if a module you depended on 
> removed a jar you needed, the remedy would be to include that jar in 
> your own module yourself.)
> 
> Anyway, at this point, there is no reason from a technical perspective 
> for their to be multiple instances of the same jar in the same suite. 
> (Note, however, that it is completely legitimate to have the same jar in 
> multiple modules that are not part of the same suite and who never share 
> a common lower priority module.) Of course, this problem of multiple 
> modules could be ameliorated to some degree by having a common lower 
> priority module (or modules) available to many suites that stores jars.  
> However, this solution has its own problems, since a suite that 
> incorporates such a common module (but not common functionality) is 
> going to have access to a lot of dependencies it does not need, which 
> means longer download times for suites that use such a module. Of 
> course, right now we already have longer download times that necessary, 
> given unnecessary duplication of jars. But, I think we could do better.
> 
> Furthermore, and I think this is also very problematic, if we have a 
> tendency to store jars in a common area, such jars are likely to 
> "check-in, but never check-out" of that common area since they will not 
> be associated with code that uses them. One would always be very worried 
> about breaking software in other modules when one is thinking of 
> deleting such a jar. This is especially problematic in the context of 
> upgrades. Worries that some other module, somewhere, might depend not 
> only on that jar, but that particular version of the jar, in such a 
> common module will make us very hesitant to upgrade.
> 
> For these reasons, I think we should stick to the following principle. 
> As a general matter, lower priority modules should only worry about 
> themselves and not about higher priority modules that depend on them. If 
> they want to upgrade a library, the should not worry too much about the 
> impact on higher priority modules that depend on them. Instead, the 
> solution if a higher priority module doesn't want to go along with the 
> upgrade is to take a forever frozen snapshot of the lower priority 
> module and store it in a tag. In this way, accessing the features of a 
> new version of a library and better ensuring that lower priority modules 
> can remain on the cutting edge (to the extent that they want to) is 
> enabled.
> 
> I think the better solution is as follows: Jars generally should be 
> stored in the lowest priority module that actually utilizes the 
> functionality of that jar. If the code is refactored in a module such 
> that a jar is no longer needed, that jar should be deleted. Higher 
> priority modules that depend on lower priority modules should not copy 
> such jars, *unless* they are also used in a different context where they 
> do not have access to that or another lower priority module that 
> contains the jar. (This will be a common case when modules are also 
> meant to be run stand-alone.) In such cases, there will be some jar 
> duplication, but it will be kept to a minimum.
> 
> We could then further develop a reporting mechanism that examines all 
> the suites in the system and (1) detects when there is jar duplication 
> within a particular suite so we can inquire whether it is justified and 
> (2) reports any jars that are stored in modules that do not utilize any 
> of the functionality of that jar so that such jars can be deleted. 
> Further, we could develop a system (ideally one that outputs a picture 
> in graphical form) that reports on the particular jars that a class 
> depends on in the context of a particular suite. Such tools would enable 
> us to minimize jar duplication on one hand, but avoid the problem of 
> jars "checking in, but never checking out" (kind of like the Hotel 
> California) and thereby allow for much easier jar upgrades and deletions.
> 
> David
>> Hi Christopher,
>>
>> In theory I think we are all on the same page here... we discussed
>> this the other day in our group and I think everyone wants there to be
>> only one copy of the ptolemy classes, with appropriate extension hooks
>> for altering behavior for Kepler in the cases where the behavior can't
>> be universally changed.  That said, this kind of refactoring takes
>> time, and practically speaking we need a way to temporarily break
>> things while designing and implementing a new architecture with
>> extensions.  Let's say it takes two to four weeks to redesign and
>> implement the new classes with their appropriate hooks in the case of
>> the reporting system. We need people to check in on a regular basis
>> (e.g., daily), exposing the incremental changes people are making in
>> order to have the 4 developers working on this feature to synchronize
>> their development.  Thus, we have used a copy and override model
>> during the development process.  Once the hooks are in place and it is
>> safe to move the code back to Ptolemy without breaking things for the
>> ptolemy team, we will do just that.   Do you have a suggestion as to
>> how we can check in daily incremental changes that would break ptolemy
>> (e.g., significantly change the GUI) without making a temporary copy?
>> The way I think of the modules in Kepler now is that each of them is a
>> self contained branch where experimental development can occur, but it
>> is fundamentally important that any overrides be merged back into the
>> main classes.  If they don't, then we'll end up with significant
>> incompatibilities due to bit rot and incompatible changes across
>> modules.
>>
>> That we have a lot of copies in many modules, especially in older
>> modules, is a problem that we need to resolve.  The jar copies are
>> also a problem, and I think can be solved with a good dependency
>> injection system where the jar files are managed in their own modules
>> that other modules can depend upon.  I'll bring this issue up with the
>> Kepler leadership team for discussion to find a solution.
>>
>> Matt
>>
>> On Mon, Feb 9, 2009 at 5:08 PM, Christopher Brooks
>> <cxh at eecs.berkeley.edu> wrote:
>>  
>>> Hi Debi,
>>> I've seen "temporary" turn into "shipped"  :-)
>>> Thomas Feng has a way to add dropdowns to the Toolbar.
>>> Thomas, can you write up something about this?
>>> It might help.
>>>
>>> It might make more sense to figure out how to embed the
>>> Ptolemy graph viewer inside a Pane instead of how it currently
>>> expect to use ptolemy.gui.Top, which extends JFrame.
>>>
>>>
>>> I was curious, so I took a look in the Kepler svn repository
>>> for java files in a /ptolemy/ directory and found these:
>>>
>>> ./modules/comad/src/ptolemy/domains/pn/kernel/PNDirector.java
>>> ./modules/comad/src/ptolemy/domains/pn/kernel/NPNDirector.java
>>> ./modules/runtimemonitor/src/ptolemy/actor/OrderedMerge.java
>>> ./modules/util/tests/src/test/ptolemy/util/OrderedResourceBundleTest.java 
>>>
>>> ./modules/util/src/ptolemy/vergil/actor/ActorController.java
>>> ./modules/util/src/ptolemy/vergil/basic/BasicGraphFrame.java
>>> ./modules/util/src/ptolemy/vergil/basic/MenuMapper.java
>>> ./modules/util/src/ptolemy/vergil/basic/BasicGraphController.java
>>> ./modules/reporting/src/ptolemy/vergil/actor/ActorEditorGraphController.java 
>>>
>>> ./modules/reporting/src/ptolemy/gui/Top.java
>>> ./modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>> ./modules/gaa/src/ptolemy/vergil/actor/ActorController.java
>>> ./modules/gaa/src/ptolemy/moml/MoMLParser.java
>>> ./modules/gaa/src/ptolemy/kernel/Entity.java
>>> ./modules/pn-branching/src/ptolemy/domains/sdf/lib/ArrayToSequence.java
>>> ./modules/core/src/ptolemy/kernel/util/ComponentEntityConfig.java
>>> ./modules/core/src/ptolemy/kernel/util/KeplerIconLoader.java
>>> ./modules/ppod-gui/src/ptolemy/actor/gui/PtolemyFrame.java
>>>
>>> There is also the diva file you checked in:
>>> ./modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>>
>>> I'm not sure about these:
>>> /modules/reporting/src/ptolemy.vergil.tree/PtolemyTreeCellRenderer.java
>>> /modules/reporting/src/ptolemy.vergil.tree/PTree.java
>>>
>>> I was curious, so below are Java files that share the same name:
>>>      8 Main.java
>>>      6 FileReader.java
>>>      5 Test.java
>>>      5 ParseException.java
>>>      4 Token.java
>>>      4 Sequence.java
>>>      4 HelloWorld.java
>>>      4 DataToken.java
>>>      4 CorbaIllegalActionException.java
>>>      4 CorbaIllegalActionExceptionHolder.java
>>>      4 CorbaIllegalActionExceptionHelper.java
>>>      3 XMLParser.java
>>>      3 Utilities.java
>>>      3 Transformer.java
>>>      3 Top.java
>>>      3 TokenMgrError.java
>>>      3 Time.java
>>>      3 TextFileWriter.java
>>>      3 StreamWriter.java
>>>      3 StreamDiscarder.java
>>>      3 StreamBuffer.java
>>>      3 SetMetadata.java
>>>      3 Report.java
>>>      3 RecordAssembler.java
>>>      3 Queue.java
>>>      3 Project.java
>>>      3 Port.java
>>>      3 OrderedMerge.java
>>>      3 Node.java
>>>      3 Multiplexor.java
>>>      3 MoMLSimpleApplication.java
>>>      3 List.java
>>>      3 Label.java
>>>      3 Kepler.java
>>>      3 IncomingCollectionManager.java
>>>      3 Entity.java
>>>      3 Counter.java
>>>      3 CollectionTransformer.java
>>>      3 BasicGraphController.java
>>>      3 AtomicCoactor.java
>>>      3 AsyncStreamRouter.java
>>>      3 All.java
>>>      3 ActorController.java
>>>      3 AbstractCollectionManager.java
>>> ...
>>> Interestingly, there are also lots of duplicated jar files:
>>>
>>>      6 batik-all-1.6.jar
>>>      5 commons-discovery.jar
>>>      4 xalan.jar
>>>      4 wsdl4j.jar
>>>      4 jaxrpc.jar
>>>      4 jargon_v2.0.jar
>>>      4 ij.jar
>>>      4 commons-logging.jar
>>>      4 axis.jar
>>>      3 xmlsec.jar
>>>      3 xml-apis.jar
>>>      3 xercesImpl.jar
>>>      3 wss4j-1.5.4.jar
>>>      3 mail.jar
>>>      3 log4j-1.2.8.jar
>>>      3 jython.jar
>>>      3 junit.jar
>>>      3 jode.jar
>>>      3 jdom.jar
>>>      3 cryptix-asn1.jar
>>>      3 cryptix32.jar
>>>      3 concurrent.jar
>>>      3 commons-httpclient-3.0.1.jar
>>>      3 commons-codec-1.3.jar
>>>      3 antlr.jar
>>>      3 ant.jar
>>>      2 xmlsec-1.4.1.jar
>>>      2 xml-apis-1.3.04.jar
>>>      2 xerces-2.4.0.jar
>>>      2 xdoclet-1.2.2.jar
>>>      2 xalan-2.7.0.jar
>>>      2 woden-impl-dom-1.0M8.jar
>>>      2 woden-api-1.0M8.jar
>>>      2 wmsd.jar
>>>      2 tar.jar
>>>      2 stax-api-1.0.1.jar
>>>      2 soaplab.jar
>>>      2 servlet.jar
>>>      2 servlet-api.jar
>>>      2 saaj.jar
>>>      2 saaj-impl.jar
>>>      2 saaj-api.jar
>>>      2 rampart-trust-1.4.jar
>>>      2 rampart-policy-1.4.jar
>>>      2 rampart-core-1.4.jar
>>>      2 qaqc.jar
>>>      2 puretls.jar
>>>      2 org.ecoinformatics.ecogrid.RegistryService-stub.jar
>>>      2 org.ecoinformatics.ecogrid.QueryService-stub.jar
>>>      2 org.ecoinformatics.ecogrid.PutService-stub.jar
>>>      2 org.ecoinformatics.ecogrid.IdentifierService-stub.jar
>>>      2 org.ecoinformatics.ecogrid.AuthenticationService-stub.jar
>>>      2 org.ecoinformatics.ecogrid.AuthenticatedQueryService-stub.jar
>>>      2 opensaml-1.1.jar
>>>      2 neethi-2.0.4.jar
>>>      2 mysql-connector-java-5.1.6-bin.jar
>>>      2 mex-1.4.jar
>>>      2 mail-1.4.jar
>>>      2 lsid-client.jar
>>>      2 log4j-1.3alpha-8.jar
>>>      2 kepler-tasks.jar
>>>      2 jts-1.4.0.jar
>>>      2 jsch-0.1.31.jar
>>>      2 jgss.jar
>>>      2 jena.jar
>>>      2 jaxrpc-spi.jar
>>>      2 jaxrpc-impl.jar
>>>      2 jaxb-impl.jar
>>>      2 jaxb-api.jar
>>>      2 jacorb.jar
>>>      2 ImageJ.jar
>>>      2 HelloWorld.jar
>>>      2 gt1.jar
>>>      2 gnu-regexp-1.0.8.jar
>>>      2 GeoVista-PCPVis.jar
>>>      2 forester.jar
>>>      2 cryptix.jar
>>>      2 commons-net-1.2.1.jar
>>>      2 commons-logging-1.1.jar
>>>      2 commons-httpclient-2.0-rc2.jar
>>>      2 cog-jglobus.jar
>>>      2 cog-axis.jar
>>>      2 CipresKeplerRegistry.jar
>>>      2 cipres_framework.jar
>>>      2 castor-0.9.5.jar
>>>      2 backport-util-concurrent-3.1.jar
>>>      2 axis-wsdl4j-1.2-RC1.jar
>>>      2 axis-saaj-1.4.jar
>>>      2 axis-jaxrpc-1.2-RC1.jar
>>>      2 axis2-kernel-1.4.jar
>>>      2 axis2-adb-1.4.jar
>>>      2 axis-1.4.jar
>>>      2 axiom-impl-1.2.7.jar
>>>      2 axiom-api-1.2.7.jar
>>>      2 antelope.jar
>>>      2 alltools.jar
>>>      2 alltools2.jar
>>>      2 activation.jar
>>>      2 activation-1.1.jar
>>>
>>> _Christopher
>>>
>>> debi staggs wrote:
>>>    
>>>> Hi Christopher,
>>>>
>>>> I checked in copies of those particular files because for the reporting
>>>> module we want to have a drop down box that is in the toolbar, that 
>>>> allows
>>>> users to change between three different views.  One view is of the 
>>>> workflow,
>>>> another is for the report designer, etc. Using the copies of these 
>>>> files is
>>>> very temporary and for testing purposes only.  We are working on a more
>>>> flexible and comprehensive way to adapt the GUI from extension 
>>>> points, but
>>>> just needed to over-ride those classes temporarily.
>>>>
>>>> Thanks,
>>>>
>>>> - Debi
>>>>
>>>>
>>>>
>>>> Christopher Brooks wrote:
>>>>      
>>>>> Hi Debi,
>>>>> Why are you checking in a copies of these file?
>>>>> Can we add extension points to the original versions?
>>>>>
>>>>> _Christopher
>>>>>
>>>>> staggs at ecoinformatics.org wrote:
>>>>>        
>>>>>> Author: staggs
>>>>>> Date: 2009-02-09 15:32:28 -0800 (Mon, 09 Feb 2009)
>>>>>> New Revision: 16583
>>>>>>
>>>>>> Added:
>>>>>>   trunk/modules/reporting/src/ptolemy/diva/
>>>>>>   trunk/modules/reporting/src/ptolemy/diva/gui/
>>>>>>   trunk/modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>>>>>   trunk/modules/reporting/src/ptolemy/vergil/actor/
>>>>>>
>>>>>> trunk/modules/reporting/src/ptolemy/vergil/actor/ActorEditorGraphController.java 
>>>>>>
>>>>>> Log:
>>>>>> Added combo box to frame for use in navigating between views.
>>>>>>
>>>>>> Added: trunk/modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>>>>> ===================================================================
>>>>>> --- trunk/modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>>>>>                      (rev 0)
>>>>>> +++ trunk/modules/reporting/src/ptolemy/diva/gui/GUIUtilities.java
>>>>>>  2009-02-09 23:32:28 UTC (rev 16583)
>>>>>> @@ -0,0 +1,514 @@
>>>>>> +/*
>>>>>> + Copyright (c) 1998-2006 The Regents of the University of California
>>>>>> + All rights reserved.
>>>>>> + Permission is hereby granted, without written agreement and without
>>>>>> + license or royalty fees, to use, copy, modify, and distribute this
>>>>>> + software and its documentation for any purpose, provided that the
>>>>>> above
>>>>>> + copyright notice and the following two paragraphs appear in all 
>>>>>> copies
>>>>>> + of this software.
>>>>>> +
>>>>>> + IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY 
>>>>>> PARTY
>>>>>> + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
>>>>>> + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
>>>>>> EVEN IF
>>>>>> + THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
>>>>>> + SUCH DAMAGE.
>>>>>> +
>>>>>> + THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
>>>>>> + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
>>>>>> + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
>>>>>> + PROVIDED HEREUNDER IS ON AN  BASIS, AND THE UNIVERSITY OF
>>>>>> + CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
>>>>>> UPDATES,
>>>>>> + ENHANCEMENTS, OR MODIFICATIONS.
>>>>>> +
>>>>>> + PT_COPYRIGHT_VERSION_2
>>>>>> + COPYRIGHTENDKEY
>>>>>> + */
>>>>>> +package ptolemy.diva.gui;
>>>>>> +
>>>>>> +import java.awt.Component;
>>>>>> +import java.awt.Dimension;
>>>>>> +import java.awt.Event;
>>>>>> +import java.awt.Insets;
>>>>>> +import java.awt.event.ActionListener;
>>>>>> +import java.awt.event.KeyEvent;
>>>>>> +import java.io.File;
>>>>>> +import java.io.PrintWriter;
>>>>>> +import java.io.StringWriter;
>>>>>> +import java.net.URL;
>>>>>> +
>>>>>> +import javax.swing.Action;
>>>>>> +import javax.swing.Icon;
>>>>>> +import javax.swing.ImageIcon;
>>>>>> +import javax.swing.JButton;
>>>>>> +import javax.swing.JComboBox;
>>>>>> +import javax.swing.JComponent;
>>>>>> +import javax.swing.JList;
>>>>>> +import javax.swing.JMenu;
>>>>>> +import javax.swing.JMenuItem;
>>>>>> +import javax.swing.JOptionPane;
>>>>>> +import javax.swing.JScrollPane;
>>>>>> +import javax.swing.JTextArea;
>>>>>> +import javax.swing.JToolBar;
>>>>>> +import javax.swing.KeyStroke;
>>>>>> +import javax.swing.ListSelectionModel;
>>>>>> +import javax.swing.event.ListSelectionListener;
>>>>>> +
>>>>>> +/**
>>>>>> + * A collection of utilities for the GUI.
>>>>>> + *
>>>>>> + * @author John Reekie
>>>>>> + * @author Steve Neuendorffer
>>>>>> + * @version $Id: GUIUtilities.java 47513 2007-12-07 06:32:21Z cxh $
>>>>>> + */
>>>>>> +public class GUIUtilities {
>>>>>> +    /** JDK1.2 doesn't have this string defined in 
>>>>>> javax.swing.Action.
>>>>>> +     *  This is the value that JDK1.3 uses.
>>>>>> +     */
>>>>>> +    public static final String ACCELERATOR_KEY = "AcceleratorKey";
>>>>>> +
>>>>>> +    /** JDK1.2 doesn't have this string defined in 
>>>>>> javax.swing.Action.
>>>>>> +     *  This is the value that JDK1.3 uses.
>>>>>> +     */
>>>>>> +    public static final String MNEMONIC_KEY = "MnemonicKey";
>>>>>> +
>>>>>> +    /** This key is used in an action to specify an icon used in
>>>>>> toolbars.
>>>>>> +     */
>>>>>> +    public static final String LARGE_ICON = "LargeIcon";
>>>>>> +
>>>>>> +    /** This key is used in an action to specify a rollover icon
>>>>>> +     *  used in toolbars.
>>>>>> +     */
>>>>>> +    public static final String ROLLOVER_ICON = "rolloverIcon";
>>>>>> +
>>>>>> +    /** This key is used in an action to specify a rollover selected
>>>>>> icon
>>>>>> +     *  used in toolbars.
>>>>>> +     */
>>>>>> +    public static final String ROLLOVER_SELECTED_ICON =
>>>>>> "rolloverSelectedIcon";
>>>>>> +
>>>>>> +    /** This key is used in an action to specify a selected icon
>>>>>> +     *  used in toolbars.
>>>>>> +     */
>>>>>> +    public static final String SELECTED_ICON = "selectedIcon";
>>>>>> +
>>>>>> +    /** Add a quick keystroke on the given pane for the given 
>>>>>> action.
>>>>>> +     *  The keystroke that is added is given in the ACCELERATOR_KEY
>>>>>> +     *  property that has been set in the action.  If the
>>>>>> ACCELERATOR_KEY
>>>>>> +     *  property has not been set, then do not add a hotkey.
>>>>>> +     */
>>>>>> +    public static void addHotKey(JComponent pane, Action action) {
>>>>>> +        addHotKey(pane, action, null);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add a quick keystroke on the given pane for the given 
>>>>>> action.
>>>>>> +     *  If the given keystroke is null, then use the ACCELERATOR_KEY
>>>>>> +     *  property that has been set in the action.  If the given
>>>>>> keystroke
>>>>>> +     *  is null, Otherwise, set the
>>>>>> +     *  ACCELERATOR_KEY property to the given key stroke.
>>>>>> +     */
>>>>>> +    public static void addHotKey(JComponent pane, Action action,
>>>>>> KeyStroke key) {
>>>>>> +        String name = (String) action.getValue(Action.NAME);
>>>>>> +
>>>>>> +        if (key == null) {
>>>>>> +            key = (KeyStroke) action.getValue(ACCELERATOR_KEY);
>>>>>> +        } else {
>>>>>> +            action.putValue(ACCELERATOR_KEY, key);
>>>>>> +        }
>>>>>> +
>>>>>> +        if (key != null) {
>>>>>> +            pane.registerKeyboardAction(action, name, key,
>>>>>> +                    JComponent.WHEN_IN_FOCUSED_WINDOW);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add icons to an action.  This method is used to associate
>>>>>> +     *  icons with the different states: unselected, rollover,
>>>>>> +     *  rollover selected, selected etc.
>>>>>> +     *
>>>>>> +     *  @param action The action to which the icons are added.
>>>>>> +     *  @param iconRoles A matrix of Strings, where each element
>>>>>> +     *  consists of two Strings, the absolute URL of the icon
>>>>>> +     *  and the key that represents the role of the icon.  The keys
>>>>>> +     *  are usually static fields from this class, such as
>>>>>> +     *  {@link #LARGE_ICON}, {@link #ROLLOVER_ICON},
>>>>>> +     *  {@link #ROLLOVER_SELECTED_ICON} or {@link #SELECTED_ICON}.
>>>>>> +     */
>>>>>> +    public static void addIcons(Action action, String[][] 
>>>>>> iconRoles) {
>>>>>> +        for (int i = 0; i < iconRoles.length; i++) {
>>>>>> +            URL img = 
>>>>>> action.getClass().getResource(iconRoles[i][0]);
>>>>>> +            if (img != null) {
>>>>>> +                ImageIcon icon = new ImageIcon(img);
>>>>>> +                action.putValue(iconRoles[i][1], icon);
>>>>>> +            }
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to a menu and return the menu item 
>>>>>> created.  If
>>>>>> +     * the tool tip is null, use the "tooltip" property already 
>>>>>> in the
>>>>>> +     * action, otherwise add the property to the action. (The 
>>>>>> mnemonic
>>>>>> +     * isn't added.)  The new menu item is added to the action as 
>>>>>> the
>>>>>> +     * "menuItem" property.  The menu item's text is set using the
>>>>>> +     * action's name, concatenated with a description of a keyboard
>>>>>> +     * accelerator, if one has been set previously on the action.
>>>>>> +     * The item will be enabled by default.
>>>>>> +     */
>>>>>> +    public static JMenuItem addMenuItem(JMenu menu, Action action) {
>>>>>> +        String label = (String) action.getValue(Action.NAME);
>>>>>> +        int mnemonic = 0;
>>>>>> +        Integer i = (Integer) action.getValue(MNEMONIC_KEY);
>>>>>> +
>>>>>> +        if (i != null) {
>>>>>> +            mnemonic = i.intValue();
>>>>>> +        }
>>>>>> +
>>>>>> +        return addMenuItem(menu, label, action, mnemonic, null, 
>>>>>> true);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to a menu and return the menu item 
>>>>>> created.  If
>>>>>> +     * the tool tip is null, use the "tooltip" property already 
>>>>>> in the
>>>>>> +     * action, otherwise add the property to the action. (The 
>>>>>> mnemonic
>>>>>> +     * isn't added.)  The new menu item is added to the action as 
>>>>>> the
>>>>>> +     * "menuItem" property.  The menu item's text is set using the
>>>>>> +     * action's name, concatenated with a description of a keyboard
>>>>>> +     * accelerator, if one has been set previously on the action.
>>>>>> +     * The item will be enabled by default.
>>>>>> +     */
>>>>>> +    public static JMenuItem addMenuItem(JMenu menu, Action action,
>>>>>> +            int mnemonic, String tooltip) {
>>>>>> +        String label = (String) action.getValue(Action.NAME);
>>>>>> +        return addMenuItem(menu, label, action, mnemonic, tooltip,
>>>>>> true);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to a menu and return the menu item 
>>>>>> created.  If
>>>>>> +     * the tool tip is null, use the "tooltip" property already 
>>>>>> in the
>>>>>> +     * action, otherwise add the property to the action. (The 
>>>>>> mnemonic
>>>>>> +     * isn't added.)  The new menu item is added to the action as 
>>>>>> the
>>>>>> +     * "menuItem" property.  The menu item's text is set to be 
>>>>>> "label",
>>>>>> +     * and is disabled or enabled according to "isEnabled."
>>>>>> +     */
>>>>>> +    public static JMenuItem addMenuItem(JMenu menu, String label,
>>>>>> +            Action action, int mnemonic, String tooltip, boolean
>>>>>> isEnabled) {
>>>>>> +        if (tooltip == null) {
>>>>>> +            tooltip = (String) action.getValue("tooltip");
>>>>>> +        } else {
>>>>>> +            action.putValue("tooltip", tooltip);
>>>>>> +        }
>>>>>> +
>>>>>> +        action.putValue("tooltip", tooltip);
>>>>>> +
>>>>>> +        JMenuItem item = menu.add(action);
>>>>>> +        item.setText(label);
>>>>>> +        item.setEnabled(isEnabled);
>>>>>> +        item.setMnemonic(mnemonic);
>>>>>> +        item.setToolTipText(tooltip);
>>>>>> +
>>>>>> +        KeyStroke key = (KeyStroke) 
>>>>>> action.getValue(ACCELERATOR_KEY);
>>>>>> +        item.setAccelerator(key);
>>>>>> +        action.putValue("menuItem", item);
>>>>>> +        return item;
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add the action to the given toolbar.
>>>>>> +     *  If the LARGE_ICON property is specified in the Action, 
>>>>>> then use
>>>>>> it
>>>>>> +     *  for the button.  We use this instead of SMALL_ICON, because
>>>>>> +     *  SMALL_ICON shows up when the action is added to a menu, 
>>>>>> and in
>>>>>> +     *  most cases we don't actually want an icon there.
>>>>>> +     *  If no icon is specified, then the button will just
>>>>>> +     *  have the name of the action.  If the "tooltip" property is
>>>>>> specified
>>>>>> +     *  in the action, then create a tooltip for the button with the
>>>>>> string.
>>>>>> +     *  The new button is added to the action as the "toolButton"
>>>>>> property.
>>>>>> +     *  The button is enabled by default.
>>>>>> +     */
>>>>>> +    +   +    +       +    +    public static JButton
>>>>>> addToolBarButton(JToolBar toolbar, Action action) {
>>>>>> +        Icon icon = (Icon) action.getValue(LARGE_ICON);
>>>>>> +        String label = null;
>>>>>> +
>>>>>> +        if (icon == null) {
>>>>>> +            label = (String) action.getValue(Action.NAME);
>>>>>> +        }
>>>>>> +
>>>>>> +        return addToolBarButton(toolbar, action, null, icon, label,
>>>>>> true);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to the toolbar.  If the tool tip is null, use
>>>>>> +     * the "tooltip" property already in the action, otherwise 
>>>>>> add the
>>>>>> +     * property to the action. The new button is added to the action
>>>>>> +     * as the "toolButton" property.  The button represented by 
>>>>>> an icon
>>>>>> +     * (no text) and is enabled by default.
>>>>>> +     */
>>>>>> +    public static JButton addToolBarButton(JToolBar toolbar, Action
>>>>>> action,
>>>>>> +            String tooltip, Icon icon) {
>>>>>> +        return addToolBarButton(toolbar, action, tooltip, icon, 
>>>>>> null,
>>>>>> true);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to the toolbar.  If the tool tip is null, use
>>>>>> +     * the "tooltip" property already in the action, otherwise 
>>>>>> add the
>>>>>> +     * property to the action. The new button is added to the action
>>>>>> +     * as the "toolButton" property.  The button represented by 
>>>>>> an icon
>>>>>> +     * (no text) and is enabled by default.
>>>>>> +     */
>>>>>> +    public static JButton addToolBarButton(JToolBar toolbar, Action
>>>>>> action,
>>>>>> +            String tooltip, Icon icon, boolean isEnabled) {
>>>>>> +        return addToolBarButton(toolbar, action, tooltip, icon, 
>>>>>> null,
>>>>>> isEnabled);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to the toolbar.  If the tool tip is null, use
>>>>>> +     * the "tooltip" property already in the action, otherwise 
>>>>>> add the
>>>>>> +     * property to the action. The new button is added to the action
>>>>>> +     * as the "toolButton" property.  The button represented by text
>>>>>> +     * (no icon) and is enabled by default.
>>>>>> +     */
>>>>>> +    public static JButton addToolBarButton(JToolBar toolbar, Action
>>>>>> action,
>>>>>> +            String tooltip, String lbl) {
>>>>>> +        return addToolBarButton(toolbar, action, tooltip, null, lbl,
>>>>>> true);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add an action to the toolbar.  If either an icon or a text
>>>>>> string
>>>>>> +     * are specified (non-null), they are added.  The button is 
>>>>>> enabled
>>>>>> by
>>>>>> +     * default.
>>>>>> +     */
>>>>>> +    public static JButton addToolBarButton(JToolBar toolbar, Action
>>>>>> action,
>>>>>> +            String tooltip, Icon icon, String lbl) {
>>>>>> +        return addToolBarButton(toolbar, action, tooltip, icon, lbl,
>>>>>> true);
>>>>>> +    }
>>>>>> +    +    /**Add a ComboBox drop down to the toolbar. */
>>>>>> +   +    +
>>>>>> +    public static JComboBox addComboBoxViewChanger(JToolBar toolbar,
>>>>>> Action action, String tooltip, +            Icon icon, String lbl, 
>>>>>> boolean
>>>>>> isEnabled) {
>>>>>> +       +        if (tooltip == null) {
>>>>>> +            tooltip = (String) action.getValue("tooltip");
>>>>>> +        } else {
>>>>>> +            action.putValue("tooltip", tooltip);
>>>>>> +        }
>>>>>> +       +        String[] viewsList = {"Edit", "Report", "View"};
>>>>>> +        JComboBox comboViewList = new JComboBox(viewsList);
>>>>>> +        //comboViewList.setSelectedIndex(2);
>>>>>> +        comboViewList.addActionListener(comboViewList);
>>>>>> +        comboViewList.setSize(new Dimension(1, 1));
>>>>>> +        comboViewList.setPreferredSize(new
>>>>>> Dimension(comboViewList.getPreferredSize().width,comboViewList.getPreferredSize().height)); 
>>>>>>
>>>>>> +        System.out.println(comboViewList.getSize());    +
>>>>>>  toolbar.add(comboViewList);   +        return comboViewList;
>>>>>> +    +    }
>>>>>> +   +
>>>>>> +   +    // public static JComboBox 
>>>>>> createComboBoxViewChanger(JToolBar
>>>>>> toolbar){    +        //    String[] viewNames = {"Edit Workflow", 
>>>>>> "Design
>>>>>> Report", "View Report" };
>>>>>> +         //   JComboBox combo = new JComboBox(viewNames);
>>>>>> +        //    return combo;
>>>>>> +    //    }
>>>>>> +     +   +   +    //public static JComboBox addViewsList(JToolBar
>>>>>> toolbar, Action action) {
>>>>>> +        //return addViewsList(toolbar, action);
>>>>>> +    //}
>>>>>> +   +
>>>>>> +    /** Add an action to the toolbar.  If the tool tip is null, use
>>>>>> +     * the "tooltip" property already in the action, otherwise 
>>>>>> add the
>>>>>> +     * property to the action.  The new button is added to the 
>>>>>> action
>>>>>> +     * as the "toolButton" property.  If either an icon or a text
>>>>>> string
>>>>>> +     * are specified (non-null), they are added.
>>>>>> +     */
>>>>>> +    public static JButton addToolBarButton(JToolBar toolbar, Action
>>>>>> action,
>>>>>> +            String tooltip, Icon icon, String lbl, boolean 
>>>>>> isEnabled) {
>>>>>> +        if (tooltip == null) {
>>>>>> +            tooltip = (String) action.getValue("tooltip");
>>>>>> +        } else {
>>>>>> +            action.putValue("tooltip", tooltip);
>>>>>> +        }
>>>>>> +
>>>>>> +        JButton button = toolbar.add(action);
>>>>>> +        button.setToolTipText(tooltip);
>>>>>> +        button.setText(null);
>>>>>> +        button.setRequestFocusEnabled(false);
>>>>>> +
>>>>>> +        if (icon != null) {
>>>>>> +            button.setIcon(icon);
>>>>>> +        }
>>>>>> +
>>>>>> +        if (lbl != null) {
>>>>>> +            button.setText(lbl);
>>>>>> +        }
>>>>>> +
>>>>>> +        Icon rolloverIcon = (Icon) action.getValue(ROLLOVER_ICON);
>>>>>> +        if (rolloverIcon != null) {
>>>>>> +            button.setRolloverIcon(rolloverIcon);
>>>>>> +        }
>>>>>> +        Icon rolloverSelectedIcon = (Icon) action
>>>>>> +                .getValue(ROLLOVER_SELECTED_ICON);
>>>>>> +        if (rolloverSelectedIcon != null) {
>>>>>> +            button.setRolloverSelectedIcon(rolloverSelectedIcon);
>>>>>> +        }
>>>>>> +        Icon selectedIcon = (Icon) action.getValue(SELECTED_ICON);
>>>>>> +        if (selectedIcon != null) {
>>>>>> +            button.setSelectedIcon(selectedIcon);
>>>>>> +        }
>>>>>> +
>>>>>> +        button.setMargin(new Insets(0, 0, 0, 0));
>>>>>> +
>>>>>> +        //        button.setBorderPainted(false);
>>>>>> +        button.setBorderPainted(true);
>>>>>> +        button.setEnabled(isEnabled);
>>>>>> +        action.putValue("toolBarButton", button);
>>>>>> +        return button;
>>>>>> +    }
>>>>>> +
>>>>>> +    /**
>>>>>> +     * Return a string that contains the original string, limited to
>>>>>> the
>>>>>> +     * given number of characters.  If the string is truncated,
>>>>>> ellipses
>>>>>> +     * will be appended to the end of the string
>>>>>> +     */
>>>>>> +    public static String ellipsis(String string, int length) {
>>>>>> +        if (string.length() > length) {
>>>>>> +            return string.substring(0, length - 3) + "...";
>>>>>> +        }
>>>>>> +
>>>>>> +        return string;
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Get the extension of a file. Return a null string is there
>>>>>> +     * is no extension.
>>>>>> +     */
>>>>>> +    public static String getFileExtension(File file) {
>>>>>> +        String str = file.getName();
>>>>>> +        int i = str.lastIndexOf('.');
>>>>>> +
>>>>>> +        if (i > 0) {
>>>>>> +            return str.substring(i + 1);
>>>>>> +        } else {
>>>>>> +            return "";
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Return a good string representation of the given keystroke,
>>>>>> since
>>>>>> +     *  the toString method returns more garbage than we want to 
>>>>>> see in
>>>>>> a
>>>>>> +     *  user interface.
>>>>>> +     */
>>>>>> +    public static String keyStrokeToString(KeyStroke key) {
>>>>>> +        int modifiers = key.getModifiers();
>>>>>> +        StringBuffer buffer = new StringBuffer();
>>>>>> +
>>>>>> +        if ((modifiers & Event.SHIFT_MASK) == Event.SHIFT_MASK) {
>>>>>> +            buffer.append("(Shift-");
>>>>>> +            buffer.append(KeyEvent.getKeyText(key.getKeyCode()));
>>>>>> +            buffer.append(")");
>>>>>> +        }
>>>>>> +
>>>>>> +        if ((modifiers & Event.CTRL_MASK) == Event.CTRL_MASK) {
>>>>>> +            buffer.append("(Ctrl-");
>>>>>> +            buffer.append(KeyEvent.getKeyText(key.getKeyCode()));
>>>>>> +            buffer.append(")");
>>>>>> +        }
>>>>>> +
>>>>>> +        if ((modifiers & Event.META_MASK) == Event.META_MASK) {
>>>>>> +            buffer.append("(Meta-");
>>>>>> +            buffer.append(KeyEvent.getKeyText(key.getKeyCode()));
>>>>>> +            buffer.append(")");
>>>>>> +        }
>>>>>> +
>>>>>> +        if ((modifiers & Event.ALT_MASK) == Event.ALT_MASK) {
>>>>>> +            buffer.append("(Alt-");
>>>>>> +            buffer.append(KeyEvent.getKeyText(key.getKeyCode()));
>>>>>> +            buffer.append(")");
>>>>>> +        }
>>>>>> +
>>>>>> +        if (modifiers == 0) {
>>>>>> +            buffer.append("(");
>>>>>> +            buffer.append(KeyEvent.getKeyText(key.getKeyCode()));
>>>>>> +            buffer.append(")");
>>>>>> +        }
>>>>>> +
>>>>>> +        return buffer.toString();
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Display an exception in a nice user-oriented way.  
>>>>>> Instead of
>>>>>> +     *  displaying the whole stack trace, just display the exception
>>>>>> message
>>>>>> +     *  and a button for displaying the whole stack trace.
>>>>>> +     */
>>>>>> +    public static void showException(Component parent, Exception e,
>>>>>> String info) {
>>>>>> +        Object[] message = new Object[1];
>>>>>> +        String string;
>>>>>> +
>>>>>> +        if (info != null) {
>>>>>> +            string = info + "\n" + e.getMessage();
>>>>>> +        } else {
>>>>>> +            string = e.getMessage();
>>>>>> +        }
>>>>>> +
>>>>>> +        message[0] = ellipsis(string, 400);
>>>>>> +
>>>>>> +        Object[] options = { "Dismiss", "Display Stack Trace" };
>>>>>> +
>>>>>> +        // Show the MODAL dialog
>>>>>> +        int selected = JOptionPane.showOptionDialog(parent, message,
>>>>>> +                "Exception Caught", JOptionPane.YES_NO_OPTION,
>>>>>> +                JOptionPane.WARNING_MESSAGE, null, options,
>>>>>> options[0]);
>>>>>> +
>>>>>> +        if (selected == 1) {
>>>>>> +            showStackTrace(parent, e, info);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Display a stack trace dialog. Eventually, the dialog should
>>>>>> +     * be able to email us a bug report.
>>>>>> +     */
>>>>>> +    public static void showStackTrace(Component parent, Exception 
>>>>>> e) {
>>>>>> +        showStackTrace(parent, e, null);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Display a stack trace dialog. Eventually, the dialog should
>>>>>> +     * be able to email us a bug report. The "info" argument is a
>>>>>> +     * string printed at the top of the dialog instead of the 
>>>>>> Exception
>>>>>> +     * message.
>>>>>> +     */
>>>>>> +    public static void showStackTrace(Component parent, Exception e,
>>>>>> String info) {
>>>>>> +        // Show the stack trace in a scrollable text area.
>>>>>> +        StringWriter sw = new StringWriter();
>>>>>> +        PrintWriter pw = new PrintWriter(sw);
>>>>>> +        e.printStackTrace(pw);
>>>>>> +
>>>>>> +        JTextArea text = new JTextArea(sw.toString(), 60, 80);
>>>>>> +        JScrollPane stext = new JScrollPane(text);
>>>>>> +        stext.setPreferredSize(new Dimension(400, 200));
>>>>>> +        text.setCaretPosition(0);
>>>>>> +        text.setEditable(false);
>>>>>> +
>>>>>> +        // We want to stack the text area with another message
>>>>>> +        Object[] message = new Object[2];
>>>>>> +        String string;
>>>>>> +
>>>>>> +        if (info != null) {
>>>>>> +            string = info + "\n" + e.getMessage();
>>>>>> +        } else {
>>>>>> +            string = e.getMessage();
>>>>>> +        }
>>>>>> +
>>>>>> +        message[0] = ellipsis(string, 400);
>>>>>> +        message[1] = stext;
>>>>>> +
>>>>>> +        // Show the MODAL dialog
>>>>>> +        JOptionPane.showMessageDialog(parent, message, "Exception
>>>>>> Caught",
>>>>>> +                JOptionPane.WARNING_MESSAGE);
>>>>>> +    }
>>>>>> +
>>>>>> +    public static void addComboBoxViewChanger(JToolBar toolbar,
>>>>>> +            Action viewAction) {
>>>>>> +        String[] ViewsList = {"Workflow Editor", "Report Designer",
>>>>>> "Report Viewer" };
>>>>>> +        JComboBox viewsCombo = new JComboBox(ViewsList);
>>>>>> +        toolbar.add(viewsCombo);
>>>>>> +       +    }
>>>>>> +}
>>>>>>
>>>>>> Added:
>>>>>> trunk/modules/reporting/src/ptolemy/vergil/actor/ActorEditorGraphController.java 
>>>>>>
>>>>>> ===================================================================
>>>>>> ---
>>>>>> trunk/modules/reporting/src/ptolemy/vergil/actor/ActorEditorGraphController.java 
>>>>>>
>>>>>>                            (rev 0)
>>>>>> +++
>>>>>> trunk/modules/reporting/src/ptolemy/vergil/actor/ActorEditorGraphController.java 
>>>>>>
>>>>>>    2009-02-09 23:32:28 UTC (rev 16583)
>>>>>> @@ -0,0 +1,766 @@
>>>>>> +/* The graph controller for vergil.
>>>>>> +
>>>>>> + Copyright (c) 1998-2008 The Regents of the University of 
>>>>>> California.
>>>>>> + All rights reserved.
>>>>>> + Permission is hereby granted, without written agreement and without
>>>>>> + license or royalty fees, to use, copy, modify, and distribute this
>>>>>> + software and its documentation for any purpose, provided that the
>>>>>> above
>>>>>> + copyright notice and the following two paragraphs appear in all 
>>>>>> copies
>>>>>> + of this software.
>>>>>> +
>>>>>> + IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY 
>>>>>> PARTY
>>>>>> + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
>>>>>> + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
>>>>>> EVEN IF
>>>>>> + THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
>>>>>> + SUCH DAMAGE.
>>>>>> +
>>>>>> + THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
>>>>>> + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
>>>>>> + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
>>>>>> + PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
>>>>>> + CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
>>>>>> UPDATES,
>>>>>> + ENHANCEMENTS, OR MODIFICATIONS.
>>>>>> +
>>>>>> + PT_COPYRIGHT_VERSION_2
>>>>>> + COPYRIGHTENDKEY
>>>>>> +
>>>>>> + */
>>>>>> +package ptolemy.vergil.actor;
>>>>>> +
>>>>>> +import java.awt.Dimension;
>>>>>> +import java.awt.Toolkit;
>>>>>> +import java.awt.event.ActionEvent;
>>>>>> +import java.awt.event.ActionListener;
>>>>>> +import java.awt.event.InputEvent;
>>>>>> +import java.awt.event.KeyEvent;
>>>>>> +import java.awt.geom.AffineTransform;
>>>>>> +import java.awt.geom.NoninvertibleTransformException;
>>>>>> +import java.awt.geom.Point2D;
>>>>>> +import java.awt.geom.Rectangle2D;
>>>>>> +import java.lang.reflect.Constructor;
>>>>>> +import java.util.Iterator;
>>>>>> +
>>>>>> +import javax.swing.Action;
>>>>>> +import javax.swing.JComboBox;
>>>>>> +import javax.swing.JMenu;
>>>>>> +import javax.swing.JMenuItem;
>>>>>> +import javax.swing.JToolBar;
>>>>>> +
>>>>>> +import ptolemy.actor.gui.Configuration;
>>>>>> +import ptolemy.kernel.CompositeEntity;
>>>>>> +import ptolemy.kernel.util.InternalErrorException;
>>>>>> +import ptolemy.kernel.util.NamedObj;
>>>>>> +import ptolemy.kernel.util.StringAttribute;
>>>>>> +import ptolemy.moml.MoMLChangeRequest;
>>>>>> +import ptolemy.util.MessageHandler;
>>>>>> +import ptolemy.vergil.basic.BasicGraphFrame;
>>>>>> +import ptolemy.vergil.basic.NamedObjController;
>>>>>> +import ptolemy.vergil.kernel.AttributeController;
>>>>>> +import ptolemy.vergil.kernel.Link;
>>>>>> +import ptolemy.vergil.kernel.PortDialogAction;
>>>>>> +import ptolemy.vergil.kernel.RelationController;
>>>>>> +import ptolemy.vergil.toolbox.FigureAction;
>>>>>> +import ptolemy.vergil.toolbox.MenuItemFactory;
>>>>>> +import ptolemy.vergil.toolbox.SnapConstraint;
>>>>>> +import ptolemy.vergil.unit.ConfigureUnitsAction;
>>>>>> +import diva.canvas.CanvasComponent;
>>>>>> +import diva.canvas.CanvasUtilities;
>>>>>> +import diva.canvas.Figure;
>>>>>> +import diva.canvas.FigureLayer;
>>>>>> +import diva.canvas.Site;
>>>>>> +import diva.canvas.connector.AutonomousSite;
>>>>>> +import diva.canvas.connector.Connector;
>>>>>> +import diva.canvas.connector.ConnectorManipulator;
>>>>>> +import diva.canvas.event.LayerEvent;
>>>>>> +import diva.canvas.event.MouseFilter;
>>>>>> +import diva.canvas.interactor.AbstractInteractor;
>>>>>> +import diva.canvas.interactor.ActionInteractor;
>>>>>> +import diva.canvas.interactor.CompositeInteractor;
>>>>>> +import diva.canvas.interactor.GrabHandle;
>>>>>> +import diva.canvas.interactor.Interactor;
>>>>>> +import diva.graph.GraphPane;
>>>>>> +import diva.graph.JGraph;
>>>>>> +import diva.graph.NodeRenderer;
>>>>>> +import diva.gui.GUIUtilities;
>>>>>> +import diva.gui.toolbox.FigureIcon;
>>>>>> +import diva.gui.toolbox.JContextMenu;
>>>>>> +import diva.util.UserObjectContainer;
>>>>>> +
>>>>>>
>>>>>> +////////////////////////////////////////////////////////////////////////// 
>>>>>>
>>>>>> +//// ActorEditorGraphController
>>>>>> +
>>>>>> +/**
>>>>>> + A Graph Controller for the Ptolemy II schematic editor.  In 
>>>>>> addition
>>>>>> to the
>>>>>> + interaction allowed in the viewer, this controller allows nodes 
>>>>>> to be
>>>>>> + dragged and dropped onto its graph.  Relations can be created by
>>>>>> + control-clicking on the background.  Links can be created by
>>>>>> control-clicking
>>>>>> + and dragging on a port or a relation.  In addition links can be
>>>>>> created by
>>>>>> + clicking and dragging on the ports that are inside an entity.
>>>>>> + Anything can be deleted by selecting it and pressing
>>>>>> + the delete key on the keyboard.
>>>>>> +
>>>>>> + @author Steve Neuendorffer, Contributor: Edward A. Lee, Bert 
>>>>>> Rodiers
>>>>>> + @version $Id: ActorEditorGraphController.java 52222 2009-01-28
>>>>>> 01:55:29Z rodiers $
>>>>>> + @since Ptolemy II 2.0
>>>>>> + @Pt.ProposedRating Red (eal)
>>>>>> + @Pt.AcceptedRating Red (johnr)
>>>>>> + */
>>>>>> +public class ActorEditorGraphController extends
>>>>>> ActorViewerGraphController {
>>>>>> +    /** Create a new basic controller with default
>>>>>> +     *  terminal and edge interactors.
>>>>>> +     */
>>>>>> +    public ActorEditorGraphController() {
>>>>>> +        super();
>>>>>> +    }
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    ////                         public 
>>>>>> methods                    ////
>>>>>> +
>>>>>> +    /** Add commands to the specified menu and toolbar, as 
>>>>>> appropriate
>>>>>> +     *  for this controller.  In this class, commands are added to
>>>>>> create
>>>>>> +     *  ports and relations.
>>>>>> +     *  @param menu The menu to add to, or null if none.
>>>>>> +     *  @param toolbar The toolbar to add to, or null if none.
>>>>>> +     */
>>>>>> +    public void addToMenuAndToolbar(JMenu menu, JToolBar toolbar) {
>>>>>> +        super.addToMenuAndToolbar(menu, toolbar);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu, 
>>>>>> _newInputPortAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> _newInputPortAction);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu, 
>>>>>> _newOutputPortAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> _newOutputPortAction);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu, 
>>>>>> _newInoutPortAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> _newInoutPortAction);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu,
>>>>>> _newInputMultiportAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> +                _newInputMultiportAction);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu,
>>>>>> _newOutputMultiportAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> +                _newOutputMultiportAction);
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu,
>>>>>> _newInoutMultiportAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> +                _newInoutMultiportAction);
>>>>>> +
>>>>>> +        menu.addSeparator();
>>>>>> +
>>>>>> +        // Add an item that adds new relations.
>>>>>> +        diva.gui.GUIUtilities.addMenuItem(menu, _newRelationAction);
>>>>>> +        diva.gui.GUIUtilities.addToolBarButton(toolbar,
>>>>>> _newRelationAction);
>>>>>> +        //diva.gui.GUIUtilities.addComboBoxViewChanger(toolbar,
>>>>>> _changeViewAction);
>>>>>> +        +       String[] ViewsList = {"Workflow Editor", "Report
>>>>>> Designer", "Report Viewer" };
>>>>>> +        JComboBox viewsCombo = new JComboBox(ViewsList);
>>>>>> +        viewsCombo.setSelectedIndex(0);
>>>>>> +        Object selectedIndex = 
>>>>>> viewsCombo.getModel().getSelectedItem();
>>>>>> +        String selectedView = viewsCombo.getName();
>>>>>> +       +
>>>>>>  viewsCombo.addActionListener(_changeViewAction(selectedView));
>>>>>> +        //TODO add ActionEvents for each Name   +
>>>>>>  toolbar.add(viewsCombo);
>>>>>> +           +        }
>>>>>> +       +
>>>>>> +    /** Set the configuration.  The configuration is used when
>>>>>> +     *  opening documentation files.
>>>>>> +     *  @param configuration The configuration.
>>>>>> +     */
>>>>>> +    public void setConfiguration(Configuration configuration) {
>>>>>> +        super.setConfiguration(configuration);
>>>>>> +
>>>>>> +        if (_portDialogAction != null) {
>>>>>> +            _portDialogAction.setConfiguration(configuration);
>>>>>> +        }
>>>>>> +
>>>>>> +        if (_configureUnitsAction != null) {
>>>>>> +            _configureUnitsAction.setConfiguration(configuration);
>>>>>> +        }
>>>>>> +
>>>>>> +        if (_listenToActorFactory != null) {
>>>>>> +            _listenToActorFactory.setConfiguration(configuration);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    ////                         protected 
>>>>>> methods                 ////
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    //// NewRelationAction
>>>>>> +    /** An action to create a new relation. */
>>>>>> +    public class NewRelationAction extends FigureAction {
>>>>>> +        /** Create an action that creates a new relation.
>>>>>> +         */
>>>>>> +        public NewRelationAction() {
>>>>>> +            this(null);
>>>>>> +        }
>>>>>> +
>>>>>> +        /** Create an action that creates a new relation.
>>>>>> +         *  @param iconRoles A matrix of Strings, where each element
>>>>>> +         *  consists of two Strings, the absolute URL of the icon
>>>>>> +         *  and the key that represents the role of the icon.  
>>>>>> The keys
>>>>>> +         *  are usually static fields from this class, such as
>>>>>> +         *  {@link diva.gui.GUIUtilities#LARGE_ICON},
>>>>>> +         *  {@link diva.gui.GUIUtilities#ROLLOVER_ICON},
>>>>>> +         *  {@link diva.gui.GUIUtilities#ROLLOVER_SELECTED_ICON} or
>>>>>> +         *  {@link diva.gui.GUIUtilities#SELECTED_ICON}.
>>>>>> +         *  If this parameter is null, then the icon comes from
>>>>>> +         *  the calling getNodeRenderer() on the {@link
>>>>>> #_portController}.
>>>>>> +         *  @see diva.gui.GUIUtilities#addIcons(Action, String[][])
>>>>>> +         */
>>>>>> +        public NewRelationAction(String[][] iconRoles) {
>>>>>> +            super("New Relation");
>>>>>> +
>>>>>> +            if (iconRoles != null) {
>>>>>> +                GUIUtilities.addIcons(this, iconRoles);
>>>>>> +            } else {
>>>>>> +                // Standard toolbar icons are 25x25 pixels.
>>>>>> +                NodeRenderer renderer =
>>>>>> _relationController.getNodeRenderer();
>>>>>> +                Figure figure = renderer.render(null);
>>>>>> +
>>>>>> +                FigureIcon icon = new FigureIcon(figure, 25, 25, 1,
>>>>>> true);
>>>>>> +                putValue(diva.gui.GUIUtilities.LARGE_ICON, icon);
>>>>>> +            }
>>>>>> +            putValue("tooltip", "Control-click to create a new
>>>>>> relation");
>>>>>> +            putValue(diva.gui.GUIUtilities.MNEMONIC_KEY, Integer
>>>>>> +                    .valueOf(KeyEvent.VK_R));
>>>>>> +        }
>>>>>> +
>>>>>> +        public void actionPerformed(ActionEvent e) {
>>>>>> +            super.actionPerformed(e);
>>>>>> +
>>>>>> +            double x;
>>>>>> +            double y;
>>>>>> +
>>>>>> +            // If you add a vertex on top of an existing link the
>>>>>> vertex will
>>>>>> +            // be added to the link. If the link exists, link 
>>>>>> will be
>>>>>> different
>>>>>> +            // from null.
>>>>>> +
>>>>>> +            Link link = null;
>>>>>> +
>>>>>> +            if ((getSourceType() == TOOLBAR_TYPE)
>>>>>> +                    || (getSourceType() == MENUBAR_TYPE)) {
>>>>>> +                // No location in the action, so put it in the 
>>>>>> middle.
>>>>>> +                BasicGraphFrame frame = 
>>>>>> ActorEditorGraphController.this
>>>>>> +                        .getFrame();
>>>>>> +                Point2D center;
>>>>>> +
>>>>>> +                if (frame != null) {
>>>>>> +                    // Put in the middle of the visible part.
>>>>>> +                    center = frame.getCenter();
>>>>>> +                    x = center.getX();
>>>>>> +                    y = center.getY();
>>>>>> +                } else {
>>>>>> +                    // Put in the middle of the pane.
>>>>>> +                    GraphPane pane = getGraphPane();
>>>>>> +                    center = pane.getSize();
>>>>>> +                    x = center.getX() / 2;
>>>>>> +                    y = center.getY() / 2;
>>>>>> +                }
>>>>>> +            } else {
>>>>>> +                // Transform
>>>>>> +                AffineTransform current =
>>>>>> getGraphPane().getTransformContext()
>>>>>> +                        .getTransform();
>>>>>> +                AffineTransform inverse;
>>>>>> +
>>>>>> +                try {
>>>>>> +                    inverse = current.createInverse();
>>>>>> +                } catch (NoninvertibleTransformException ex) {
>>>>>> +                    throw new RuntimeException(ex.toString());
>>>>>> +                }
>>>>>> +
>>>>>> +                Point2D point = new Point2D.Double(getX(), getY());
>>>>>> +
>>>>>> +                inverse.transform(point, point);
>>>>>> +                x = point.getX();
>>>>>> +                y = point.getY();               +                +
>>>>>>            // If you add a vertex on top of an existing link the 
>>>>>> vertex will
>>>>>> +                // be added to the link. In this code fragment we 
>>>>>> will
>>>>>> find
>>>>>> +                // out whether the vertex is on top of a link.
>>>>>> +                {
>>>>>> +                    GraphPane pane = getGraphPane();
>>>>>> +                    FigureLayer foregroundLayer =
>>>>>> pane.getForegroundLayer();
>>>>>> +        +                    double halo =
>>>>>> foregroundLayer.getPickHalo();
>>>>>> +                    double width = halo * 2;
>>>>>> +
>>>>>> +                    // The rectangle in which we search for a 
>>>>>> Figure.
>>>>>> +                    Rectangle2D region = new Rectangle2D.Double(
>>>>>> +                            x - halo, y - halo, width, width);
>>>>>> +
>>>>>> +                    // Iterate through figures within the region.
>>>>>> +                    Iterator<?> foregroundFigures =
>>>>>> foregroundLayer.getFigures().getIntersectedFigures(region).figuresFromFront(); 
>>>>>>
>>>>>> +                    Iterator<?> pickFigures =
>>>>>> CanvasUtilities.pickIter(foregroundFigures,
>>>>>> +                            region);
>>>>>> +
>>>>>> +                    while(link == null && pickFigures.hasNext()) {
>>>>>> +                        CanvasComponent possibleFigure =
>>>>>> (CanvasComponent)pickFigures.next();
>>>>>> +                        if (possibleFigure == null) {
>>>>>> +                            // Nothing to see here, move along - 
>>>>>> there
>>>>>> is no Figure.
>>>>>> +                        } else if (possibleFigure instanceof
>>>>>> UserObjectContainer) {
>>>>>> +                            // Work our way up the CanvasComponent
>>>>>> parent tree
>>>>>> +                            // See EditorDropTarget for similar 
>>>>>> code.
>>>>>> +                           if (possibleFigure instanceof
>>>>>> UserObjectContainer) {                            +
>>>>>>     Object userObject = ((UserObjectContainer)
>>>>>> possibleFigure).getUserObject();
>>>>>> +                                if (userObject instanceof Link) {
>>>>>> +                                    link = (Link) userObject;
>>>>>> +                                }
>>>>>> +                            }
>>>>>> +                        }
>>>>>> +                    }
>>>>>> +                }                +            }
>>>>>> +        +            ActorGraphModel graphModel = (ActorGraphModel)
>>>>>> getGraphModel();
>>>>>> +            double[] point =
>>>>>> _offsetVertex(SnapConstraint.constrainPoint(x, y));
>>>>>> +            final NamedObj toplevel = graphModel.getPtolemyModel();
>>>>>> +
>>>>>> +            if (!(toplevel instanceof CompositeEntity)) {
>>>>>> +                throw new InternalErrorException(
>>>>>> +                        "Cannot invoke NewRelationAction on an 
>>>>>> object "
>>>>>> +                                + "that is not a CompositeEntity.");
>>>>>> +            }
>>>>>> +
>>>>>> +            final String relationName =
>>>>>> toplevel.uniqueName("relation");                +
>>>>>> +            StringBuffer moml = new StringBuffer();
>>>>>> +            if (link != null) {
>>>>>> +                // Add the vertex to an existing link.
>>>>>> +                moml.append("<group>\n");
>>>>>> +                StringBuffer failmoml = new StringBuffer();
>>>>>> +                graphModel.getLinkModel().addNewVertexToLink(moml,
>>>>>> +                        failmoml, (CompositeEntity) toplevel, link,
>>>>>> relationName, x, y);
>>>>>> +                moml.append("</group>\n");
>>>>>> +            } else {
>>>>>> +                final String vertexName = "vertex1";
>>>>>> +                +                // Create the relation.
>>>>>>      +                moml.append("<relation name=\"" + 
>>>>>> relationName +
>>>>>> "\">\n");
>>>>>> +                moml.append("<vertex name=\"" + vertexName + "\"
>>>>>> value=\"{");
>>>>>> +                moml.append(point[0] + ", " + point[1]);
>>>>>> +                moml.append("}\"/>\n");
>>>>>> +                moml.append("</relation>");
>>>>>> +            }    +            MoMLChangeRequest request = new
>>>>>> MoMLChangeRequest(this, toplevel,
>>>>>> +                    moml.toString());
>>>>>> +            request.setUndoable(true);
>>>>>> +            toplevel.requestChange(request);
>>>>>> +        }
>>>>>> +
>>>>>> +        /** Offset a figure if another figure is already at that
>>>>>> location.
>>>>>> +         *  @param point An array of two doubles (x and y)
>>>>>> +         *  @return An array of two doubles (x and y) that 
>>>>>> represents
>>>>>> +         *  either the original location or an offset location that
>>>>>> +         *  does not obscure an object of class <i>figure</i>.
>>>>>> +         */
>>>>>> +        protected double[] _offsetVertex(double[] point) {
>>>>>> +
>>>>>> +            GraphPane pane = getGraphPane();
>>>>>> +            FigureLayer foregroundLayer = pane.getForegroundLayer();
>>>>>> +
>>>>>> +            Rectangle2D visibleRectangle;
>>>>>> +            BasicGraphFrame frame =
>>>>>> ActorEditorGraphController.this.getFrame();
>>>>>> +            if (frame != null) {
>>>>>> +                visibleRectangle = frame.getVisibleRectangle();
>>>>>> +            } else {
>>>>>> +                visibleRectangle = 
>>>>>> pane.getCanvas().getVisibleSize();
>>>>>> +            }
>>>>>> +            return _offsetFigure(point[0], point[1], _PASTE_OFFSET,
>>>>>> +                    _PASTE_OFFSET, ptolemy.moml.Vertex.class,
>>>>>> foregroundLayer,
>>>>>> +                    visibleRectangle);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Add hot keys to the actions in the given JGraph.
>>>>>> +     *
>>>>>> +     *  @param jgraph The JGraph to which hot keys are to be added.
>>>>>> +     */
>>>>>> +    protected void _addHotKeys(JGraph jgraph) {
>>>>>> +        super._addHotKeys(jgraph);
>>>>>> +        +
>>>>>>  _classDefinitionController.addHotKeys(getFrame().getJGraph());
>>>>>> +
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Create the controllers for nodes in this graph.
>>>>>> +     *  In this class, controllers with FULL access are created.
>>>>>> +     *  This is called by the constructor, so derived classes that
>>>>>> +     *  override this must be careful not to reference local 
>>>>>> variables
>>>>>> +     *  defined in the derived classes, because the derived classes
>>>>>> +     *  will not have been fully constructed by the time this is
>>>>>> called.
>>>>>> +     */
>>>>>> +    protected void _createControllers() {
>>>>>> +        Configuration _config =
>>>>>> (Configuration)Configuration.configurations().iterator().next();
>>>>>> +        String _alternateActorInstanceClassName = null;
>>>>>> +        _attributeController = new AttributeController(this,
>>>>>> +                AttributeController.FULL);
>>>>>> +
>>>>>> +        _classDefinitionController = new
>>>>>> ClassDefinitionController(this);
>>>>>> +
>>>>>> +        if(_config != null) {
>>>>>> +          /*
>>>>>> +           * If _alternateActorInstanceController is set in the 
>>>>>> config,
>>>>>> use that
>>>>>> +           * class as the _entityController instead of the default +
>>>>>>         * ActorInstanceController
>>>>>> +          */
>>>>>> +          StringAttribute _alternateActorInstanceAttribute =
>>>>>> (StringAttribute)
>>>>>> +            
>>>>>> _config.getAttribute("_alternateActorInstanceController");
>>>>>> +          if(_alternateActorInstanceAttribute != null) {
>>>>>> +            _alternateActorInstanceClassName = +
>>>>>>  _alternateActorInstanceAttribute.getExpression();
>>>>>> +          }
>>>>>> +        }
>>>>>> +        +        if(_alternateActorInstanceClassName == null) {
>>>>>> +          //System.out.println("Using standard
>>>>>> ActorInstanceController");
>>>>>> +          +          //default to the normal ActorInstanceController
>>>>>> +          _entityController = new ActorInstanceController(this);
>>>>>> +        } else {
>>>>>> +          try {
>>>>>> +            //try to load the alternate class
>>>>>> +            +            //System.out.println("Using
>>>>>> _alternateActorInstanceController: " + +            //
>>>>>>  _alternateActorInstanceClassName);
>>>>>> +            Class _alternateActorInstanceClass =
>>>>>> Class.forName(_alternateActorInstanceClassName);
>>>>>> +            Class[] argsClass = new Class[]
>>>>>> {diva.graph.GraphController.class};
>>>>>> +            Object[] args = new Object[] {this};
>>>>>> +            Constructor alternateActorInstanceConstructor =
>>>>>> _alternateActorInstanceClass.getConstructor(argsClass);
>>>>>> +            _entityController = (ActorController)
>>>>>> alternateActorInstanceConstructor.newInstance(args);
>>>>>> +          } catch(Exception e) {
>>>>>> +            System.out.println("The configuration has " +
>>>>>> +              "_alternateActorInstanceController set, but the 
>>>>>> class " +
>>>>>> +              _alternateActorInstanceClassName + " is not found.
>>>>>>  Defaulting " +
>>>>>> +              " to ActorInstanceController: " + e.getMessage());
>>>>>> +              e.printStackTrace();
>>>>>> +          }
>>>>>> +        }
>>>>>> +        _entityPortController = new IOPortController(this,
>>>>>> +                AttributeController.FULL);
>>>>>> +        _portController = new ExternalIOPortController(this,
>>>>>> +                AttributeController.FULL);
>>>>>> +        _relationController = new RelationController(this);
>>>>>> +        _linkController = new LinkController(this);
>>>>>> +    }
>>>>>> +
>>>>>> +    /** Initialize interactions for the specified controller.  This
>>>>>> +     *  method is called when a new controller is constructed. In 
>>>>>> this
>>>>>> +     *  class, this method attaches a link creator to the controller
>>>>>> +     *  if the controller is an instance of 
>>>>>> ExternalIOPortController,
>>>>>> +     *  IOPortController, or RelationController.
>>>>>> +     *  @param controller The controller for which to initialize
>>>>>> interaction.
>>>>>> +     */
>>>>>> +    protected void _initializeInteraction(NamedObjController
>>>>>> controller) {
>>>>>> +        super._initializeInteraction(controller);
>>>>>> +
>>>>>> +        if (controller instanceof ExternalIOPortController
>>>>>> +                || controller instanceof IOPortController
>>>>>> +                || controller instanceof RelationController) {
>>>>>> +            Interactor interactor = controller.getNodeInteractor();
>>>>>> +
>>>>>> +            if (interactor instanceof CompositeInteractor) {
>>>>>> +                ((CompositeInteractor)
>>>>>> interactor).addInteractor(_linkCreator);
>>>>>> +            }
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    ////                         protected 
>>>>>> methods                 ////
>>>>>> +
>>>>>> +    /** Initialize all interaction on the graph pane. This method
>>>>>> +     *  is called by the setGraphPane() method of the superclass.
>>>>>> +     *  This initialization cannot be done in the constructor 
>>>>>> because
>>>>>> +     *  the controller does not yet have a reference to its pane
>>>>>> +     *  at that time.
>>>>>> +     */
>>>>>> +    protected void initializeInteraction() {
>>>>>> +        super.initializeInteraction();
>>>>>> +
>>>>>> +        GraphPane pane = getGraphPane();
>>>>>> +
>>>>>> +        // Add a menu command to configure the ports.
>>>>>> +        _portDialogAction = new PortDialogAction("Ports");
>>>>>> +        _portDialogAction.setConfiguration(getConfiguration());
>>>>>> +
>>>>>> +        _configureMenuFactory.addAction(_portDialogAction,
>>>>>> "Customize");
>>>>>> +        _configureUnitsAction = new ConfigureUnitsAction("Units
>>>>>> Constraints");
>>>>>> +        _configureMenuFactory.addAction(_configureUnitsAction,
>>>>>> "Customize");
>>>>>> +        _configureUnitsAction.setConfiguration(getConfiguration());
>>>>>> +
>>>>>> +        // Add a menu command to list to the actor.
>>>>>> +        _listenToActorFactory = new ListenToActorFactory();
>>>>>> +        _menuFactory.addMenuItemFactory(_listenToActorFactory);
>>>>>> +        _listenToActorFactory.setConfiguration(getConfiguration());
>>>>>> +
>>>>>> +        // Create listeners that creates new relations.
>>>>>> +        _relationCreator = new RelationCreator();
>>>>>> +        _relationCreator.setMouseFilter(_shortcutFilter);
>>>>>> +
>>>>>> +        
>>>>>> pane.getBackgroundEventLayer().addInteractor(_relationCreator);
>>>>>> +
>>>>>> +        // Note that shift-click is already bound to the 
>>>>>> dragSelection
>>>>>> +        // interactor when adding things to a selection.
>>>>>> +        // Create the interactor that drags new edges.
>>>>>> +        _linkCreator = new LinkCreator();
>>>>>> +        _linkCreator.setMouseFilter(_shortcutFilter);
>>>>>> +
>>>>>> +        // NOTE: Do not use _initializeInteraction() because we are
>>>>>> +        // still in the constructor, and that method is 
>>>>>> overloaded in
>>>>>> +        // derived classes.
>>>>>> +        ((CompositeInteractor) _portController.getNodeInteractor())
>>>>>> +                .addInteractor(_linkCreator);
>>>>>> +        ((CompositeInteractor)
>>>>>> _entityPortController.getNodeInteractor())
>>>>>> +                .addInteractor(_linkCreator);
>>>>>> +        ((CompositeInteractor) 
>>>>>> _relationController.getNodeInteractor())
>>>>>> +                .addInteractor(_linkCreator);
>>>>>> +
>>>>>> +        LinkCreator linkCreator2 = new LinkCreator();
>>>>>> +        linkCreator2
>>>>>> +                .setMouseFilter(new
>>>>>> MouseFilter(InputEvent.BUTTON1_MASK, 0));
>>>>>> +        ((CompositeInteractor)
>>>>>> _entityPortController.getNodeInteractor())
>>>>>> +                .addInteractor(linkCreator2);
>>>>>> +    }
>>>>>> +    +   +    /** Action for creating a new relation. */
>>>>>> +    protected Action _newRelationAction = new NewRelationAction(
>>>>>> +            new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/relation.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/relation_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/relation_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/relation_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    //   private LinkCreator _linkCreator2;  // For shift-click
>>>>>> +
>>>>>> +    /** This class is an interactor that interactively drags 
>>>>>> edges from
>>>>>> +     *  one terminal to another, creating a link to connect them.
>>>>>> +     */
>>>>>> +    protected class LinkCreator extends AbstractInteractor {
>>>>>> +        /** Create a new edge when the mouse is pressed. */
>>>>>> +        public void mousePressed(LayerEvent event) {
>>>>>> +            Figure source = event.getFigureSource();
>>>>>> +            NamedObj sourceObject = (NamedObj) 
>>>>>> source.getUserObject();
>>>>>> +
>>>>>> +            // Create the new edge.
>>>>>> +            Link link = new Link();
>>>>>> +
>>>>>> +            // Set the tail, going through the model so the link is
>>>>>> added
>>>>>> +            // to the list of links.
>>>>>> +            ActorGraphModel model = (ActorGraphModel) 
>>>>>> getGraphModel();
>>>>>> +            model.getLinkModel().setTail(link, sourceObject);
>>>>>> +
>>>>>> +            try {
>>>>>> +                // add it to the foreground layer.
>>>>>> +                FigureLayer layer =
>>>>>> getGraphPane().getForegroundLayer();
>>>>>> +                Site headSite;
>>>>>> +                Site tailSite;
>>>>>> +
>>>>>> +                // Temporary sites.  One of these will get blown 
>>>>>> away
>>>>>> later.
>>>>>> +                headSite = new AutonomousSite(layer, 
>>>>>> event.getLayerX(),
>>>>>> event
>>>>>> +                        .getLayerY());
>>>>>> +                tailSite = new AutonomousSite(layer, 
>>>>>> event.getLayerX(),
>>>>>> event
>>>>>> +                        .getLayerY());
>>>>>> +
>>>>>> +                // Render the edge.
>>>>>> +                Connector c = getEdgeController(link).render(link,
>>>>>> layer,
>>>>>> +                        tailSite, headSite);
>>>>>> +
>>>>>> +                // get the actual attach site.
>>>>>> +                tailSite = 
>>>>>> getEdgeController(link).getConnectorTarget()
>>>>>> +                        .getTailSite(c, source, event.getLayerX(),
>>>>>> +                                event.getLayerY());
>>>>>> +
>>>>>> +                if (tailSite == null) {
>>>>>> +                    throw new RuntimeException("Invalid connector
>>>>>> target: "
>>>>>> +                            + "no valid site found for tail of new
>>>>>> connector.");
>>>>>> +                }
>>>>>> +
>>>>>> +                // And reattach the connector.
>>>>>> +                c.setTailSite(tailSite);
>>>>>> +
>>>>>> +                // Add it to the selection so it gets a manipulator,
>>>>>> and
>>>>>> +                // make events go to the grab-handle under the mouse
>>>>>> +                getSelectionModel().addSelection(c);
>>>>>> +
>>>>>> +                ConnectorManipulator cm = (ConnectorManipulator)
>>>>>> c.getParent();
>>>>>> +                GrabHandle gh = cm.getHeadHandle();
>>>>>> +                layer.grabPointer(event, gh);
>>>>>> +            } catch (Exception ex) {
>>>>>> +                MessageHandler.error("Drag connection failed:", ex);
>>>>>> +            }
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    /** An interactor for creating relations upon control clicking.
>>>>>> +     */
>>>>>> +    protected class RelationCreator extends ActionInteractor {
>>>>>> +        public RelationCreator() {
>>>>>> +            super();
>>>>>> +            setAction(_newRelationAction);
>>>>>> +        }
>>>>>> +    }
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    ////                         private 
>>>>>> variables                 ////
>>>>>> +
>>>>>> +    private ConfigureUnitsAction _configureUnitsAction;
>>>>>> +
>>>>>> +    /** The interactors that interactively creates edges. */
>>>>>> +    private LinkCreator _linkCreator; // For control-click
>>>>>> +
>>>>>> +    /** Factory for listen to actor menu item. */
>>>>>> +    private ListenToActorFactory _listenToActorFactory;
>>>>>> +
>>>>>> +    /** Action for creating a new inout multiport. */
>>>>>> +    private Action _newInoutMultiportAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_INOUT_MULTIPORT,
>>>>>> +            "New input/output multiport", KeyEvent.VK_T, new 
>>>>>> String[][]
>>>>>> {
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_inout.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_inout_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { 
>>>>>> "/ptolemy/vergil/actor/img/multi_inout_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { 
>>>>>> "/ptolemy/vergil/actor/img/multi_inout_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    /** Action for creating a new input/output port. */
>>>>>> +    private Action _newInoutPortAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_INOUT, "New 
>>>>>> input/output
>>>>>> port",
>>>>>> +            KeyEvent.VK_P, new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_inout.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { 
>>>>>> "/ptolemy/vergil/actor/img/single_inout_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { 
>>>>>> "/ptolemy/vergil/actor/img/single_inout_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { 
>>>>>> "/ptolemy/vergil/actor/img/single_inout_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    /** Action for creating a new input multiport. */
>>>>>> +    private Action _newInputMultiportAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_INPUT_MULTIPORT,
>>>>>> +            "New input multiport", KeyEvent.VK_N, new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_in.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_in_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_in_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_in_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    /** Action for creating a new input port. */
>>>>>> +    private Action _newInputPortAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_INPUT, "New input 
>>>>>> port",
>>>>>> +            KeyEvent.VK_I, new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_in.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_in_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_in_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_in_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    /** Action for creating a new output multiport. */
>>>>>> +    private Action _newOutputMultiportAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_OUTPUT_MULTIPORT,
>>>>>> +            "New output multiport", KeyEvent.VK_U, new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_out.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_out_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_out_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/multi_out_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +
>>>>>> +    +    +    /** Action for creating a new output port. */
>>>>>> +    private Action _newOutputPortAction = new NewPortAction(
>>>>>> +            ExternalIOPortController._GENERIC_OUTPUT, "New output
>>>>>> port",
>>>>>> +            KeyEvent.VK_O, new String[][] {
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_out.gif",
>>>>>> +                            GUIUtilities.LARGE_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_out_o.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_out_ov.gif",
>>>>>> +                            GUIUtilities.ROLLOVER_SELECTED_ICON },
>>>>>> +                    { "/ptolemy/vergil/actor/img/single_out_on.gif",
>>>>>> +                            GUIUtilities.SELECTED_ICON } });
>>>>>> +    +    /** Action for changing the view. */
>>>>>> +    private Action _changeViewAction(String strView) {
>>>>>> +    String view = strView;
>>>>>> +    System.out.println("The View is:" + view);
>>>>>> +    return null;
>>>>>> +        }    {
>>>>>> +       +    }
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    ////                         inner 
>>>>>> classes                     ////
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    //// LinkCreator
>>>>>> +
>>>>>> +    /** The port dialog factory. */
>>>>>> +    private PortDialogAction _portDialogAction;
>>>>>> +
>>>>>> +    /** The interactor for creating new relations. */
>>>>>> +    private RelationCreator _relationCreator;
>>>>>> +
>>>>>> +    /** The filter for shortcut operations.  This is used for 
>>>>>> creation
>>>>>> +     *  of relations and creation of links from relations. Under PC,
>>>>>> +     *  this is a control-1 click.  Under Mac OS X, the control 
>>>>>> key is
>>>>>> +     *  used for context menus and this corresponds to the command-1
>>>>>> +     *  click.  For details, see the Apple java archive
>>>>>> +     *  http://lists.apple.com/archives/java-dev User: archives,
>>>>>> +     *  passwd: archives
>>>>>> +     */
>>>>>> +    private MouseFilter _shortcutFilter = new MouseFilter(
>>>>>> +            InputEvent.BUTTON1_MASK, Toolkit.getDefaultToolkit()
>>>>>> +                    .getMenuShortcutKeyMask(),
>>>>>> Toolkit.getDefaultToolkit()
>>>>>> +                    .getMenuShortcutKeyMask());
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    //// RelationCreator
>>>>>> +
>>>>>> +    
>>>>>> ///////////////////////////////////////////////////////////////////
>>>>>> +    //// ListenToActorFactory
>>>>>> +    private class ListenToActorFactory implements MenuItemFactory {
>>>>>> +        /** Add an item to the given context menu that will open a
>>>>>> listen
>>>>>> +         *  to actor window.
>>>>>> +         *  @param menu The context menu.
>>>>>> +         *  @param object The object whose ports are being 
>>>>>> manipulated.
>>>>>> +         */
>>>>>> +        public JMenuItem create(final JContextMenu menu, NamedObj
>>>>>> object) {
>>>>>> +            String name = "Listen to Actor";
>>>>>> +            final NamedObj target = object;
>>>>>> +
>>>>>> +            _action = new 
>>>>>> ActorController.ListenToActorAction(target,
>>>>>> +                    ActorEditorGraphController.this);
>>>>>> +            _action.setConfiguration(_configuration);
>>>>>> +            return menu.add(_action, name);
>>>>>> +        }
>>>>>> +
>>>>>> +        /** Set the configuration for use by the help screen.
>>>>>> +         *  @param configuration The configuration.
>>>>>> +         */
>>>>>> +        public void setConfiguration(Configuration configuration) {
>>>>>> +            _configuration = configuration;
>>>>>> +
>>>>>> +            if (_action != null) {
>>>>>> +                _action.setConfiguration(_configuration);
>>>>>> +            }
>>>>>> +        }
>>>>>> +
>>>>>> +        private ActorController.ListenToActorAction _action;
>>>>>> +
>>>>>> +        private Configuration _configuration;
>>>>>> +    }
>>>>>> +}
>>>>>>
>>>>>> _______________________________________________
>>>>>> Kepler-cvs mailing list
>>>>>> Kepler-cvs at kepler-project.org
>>>>>> http://mercury.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-cvs
>>>>>>           
>>> -- 
>>> Christopher Brooks (cxh at eecs berkeley edu) University of California
>>> CHESS Executive Director                      US Mail: 337 Cory Hall
>>> Programmer/Analyst CHESS/Ptolemy/Trust        Berkeley, CA 94720-1774
>>> ph: 510.643.9841 fax:510.642.2718             (Office: 545Q Cory)
>>> home: (F-Tu) 707.665.0131 (W-F) 510.655.5480
>>> _______________________________________________
>>> Kepler-dev mailing list
>>> Kepler-dev at kepler-project.org
>>> http://mercury.nceas.ucsb.edu/k
>>>     
>>
>>
>>
>>   
> 

-- 
Christopher Brooks (cxh at eecs berkeley edu) University of California
CHESS Executive Director                      US Mail: 337 Cory Hall
Programmer/Analyst CHESS/Ptolemy/Trust        Berkeley, CA 94720-1774
ph: 510.643.9841 fax:510.642.2718	      (Office: 545Q Cory)
home: (F-Tu) 707.665.0131 (W-F) 510.655.5480


More information about the Kepler-dev mailing list