In order to create a new diagram, we must create a new entry in one of Argo's menus. To achieve that,
we will use functionnalites from the PluggableMenu interface.
PluggableMenu is an interface that let you create PlugIns for Argo that adds
an entry into the menus. PluggableMenu comes from Pluggable
which in its turn comes from Module.
Next figure presents the class diagram corresponding to modules.
Methods providedd by the Module interface are mainly used to identify the module,
to initialize it and finally to close it in a clean way.
The inContext methode from the Pluggable interface
is used by the pluggin to plug itself to some part of Argo.
getMenuItem method from the PluggableMenu interface is
the function by which Argo will be able to get the JMenuItem provided by
our PluggableMenu and insert it in the good context
which was asked by argo before.
The buildContext method from the PluggableMenu interface
is used to make the array of Objects that will be passed as arguments to
the inContext method. This method is used by Argo to build the context for modules
but I haven't been able to see why. (maybe it can be usefull when you so some inheritance ?)
The sequence diagram coming next explains how the insertion of an entry in the menu of ArgoUML is done.
We will now write our own PluggableMenu. We will name it
ActionTestDiagram, it will be a son for the class UMLAction
while implementing PluggableMenu (this will permit us to have in the same class
the action that creates the MenuItem and the one that is executed when it is selected).
Our new class will implement all the methods from Module, Pluggable
and PluggableMenu, and will also implement ActionPerformed
that will be the action executed when our menuItem will be seclected (for the begining it will be
a simple System.out.println.
This new class will be placed in the directory src/org/argouml/uml/ui that you must
create and will be part of the org.argouml.uml.ui package.
package org.argouml.uml.ui;
import org.argouml.ui.*;
import org.argouml.application.api.*;
import org.argouml.uml.ui.*;
import org.argouml.uml.*;
import org.argouml.kernel.*;
import org.tigris.gef.base.*;
import org.tigris.gef.util.*;
import ru.novosoft.uml.foundation.core.*;
import ru.novosoft.uml.behavior.state_machines.*;
import ru.novosoft.uml.model_management.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.beans.*;
/**
* Notre classe ActionTestDiagram
*/
public class ActionTestDiagram extends UMLAction
implements PluggableMenu {
public ActionTestDiagram() { super ("TestDiagram"); }
private static JMenuItem _menuItem = null;
/////////////////////////////////////////
// implementation de UMLAction
/**
* Action executée par la selection du menu
*/
public void actionPerformed (ActionEvent ae) {
System.out.println("HelloWorld!!");
}
/////////////////////////////////////////////////////////////////
// implementation de l'interface Module
private boolean _initialized = false;
public boolean initializeModule() {
Argo.log.info("*** Initialisation de TestDiagram");
_initialized = true;
return _initialized;
}
public void setModuleEnabled(boolean enabled) { }
public boolean isModuleEnabled() { return true; }
public Vector getModulePopUpActions(Vector v, Object o) { return null; }
public boolean shutdownModule() { return true; }
public String getModuleName() { return "TestDiagram"; }
public String getModuleDescription() { return "TestDiagram"; }
public String getModuleAuthor() { return "Florent de Lamotte"; }
public String getModuleVersion() { return "0.9.10"; }
public String getModuleKey() { return "module.tools.test"; }
/////////////////////////////////////////////////////////////////
// Implémentation de l'interface Pluggable
/**
* Permet au module d'insérer le menu ou il le veut
* @param o l'objet décrivant le contexte le premier objet est un JMenuItem
* et le second une clé correspondant à ce JMenuItem et correspondant à une entrée
* dans le menu
* @return true si l'emplacement nous convient
*/
public boolean inContext(Object[] o) {
if (o.length < 2) return false;
if ((o[0] instanceof JMenuItem) && ("Create Diagrams".equals(o[1]))) {
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////
// Implémentation de l'interface PluggableMenu
/**
* Retourne le JMenuItem que l'on veut ajouter au menu
*
* @param mi le JMenuItem dans lequel sera ajouté notre JMenuItem
* @param s La clé correspondante (celle qui avait été passée lors du inContext
* @return Le JMenuItem correspondant à ce menu
*/
public JMenuItem getMenuItem(JMenuItem mi, String s) {
if (_menuItem == null) {
_menuItem = new JMenuItem("Test Diagram",
ResourceLoader.lookupIconResource("TestDiagram"));
}
_menuItem.addActionListener(this);
return _menuItem;
}
/**
* Construit l'objet qui sera envoyé a inContext
*/
public Object[] buildContext(JMenuItem a, String b) {
return new Object[] { a, b };
}
}
Once the new class is written, you can launch ArgoUML with your new module by executing
the command ant run from your module's directory.
Your module should be loaded by Argo and you should see the following message
[java] *** Initialisation de TestDiagram
[java] Loaded Module: TestDiagram
In the "Create Diagram" entry in the menu, a new item should appear : "Test Diagram",
if you select this item,
HelloWorld!! should appear on the console.
While the module is loading, it complains because it can't find an Icon ...
In fact, when we created our JMenuItem, we associated it
the icon TestDiagram that we have neither created nor placed
in the jar.
Icons are placed in the directory src/org/argouml/Imafes so you
can put an icon with the name TestDiagram.gif in the
gif format in this directory.
We will now have to make a little modification in our build.xml file
so that it can copy every icon from the src/org/argouml/Images directory
int hte build/classes/org/argouml/Images directory, that will then enable
GEF to find the icon (in fact it is the RessourceLoader from GEF
that does this task.)
The modifications are added to the prepare target which aim is to
prepare the directories where the files to be archived are placed.
<!-- =================================================================== -->
<!-- Prepares the build directory -->
<!-- =================================================================== -->
<target name="prepare" depends="init">
<!-- create directories -->
<echo message="Preparing the build directories"/>
<copy todir="${module.build.dest}/org/argouml/Images">
<fileset dir="${module.build.src}/org/argouml/Images"
includes="**/**" excludes="CVS/**"/>
</copy>
<!-- These must be there already -->
</target>
Now if you execute ant run, you should see your icon near the text of
your JMenuItem.