Table des matières
Ce document est un complément au cookbook d'Argo. Il a pour ambition de guider le lecteur vers une meilleure compréhension du fonctionnement d'ArgoUML. Il est basé sur une expérience personnelle et ne constitue donc pas un document de référence.
Les fichiers d'exemple, créés pendant l'élaboration de ce tutoriel sont disponibles ici. Vous pouvez tester le module directement en le décompactant dans le répertoire modules d'ArgoUML et en exécutant la commande ant run dans le répertoire test nouvellement créé (il faudra bien sur pour cela que Ant et le code source d'ArgoUML soient bien installés).
Un diagramme est une entité composée de :
Un Layer
Un GraphModel
Une Toolbar
Un Title
La classe de base pour réaliser un diagramme UML Dans ArgoUML est la classe UMLDiagram, qui hérite de ArgoDiagram. Ces deux classes qui se trouvent respectivement dans org.argouml.uml.diagram.ui et org.argouml.ui.
On ajoute une figure au diagramme à l'aide de la methode add
Il est possible de récupérer les éléments d'un diagramme au travers de la méthode elements qui renvoie une Enumeration contenant les figures présentes dans le diagramme. La suppression d'une figure se fera à l'aide de la methode remove.
Un GraphModel stocke le modèle qui se cache derrière un diagramme. C'est au niveau du GraphModel que l'on va ajouter des éléments (si on peut ajouter des éléments à un GraphModel, on parle de MutableGraphModel). On peut ajouter un listener à un GraphModel, qui renverra alors un GraphEvent lorsqu'une modification est apportée au modèle.
Un des gros interêts du GraphModel est qu'il permet de gérer la connection entre plusieurs éléments il se charge en effet, au travers de la méthode connect de relier deux ports et de créer (s'il y en a besoin) la classe qui reliera ces deux ports. Une fois que la liaison est faite, le GraphModel enverra un Evenement edgeAdded pour que la partie graphique (le Layer en fait) sache qu'une liaison à été ajoutée.
Un GraphRenderer est une classe qui implémente deux interfaces : GraphNodeRenderer et GraphEdgeRenderer.
Ces deux interfaces fournissent un service permettant de créer une figure associée à un objet (un "node" ou une "edge" du diagramme). Les methodes permettant de faire cela sont getFigNodeFor et getFigEdgeFor.
Les Layers (calques en français) contiennent les différentes figures d'un diagramme et gèrent leur disposition. Comme ce sont eux qui gèrent les figures, ce sont vers eux qu'il faut se tourner lorsque l'on veut les manipuler.
On peut récupérer un calque lié à un diagramme à l'aide de la methode getLayer d'un diagramme.
Voici une liste de différentes opérations possibles sur une figure accessibles depuis le layer auquel elle appartient. Cette liste n'est pas exhaustive. Pour avoir une liste exhaustive mieux vaut aller voir la liste fournie par le JavaDoc.
add : ajoute une figure au Layer
remove : supprime une figure du Layer
sendToBack, sendToFront : place la figure devant ou derriere les autres figures du Layer
sendBackWard, sendForward : gère la position d'une figure dans un layer
bringInFrontOf : permet de mettre une figure devant une autre
presentationFor : permet de récupérer une figure correspondant à un modèle
Les calques utilisés dans les diagrammes d'Argo sont du type LayerPerspective. Un Layer du type LayerPerspective permet une meilleure liaison avec un GraphModel et un GraphRenderer. En effet, un LayerPerspective va récupérer les évènements en provenance du GraphModel. Lorsque celui-ci signale qu'il vient d'ajouter un node ou un edge au modèle le Layer demande au GraphRenderer de lui créer la figure qui va bien pour ensuite l'ajouter au diagramme.
La barre d'outils est une barre de boutons dans laquelle chaque bouton est relié à une commande GEF. Les commandes GEF utilisées sont généralement CmdCreateNode ou CmdSetMode. CmdCreateNode crée un node et le rajoute au diagramme. CmdSetMode est généralement utilisé pour passer l'editeur dans un mode du type : ModeCreatePolyEdge qui permet de créer un lien entre deux nodes.
Les diagrammes sont généralement placés dans le package : org.argouml.uml.diagram. Ce package comporte normalement un sous-package ui dans lequel sont regroupés toutes les classes qui se raportent à l'ui.
Les figures
Les Selections
La classe diagramme correspondante
Le GraphRenderer
Finalement ne reste généralement à la racine du package que le GraphModel et éventuellement des fichiers permettant la représentation du diagramme sous forme de table.
Il vous faudra tout d'abord choisir comment vous voulez intégrer votre diagramme à Argo.
Deux solutions s'offrent à vous :
Vous pouvez ajouter du code à ArgoUML, permettant de prendre en compte votre diagramme.
Vous pouvez créer un module que vous pourrez distribuer indépendamment du code source d'ArgoUML.
Je recommande fortement la création d'un nouveau module implémentant votre diagramme. La raison principale est que vous pouvez ainsi rester totalement indépendant du code source d'ArgoUML et ne souffrirez pas d'une modification d'un fichier du source d'argo que vous aurez du modifier pour que l'utilisateur puisse accéder à votre diagramme.
Il vous faudra tout d'abord créer un répertoire dans argouml/modules dans lequel vous mettrez les fichiers correspondant à votre module.
Pour notre exemple nous allons appeller ce répertoire test.
Placez dans ce répertoire un fichier build.xml de configuration de ant et un fichier module.properties qui va paramétrer son fonctionnement. Vous pouvez récupérer ces fichiers dans le répertoire d'un autre module.
Si vous prenez par exemple le fichier build.xml provenant du module php, vous n'aurez normalement rien à modifier, tous les paramètres pour ce module se trouvant dans le fichier module.properties (Par contre le fichier build.xml du module junit est un peu différent puisqu'il a besoin de librairies externes.)
Le fichier module.properties comporte pour l'instant deux lignes (ce sont des propriétés ant).
argo.module.name : permet de spécifier le nom du module
argo.module.jarfile : permet de spécifier le nom de l'archive .jar
Pour notre module, le fichier de propriétés sera le suivant :
argo.module.name=test argo.module.jarfile=argo_test
Une fois que vous avez vos fichierz build.xml et module.properties vous pouvez tester la configuration de votre module en tapant ant.
Voici ce que ant devrait vous sortir :
$ ant Buildfile: build.xml init: [echo] ------------------- ArgoModule-test 0.9.5-20020718-0858 [2001] ---------------- usage: [echo] [echo] [echo] ArgoModule-test Build file [echo] ------------------------------------------------------------- [echo] [echo] available targets are: [echo] [echo] compile --> compiles the source code to the tree under ../../modules/test/build [echo] package --> generates the argo_test.jar file [echo] run --> runs ArgoUML argo_test.jar [echo] install --> merges ./org into ../src_new/org tree [echo] usage --> show this message (default) [echo] [echo] See the comments inside the build.xml file for more details. [echo] ------------------------------------------------------------- [echo] [echo] BUILD SUCCESSFUL Total time: 2 seconds
Si vous obtenez quelque chose de semblable, c'est que la configuration de la compilation est correcte. Vérifiez surtout que le nom de l'archive est bien celui que vous aviez demandé, il est normalement visible sur les lignes package et run. De même, vérifiez le nom du module (vous devez voir s'afficher ArgoModule-test lors de l'init.
Une fois que ant est configuré, vous pouvez créer l'arborescence des répertoires.
Créez donc un répertoire src dans lequel vous placerez les package c'est à dire une arborescence org/argouml.
Créez aussi un répertoire lib qui sera utilisé pour placer d'éventuelles librairies externes.
Pour que le chargement du module s'effectue correctement, il vous faudra écrire un fichier manifest.mf indiquant les informations nécéssaires au chargement du module. Voici le manifest.mf pour notre module test.
Manifest-Version: 2.0 Class-Path: test.jar Created-By: 1.3.1 (Sun Microsystem Inc.) Name: org/argouml/uml/ui/ActionTestDiagram.class Extension-name: module.tools.test Specification-Title: ArgoUML Dynamic Load Module Specification-Version: 0.9.10 Specification-Vendor: University of California Implementation-Title: Test Module Implementation-Version: 0.9.10 Implementation-Vendor: test
Une petite explication s'impose ...
Le champ Manifest-Version permet de spécifier la version du format utilisé, ici 2.0.
Le champ ClassPath nous donne le nom des classes à charger en même demps que le module
Le champ Created-By contient le nom du compilateur utilisé pour compiler les classes.
Le champ Name explicite le nom de la classe principale. Cette classe sera chargée par le classloader d'Argo en tant que module.
...
Le fichier manifest.mf doit être placé à la racine de l'archive, c'est à dire dans le répertoire src/org.
Nous allons maintenant pouvoir tester que tout fonctionne correctement avant de commencer.
Tout d'abord, nous allons essayer de créer le package à l'aide de la commande ant package que vous devez exécuter dans le répertoire de base de votre module.
$ ant package Buildfile: build.xml init: [echo] ------------------- ArgoModule-test 0.9.5-20020718-0941 [2001] ---------------- prepare: [echo] Preparing the build directories compile: [echo] Compiling the sources package: [copy] Copying 1 file to /usr/src/argo/modules/test/build/classes [jar] Building jar: /usr/src/argo/modules/test/build/argo_test.jar BUILD SUCCESSFUL Total time: 3 seconds
Vous devriez obtenir le même résultat. Après l'exécution de la commande, un fichier build/argo_test.jar devrait avoir été créé.
Bien sur l'archive argo_test.jar que vous avez générée ne devrait contenir que le fichier manifest.mf.
Vous pouvez même essayer la commande ant run qui devrait normalement lancer ArgoUML avec votre module. Bien sur comme la classe que vous avez spécifié dans le champ Name de votre manifest.mf n'existe pas, le chargement du module devrait échouer et vous devriez voir s'afficher :
[java] Could not instantiate module org/argouml/uml/ui/ActionTestDiagram
Si par contre ArgoUML ne se lance pas et que vous obtenez
run: [echo] --- Executing ArgoModule-test --- [java] Exception in thread "main" java.lang.NoClassDefFoundError: org/argouml/application/Main [java] Java Result: 1
C'est que vous n'avez pas créé le fichier argouml.jar qui doit être placé dans le répertoire build d'Argo.
Un simple ant package dans le répertoire src_new d'Argo devrait résoudre le problème.
Pour pouvoir créer notre diagramme, in nous faut créer une entrée dans l'un des menus d'Argo. Pour cela, nous allons utiliser les fonctionnalités de PluggableMenu.
PluggableMenu est une interface permettant d'écrire des Plug-ins pour Argo. PluggableMenu dérive de Pluggable qui elle même dérive de Module.
La figure suivante présente le diagramme de classe correspondant aux modules.
Les méthodes fournies par l'interface Module servent principalement à identifier le module, l'initialiser et finalement à le fermer proprement.
La méthode inContext de l'interface Pluggable sert au plugin à se ratacher à une partie d'Argo.
La méthode getMenuItem de l'interface PluggableMenu est le gros interêt de cette interface, c'est au travers de cette méthode qu'ArgoUML va récupérer le JMenuItem fourni par notre PluggableMenu et l'insérer dans le bon context (précédemment demandé).
La méthode buildContext de l'interface PluggableMenu permet quant à elle de créer le tableau d'object qui sera renvoyé a la méthode inContext. Cette méthode est utilisée par Argo.
Le diagramme de séquence suivant explique comment se fait l'insertion d'une entrée dans le menu d'ArgoUML.
Nous allons maintenant écrire notre PluggableMenu. Que nous allons appeller ActionTestDiagram et qui sera un fils de la classe UMLAction tout en implémentant PluggableMenu (ceci nous permet d'avoir dans la même classe l'action qui créé le menu et celle qui est éxecutée lorsque l'item est séléctionné).
Notre classe devra bien sur implémenter toutes les méthodes de Module, de Pluggable et de PluggableMenu, ainsi que ActionPerformed qui sera l'action exécutée par notre menu (pour commencer ce sera un simple System.out.println("Hello World!!").
Elle sera placée dans le répertoire src/org/argouml/uml/ui que vous devez créer, et appartiendra donc au package org.argouml.uml.ui.
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 }; } }
Une fois que la nouvelle classe est écrite, vous pouvez lancer Argo avec votre Nouveau module grâce à la commande ant run depuis le répertoire de votre module.
Votre module devrait être chargé par Argo, et vous devriez voir les message suivant s'afficher :
[java] *** Initialisation de TestDiagram [java] Loaded Module: TestDiagramDe plus, dans le menu "Créer Diagramme", un nouvel item est apparu : "Test Diagram" Si on selectionne cet item, HelloWorld!! s'affiche sur la console.
Au chargement du module, un message indique qu'il n'a pas pu trouver une Icône ... en effet, lorsque nous avons créé notre JMenuItem, nous lui avons associé l'icône TestDiagram que nous n'avons ni créée ni placée dans le jar.
Les icônes sont placées dans le répertoire src/org/argouml/Images vous pouvez donc y placer une icône portant le nom TestDiagram.gif au format .gif.
Il va nous falloir modifier un petit peu le fichier build.xml pour qu'il copie toutes les images du répertoire src/org/argouml/Images dans le répertoire build/classes/org/argouml/Images, ce qui permettra ensuite à GEF de retrouver l'icône (c'est en fait le RessourceLoader de GEF qui s'occupe de ça.
Les modifications sont à effectuer pour la cible prepare qui s'occupe de préparer les répertoires dans lesquels seront placés les fichiers à archiver.
<!-- =================================================================== --> <!-- 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>
Si vous executez ant run, vous devriez maintenant voir votre icône à côté du texte pour votre JMenuItem.
Nous arrivons enfin au sujet de l'article ... la création d'un nouveau diagramme.
Les fichiers sources concernant notre diagramme seront placés dans src/org/argouml/uml/diagram/test/, le package sera donc org.argouml.uml.diagram.test et il vous faut créer ce répertoire ainsi que le répertoire src/org/Argouml/uml/diagram/test/ui dans lequel seront placées toutes les classes se rapportant à l'interface utilisateur.
Le diagramme que nous allons réaliser sera un diagramme de classe tout simple dans lequel les classes sont représentées par des rectangles et dans lequel il n'y a que des associations entre les classes.
Nous allons commencer par écrire un GraphModel pour notre diagramme.
Il s'agit juste de remplir les methodes du MutableGraphModel. Par contre, le nombre de methodes est assez important. Pour l'exemple, j'ai pris le GraphModel du Diagramme de Classe que j'ai simplifié en enlevant les généralisations, et les interfaces.
Le GraphModel est composé de deux vecteurs qui sont _nodes et _edges et qui contiennent les noeuds et les liaisons du modèle.
On peut remarquer dans le code du GraphModel qu'à chaque fois qu'un élément du modèle est ajouté ou enlevé, un évènement est envoyé. Il sera récupéré par le layer qui propagera les modifications.
Le GraphRenderer est encore plus simple à implémenter que le GraphModel puisqu'il suffit de renvoyer la figure qui va bien.
Nous allons appeller les figures qui représenteront les classes FigClass et celles qui représenteront les associations FigAssociation.
Lorsque l'on veut une figure pour une classe, on appelle getFigNodeFor cette fonction renverra une nouvelle FigClass correspondante. Pour une liaison, il faut en plus récupérer les extrémités et le connecter ce qui demande beaucoup plus de travail. Ci dessous l'implémentation de FigNodeFor pour notre diagramme.
public FigEdge getFigEdgeFor(GraphModel gm, Layer lay, Object edge) { if (edge instanceof MAssociation) { MAssociation a = (MAssociation) edge; FigAssociation aFig = new FigAssociation(a); Collection connections = a.getConnections(); if (connections == null) System.out.println("null connections...."); Object[] con = connections.toArray(); MAssociationEnd fromEnd = (MAssociationEnd) con[0]; MClassifier fromCls = (MClassifier) fromEnd.getType(); MAssociationEnd toEnd = (MAssociationEnd) con[1]; MClassifier toCls = (MClassifier) toEnd.getType(); FigNode fromFN = (FigNode) lay.presentationFor(fromCls); FigNode toFN = (FigNode) lay.presentationFor(toCls); aFig.setSourcePortFig(fromFN); aFig.setSourceFigNode(fromFN); aFig.setDestPortFig(toFN); aFig.setDestFigNode(toFN); aFig.getFig().setLayer(lay); return aFig; } return null; }
Il nous allons maintenant créer les figures pour notre diagramme. Nous avons deux figures à créer une du type FigNodeModelElement et l'autre du type FigEdgeModelElement.
Les noeuds (FigNodeModelElement) dérivent de FigNode dans GEF. Elles sont constitué d'un ou de plusieurs ports ainsi que de figures qui permettent de dessiner l'element. La plupart des diagrammes dans Argo n'ont qu'un seul port qui s'appelle généralement _bigPort. Voici le constructeur de notre FigClass.
public FigClass() { _bigPort = new FigRect(X+1, Y+1, W+2, H+2, null, null); _bigPort.setLineWidth(0); _rectangle = new FigRect(X, Y, W, H, Color.black, Color.yellow); _rectangle.setFilled(true); setBounds(X+1, Y+1, W+2, H+2); addFig(_bigPort); addFig(_rectangle); } public FigClass(GraphModel gm, Object node) { this(); setOwner(node); }
On construit les éléments de la figure et on les ajoute ensuite à notre figure. Le port (_bigPort) est un élément comme les autres. Ici il est invisible.
Le fait que le port par défaut soit _figPort est défini dans la classe FigNodeModelElement. Si on veut ajouter d'autres ports pour des types de liaisons différente, on peut utiliser la méthode bindPort qui associe un Object à une figure du dessin.
Il est nécéssaire de surcharger la fonction setBounds pour que le redimensionnement de la figure se fasse correctement.
public void setBounds(int x, int y, int w, int h) { Rectangle oldBounds = getBounds(); _bigPort.setBounds(x, y, w, h); _rectangle.setBounds(x,y,w,h); calcBounds(); updateEdges(); firePropChange("bounds", oldBounds,getBounds()); }
Comme on peut le voir, il est nécessaire de lancer un événement PropChange pour propager des modification aux listeners.
Si maintenant, on veut ajouter le nom de la classe sur le diagramme, il nous faut ajouter une nouvelle figure. On va d'abord modifier le constructeur.
public FigClass() { _bigPort = new FigRect(X+1, Y+1, W+2, H+2, null, null); _bigPort.setLineWidth(0); _rectangle = new FigRect(X, Y, W, H, Color.black, Color.yellow); _rectangle.setFilled(true); _name = new FigText(W, Y, W, H); _name.setFilled(false); _name.setLineWidth(0); Rectangle r = _name.getBounds(); setBounds(r); addFig(_bigPort); addFig(_rectangle); addFig(_name); }
On peut noter qu'il est important d'effectuer les appels à addFig dans le bon ordre puisque cet appel détermine la position des figures les unes par rapport aux autres.
Pour que le champ _name soit correctement initialisé lors de l'insertion d'une figure dans le diagramme, il faut surcharger la méthode modelChanged.
public void modelChanged() { MClass owner = (MClass)getOwner(); String name = owner.getName(); _name.setText(name != null ? name : ""); }
Il nous faut aussi modifier l'appel à clone pour que _name soit correctement clonnée.
public Object clone() { FigClass figClone = (FigClass) super.clone(); Vector v = figClone.getFigs(); figClone._bigPort = (FigRect) v.elementAt(0); figClone._rectangle = (FigRect) v.elementAt(1); figClone._name = (FigText) v.elementAt(2); return figClone; }
En ce qui concerne notre FigAssociation, son implémentation n'est pas très compliquée puisqu'elle ne comprends qu'un constructeur.
UMLTestDiagram est la classe qui représente notre diagramme.
Les premières définitions que l'on rencontre sont les définitions statiques des Cmd permettant de créer nos figures
protected static Action _actionClass = new CmdCreateNode(MClassImpl.class, "Class"); protected static Action _actionAssociation = new CmdSetMode(ModeCreatePolyEdge.class, "edgeClass", MAssociationImpl.class, "Association");
Ensuite vient notre constructeur qui est chargé de construire tout l'environnement du diagramme c'est-à-dire le TestDiagramGraphModel, LayerPerspective et TestDiagramRenderer et d'initialiser tout ça.
public UMLTestDiagram() { String name = "Test diagram " + _TestDiagramSerial; _TestDiagramSerial++; try { setName(name); } catch (PropertyVetoException pve) { } } public UMLTestDiagram(MNamespace m) { this(); TestDiagramGraphModel gm = new TestDiagramGraphModel(); setNamespace(m); setGraphModel(gm); LayerPerspective lay = new LayerPerspectiveMutable(m.getName(), gm); setLayer(lay); TestDiagramRenderer rend = new TestDiagramRenderer(); lay.setGraphNodeRenderer(rend); lay.setGraphEdgeRenderer(rend); }
Les méthodes getOwner et setNameSpace sont des accesseurs vers le GraphModel.
Finalement initToolBar initialise la toolbar en créant les boutons et en y associant des actions.
Maintenant que nous avons tous les éléments du diagramme, on aimerait bien pouvoir le tester. Pour cela il faut pouvoir le créer et cela se fait normalement à l'aide d'une séléction d'un élement dans un menu (comme par hasard nous avons déjà réservé de la place pour cela.
Il va donc nous falloir remplacer la méthode actionPerformed de ActionTestDiagram par une vraie actionPerformed qui fait quelque chose d'utile : instancier UMLTestDiagram.
Voilà le code de notre nouvelle ActionPerformed :
/** * Action executée par la selection du menu */ public void actionPerformed (ActionEvent ae) { Project p = ProjectBrowser.TheInstance.getProject(); Object target = ProjectBrowser.TheInstance.getDetailsTarget(); MNamespace ns = p.getCurrentNamespace(); if (target instanceof MPackage) ns = (MNamespace) target; try { ArgoDiagram d = new UMLTestDiagram(ns); p.addMember(d); ProjectBrowser.TheInstance.getNavPane().addToHistory(d); ProjectBrowser.TheInstance.setTarget(d); } catch (PropertyVetoException pve) { } }
Comme on peut le voir, quelques enregistrements aux bons endroits et c'est gagné !!
Une fois que tout ceci est terminé, on peut normalement tester notre nouveau diagramme.