001    /*
002      Copyright (C) 2002-2003 Renaud Pawlak <renaud@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017    */
018    
019    package org.objectweb.jac.ide.diagrams;
020    
021    import CH.ifa.draw.framework.Drawing;
022    import CH.ifa.draw.framework.DrawingEditor;
023    import CH.ifa.draw.framework.DrawingView;
024    import CH.ifa.draw.framework.Figure;
025    import CH.ifa.draw.framework.FigureEnumeration;
026    import CH.ifa.draw.framework.Tool;
027    import CH.ifa.draw.framework.ViewChangeListener;
028    import CH.ifa.draw.standard.ChangeAttributeCommand;
029    import CH.ifa.draw.standard.ChopBoxConnector;
030    import CH.ifa.draw.standard.StandardDrawing;
031    import CH.ifa.draw.util.ColorMap;
032    import CH.ifa.draw.util.CommandChoice;
033    import CH.ifa.draw.util.Filler;
034    import CH.ifa.draw.util.PaletteButton;
035    import CH.ifa.draw.util.PaletteListener;
036    import CH.ifa.draw.util.StandardVersionControlStrategy;
037    import CH.ifa.draw.util.VersionControlStrategy;
038    import CH.ifa.draw.util.VersionManagement;
039    import CH.ifa.draw.util.VersionRequester;
040    import java.awt.BorderLayout;
041    import java.awt.Component;
042    import java.awt.Point;
043    import java.awt.datatransfer.Transferable;
044    import java.awt.dnd.DnDConstants;
045    import java.awt.dnd.DropTarget;
046    import java.awt.dnd.DropTargetDragEvent;
047    import java.awt.dnd.DropTargetDropEvent;
048    import java.awt.dnd.DropTargetEvent;
049    import java.awt.dnd.DropTargetListener;
050    import java.awt.event.ActionEvent;
051    import java.awt.event.ActionListener;
052    import java.awt.event.KeyAdapter;
053    import java.awt.event.KeyEvent;
054    import java.awt.event.MouseAdapter;
055    import java.awt.event.MouseEvent;
056    import java.util.Iterator;
057    import java.util.List;
058    import java.util.Vector;
059    import javax.swing.JComboBox;
060    import javax.swing.JLabel;
061    import javax.swing.JPanel;
062    import javax.swing.JScrollPane;
063    import org.objectweb.jac.aspects.gui.CollectionUpdate;
064    import org.objectweb.jac.aspects.gui.DisplayContext;
065    import org.objectweb.jac.aspects.gui.EventHandler;
066    import org.objectweb.jac.aspects.gui.GuiAC;
067    import org.objectweb.jac.aspects.gui.Transfer;
068    import org.objectweb.jac.aspects.gui.Utils;
069    import org.objectweb.jac.aspects.gui.ViewFactory;
070    import org.objectweb.jac.aspects.gui.swing.AbstractView;
071    import org.objectweb.jac.aspects.gui.swing.SwingEvents;
072    import org.objectweb.jac.core.rtti.ClassRepository;
073    import org.objectweb.jac.core.rtti.CollectionItem;
074    import org.objectweb.jac.ide.Aspect;
075    import org.objectweb.jac.ide.Class;
076    import org.objectweb.jac.ide.Diagram;
077    import org.objectweb.jac.ide.InheritanceLink;
078    import org.objectweb.jac.ide.Link;
079    import org.objectweb.jac.ide.ModelElement;
080    import org.objectweb.jac.ide.Package;
081    import org.objectweb.jac.ide.RelationLink;
082    import org.objectweb.jac.ide.RelationRole;
083    import org.objectweb.jac.ide.TypedElement;
084    import org.objectweb.jac.util.Log;
085    import org.objectweb.jac.util.Strings;
086    
087    public class DiagramView extends AbstractView
088        implements DrawingEditor, PaletteListener, VersionRequester, 
089                  CollectionUpdate, DropTargetListener
090    {
091        static public boolean init = false;
092    
093        protected Diagram diagram;
094    
095        public DiagramView(ViewFactory factory, DisplayContext context, 
096                           Object diagram) {
097            super(factory,context);
098            new DropTarget(this, // component
099                           DnDConstants.ACTION_COPY_OR_MOVE, // actions
100                           this); // DropTargetListener
101            this.diagram = (Diagram)diagram;
102            init();
103            Utils.registerCollection(diagram,"figures",this);
104        }
105    
106        public void close(boolean validate) {
107            Log.trace("diagram","CLOSING DIAGRAM "+this);
108            super.close(validate);
109            FigureEnumeration figures = fDrawing.figures();
110            while (figures.hasMoreElements()) {
111                Figure f = figures.nextFigure();
112                if (f instanceof ModelElementFigure)
113                    ((ModelElementFigure)f).close();
114            }
115            Utils.unregisterCollection(diagram,"figures",this);      
116        }
117    
118        public Object getSubstance() {
119            return diagram;
120        }
121    
122        public final Diagram getDiagram() {
123            return diagram;
124        }
125    
126        /**
127         * Add a figure for a class at a given location
128         * @param cl the class to add a figure for
129         * @param location where to put the class figure
130         */
131        public void addClass(Class cl, Point location) {
132            Diagram diagram = (Diagram)getSubstance();
133            if (diagram.contains(cl)) 
134                return;
135            ClassFigure cf = null;
136            org.objectweb.jac.ide.ClassFigure figure = new org.objectweb.jac.ide.ClassFigure(cl);
137            Log.trace("diagram","diagram = "+diagram);
138            diagram.addFigure(figure);
139            Log.trace("diagram","creating new figure "+figure+","+
140                      diagram.getContainer());
141            cf = new ClassFigure(figure,diagram.getContainer(),
142                                 view());
143            (view().add(cf)).displayBox(location,location);
144        }
145    
146        /**
147         * Import all relations and inheritance links between a class with
148         * other classes on the diagram
149         * @param cl the class to import relations for 
150         */
151        public void importRelations(Class cl) {
152            Iterator it = diagram.getMissingRelations(cl).iterator();
153            while (it.hasNext()) {
154                Link relation = (Link)it.next();
155                try {
156                    if (relation instanceof RelationLink)
157                        importRelation((RelationLink)relation);
158                    else if (relation instanceof InheritanceLink)
159                        importInheritance((InheritanceLink)relation);
160                } catch (Exception e) {
161                     Log.warning(e.getMessage());
162                }
163            }
164        }
165    
166        /**
167         * Import a relation in the diagram.
168         * @param relation the relation to import
169         * @throws Exception if both classes of the relation are not on the diagram
170         */
171        public void importRelation(RelationLink relation) throws Exception {
172            ClassFigure endFig = findClass((Class)relation.getEnd());
173            if (endFig==null) {
174                throw new Exception("Cannot import relation "+GuiAC.toString(relation)+
175                                    " since "+GuiAC.toString(relation.getEnd())+
176                                    " is not on the diagram");
177            }
178            ClassFigure startFig = findClass((Class)relation.getStart());
179            if (startFig==null) {
180                throw new Exception("Cannot import relation "+GuiAC.toString(relation)+
181                                    " since "+GuiAC.toString(relation.getStart())+
182                                    " is not on the diagram");
183            }
184    
185            org.objectweb.jac.ide.LinkFigure linkFig = new org.objectweb.jac.ide.LinkFigure(relation);
186            diagram.addFigure(linkFig);
187          
188            RelationLinkFigure relf = new RelationLinkFigure();
189            relf.setLinkFigure(linkFig);
190    
191            relf.startPoint(startFig.center());
192            relf.endPoint(endFig.center());
193            relf.connectStart(startFig.connectorAt(startFig.center()));
194            relf.connectEnd(endFig.connectorAt(endFig.center()));
195    
196            relf.updateConnection();
197          
198            view().add(relf);
199            if (relation.getName()!=null && !relation.getName().equals(""))
200                view().add(relf.createName());
201            if (relation.getEndRole()!=null && !relation.getEndRole().equals(""))
202                view().add(relf.createEndRole());
203            if (relation.getStartRole()!=null && !relation.getStartRole().equals(""))
204                view().add(relf.createStartRole());
205            String startCardinality = relation.startRole().getCardinality();
206            if (startCardinality!=null && !startCardinality.equals(""))
207                view().add(relf.createStartCardinality());
208            String endCardinality = relation.endRole().getCardinality();
209            if (endCardinality!=null && !endCardinality.equals(""))
210                view().add(relf.createEndCardinality());
211          
212            Utils.registerObject(relation,relf);
213        }
214    
215        /**
216         * Import an inheritance link in the diagram. An exception 
217         * @param inheritance the inheritance link to import
218         */
219        public void importInheritance(InheritanceLink inheritance) throws Exception {
220            ClassFigure endFig = findClass((Class)inheritance.getEnd());
221            ClassFigure startFig = findClass((Class)inheritance.getStart());
222          
223            org.objectweb.jac.ide.LinkFigure linkFig = new org.objectweb.jac.ide.LinkFigure(inheritance);
224            diagram.addFigure(linkFig);
225          
226            InheritanceLinkFigure relf = new InheritanceLinkFigure();
227            relf.setLinkFigure(linkFig);
228    
229            relf.startPoint(startFig.center());
230            relf.endPoint(endFig.center());
231            relf.connectStart(startFig.connectorAt(startFig.center()));
232            relf.connectEnd(endFig.connectorAt(endFig.center()));
233    
234            relf.updateConnection();
235          
236            view().add(relf);
237          
238            Utils.registerObject(inheritance,relf);
239        }
240    
241        /**
242         * Create a RelationLink between two classes.
243         * @param source start class of the link
244         * @param target end class of the link
245         * @param linkfigure the figure that represents the relation
246         * @param isAggregation wether the relation is an aggregation
247         */
248        public void createRelation(Class source, Class target, 
249                                   RelationLinkFigure linkFigure,
250                                   boolean isAggregation) {
251            Log.trace("figures","creating a new relation link between "+
252                      source+" and "+target);
253    
254            RelationLink rel = new RelationLink();
255            rel.setStart(source);
256            rel.setEnd(target);
257            rel.setAggregation(isAggregation);
258            Log.trace("diagram","1. end="+rel.getEnd()+"===> substance="+target);
259            org.objectweb.jac.ide.LinkFigure linkFig = new org.objectweb.jac.ide.LinkFigure(rel);
260            linkFigure.setLinkFigure(linkFig);
261            view().add(linkFigure.createName());
262            view().add(linkFigure.createEndRole());
263            view().add(linkFigure.createStartRole());
264            view().add(linkFigure.createStartCardinality());
265            view().add(linkFigure.createEndCardinality());
266          
267            Log.trace("diagram","2. end="+rel.getEnd());
268    
269            if (source==target) {
270                Point c = linkFigure.endFigure().center();
271                linkFig.addPoint(1,new Point(c.x+100,c.y));
272                linkFig.addPoint(1,new Point(c.x+100,c.y+100));
273                linkFig.addPoint(1,new Point(c.x,c.y+100));
274            }
275          
276            diagram.addFigure(linkFig);
277    
278            Utils.registerObject(rel,linkFigure);
279            Log.trace("diagram","3. end="+rel.getEnd());
280        }
281    
282        // drop listener interface
283        public void drop(DropTargetDropEvent e) {
284            try {
285                Transferable tr = e.getTransferable();
286                List transfered = Transfer.getTransferedWrappees(tr);
287                Object o = transfered.get(0);
288                Point location = e.getLocation();
289                Point offset = scrollPane.getViewport().getViewPosition();
290                location.translate((int)offset.getX(),(int)offset.getY());
291                Log.trace("gui.dnd","drop event: "+o);
292                if (o==null) 
293                    return;
294                if (o instanceof Class) {
295                    addClass((Class)o,location);
296                } else if (o instanceof RelationRole) {
297                    importRelation((RelationLink)((RelationRole)o).getLink());
298                }
299    
300            } catch(Exception ex) {
301                ex.printStackTrace();
302            }
303        }
304        public void dragEnter(DropTargetDragEvent e) { }
305        public void dragExit(DropTargetEvent e) { }
306        public void dragOver(DropTargetDragEvent e) { }
307        public void dropActionChanged(DropTargetDragEvent e) { }
308        // end of drop listener interface
309    
310        public void figureSelectionChanged(DrawingView view) {
311            if (view.selection().size() > 0) {
312                Figure f = (Figure)view.selection().get(0);
313    
314                Log.trace("figures","figure "+f+" selected");
315    
316                if (f instanceof Selectable) {
317                    ((Selectable)f).onSelect(getContext());
318                }
319    
320                if (f instanceof ClassFigure) {
321                    CollectionItem coll = ClassRepository.get().getClass(Package.class)
322                        .getCollection("classes");
323                    EventHandler.get().onSelection(
324                        getContext(),coll,((ClassFigure)f).getSubstance(),null,null);
325    
326                } else if (f instanceof InstanceFigure) {
327                    CollectionItem coll = ClassRepository.get().getClass(Package.class)
328                        .getCollection("instances");
329                    EventHandler.get().onSelection(
330                        getContext(),coll,((InstanceFigure)f).getSubstance(),null,null);
331    
332                } else if (f instanceof GenericObjectFigure) {
333    
334                    Log.trace("figures","generic object");
335                    EventHandler.get().onSelection(
336                        getContext(),
337                        ((GenericObjectFigure)f).getCollection(),
338                        ((GenericObjectFigure)f).getSubstance(),null,null);
339    
340                } else if (f instanceof RelationLinkFigure || 
341                           f instanceof AttachedTextFigure) {
342                
343                    RelationLink rel = (RelationLink)
344                        ((ModelElementFigure)f).getSubstance();
345                    Class cl = (Class)rel.getStart();
346                    CollectionItem coll = ClassRepository.get().getClass(Package.class)
347                        .getCollection("classes");
348                    EventHandler.get().onSelection(getContext(),coll,cl,null,null);
349                    coll = ClassRepository.get().getClass(Class.class)
350                        .getCollection("relationRoles");
351                    EventHandler.get().onSelection(getContext(),coll,
352                                                   rel.getStartRole(),null,null);
353                    //((RelationLinkFigure)f).selectAll(view);
354    
355                } else if (f instanceof PointcutLinkFigure) {
356                
357                    org.objectweb.jac.ide.PointcutLink rel = (org.objectweb.jac.ide.PointcutLink)
358                        ((PointcutLinkFigure)f).getSubstance();
359                    org.objectweb.jac.ide.Aspect aspect = (org.objectweb.jac.ide.Aspect)rel.getStart();
360                    CollectionItem coll = ClassRepository.get().getClass(Package.class)
361                        .getCollection("aspects");
362                    EventHandler.get().onSelection(getContext(),coll,aspect,null,null);
363                    coll = ClassRepository.get().getClass(Aspect.class)
364                        .getCollection("pointcutLinks");
365                    EventHandler.get().onSelection(getContext(),coll,rel,null,null);
366                    //((PointcutLinkFigure)f).selectAll(view);
367                }
368            }
369            //      update(getGraphics());
370        }
371    
372        private transient Drawing         fDrawing;
373        private transient Tool            fTool;
374       
375        private transient DrawingView     fView;
376        private transient ToolButton      fSelectedToolButton;
377       
378        static String                     fgUntitled = "untitled";
379       
380        ToolPalette classPalette;
381        ToolPalette aspectPalette;
382        ToolPalette instancePalette;
383        ToolPalette groupPalette;
384        ToolPalette currentPalette;
385    
386        /**
387         * Find the figure of a given class in the default drawing.
388         * @param cl the Class to search for
389         * @return a ModelElementFigure that matches cl, or null if none is found.
390         */
391        public ClassFigure findClass(Class cl) {
392            return (ClassFigure)findFigure(view().drawing(),cl);
393        }
394    
395        /**
396         * Find the figure of a given model element
397         * @param drawing the Drawing to search the figure into
398         * @param cl the Class to search for
399         * @return a ModelElementFigure that matches cl, or null if none is found.
400         */
401        public ClassFigure findClass(Drawing drawing, Class cl) {
402            return (ClassFigure)findFigure(drawing,cl);
403        }
404    
405        /**
406         * Find the figure of a given model element.
407         * @param drawing the Drawing to search the figure into
408         * @param element the ModelElement to search for
409         * @return a ModelElementFigure that matches element, or null if none is found.
410         */
411        public ModelElementFigure findFigure(Drawing drawing, ModelElement element) {
412            FigureEnumeration figs = drawing.figures();
413            while(figs.hasMoreElements()) {
414                Figure fig = figs.nextFigure();
415                if( (fig instanceof ModelElementFigure) && 
416                    ((ModelElementFigure)fig).getSubstance() == element) {
417                    return (ModelElementFigure)fig;
418                }
419            }
420            return null;
421        }
422    
423        /**
424         * Find the figure of a given TypedElement
425         */
426        public Figure findElement(TypedElement te) {
427            FigureEnumeration figs = view().drawing().figures();
428            while(figs.hasMoreElements()) {
429                Figure fig = figs.nextFigure();
430                if( (fig instanceof ModelElementFigure) && 
431                    ((ModelElementFigure)fig).getSubstance() == te) {
432                    return fig;
433                }
434            }
435            return null;
436        }
437    
438        /**
439         * Find the figure of a given ModelElement
440         */
441        public Figure findElement(ModelElement element) {
442            FigureEnumeration figs = view().drawing().figures();
443            while(figs.hasMoreElements()) {
444                Figure fig = figs.nextFigure();
445                if( (fig instanceof ModelElementFigure) && 
446                    ((ModelElementFigure)fig).getSubstance() == element) {
447                    return fig;
448                }
449            }
450            return null;
451        }
452       
453        JScrollPane scrollPane;
454        /**
455         * Initializes the applet and creates its contents.
456         */
457        public void init() {
458            //DiagramView.display = display;
459            //diagramViews.add(this);
460    
461            getVersionControlStrategy().assertCompatibleVersion();
462                    
463            setLayout(new BorderLayout());
464    
465            fView = createDrawingView();
466    
467            try {
468                buildClassBar();
469            } catch (Exception e) {
470                e.printStackTrace();
471            }
472    
473            scrollPane = new JScrollPane((Component)view());
474            add("Center", scrollPane);
475            JPanel buttonPalette = createButtonPanel();
476            createButtons(buttonPalette);
477            add("North", buttonPalette);
478            setToolBar(buildClassBar());
479    
480            initDrawing();
481            // JFC should have its own internal double buffering...
482            //setBufferedDisplayUpdate();
483            //setupAttributes();
484            load();
485            //((JComponent)drawing()).setMinimumSize(new Dimension(2000,2000));
486        }
487    
488        public void addViewChangeListener(ViewChangeListener vsl) {
489        }
490    
491        public void removeViewChangeListener(ViewChangeListener vsl) {
492        }
493    
494    
495        /**
496         * Creates the color choice for the given attribute.
497         */
498        protected JComboBox createColorChoice(String attribute) {
499            CommandChoice choice = new CommandChoice();
500            for (int i = 0; i < ColorMap.size(); i++)
501                choice.addItem(
502                    new ChangeAttributeCommand(
503                        ColorMap.name(i),
504                        attribute,
505                        ColorMap.color(i),
506                        this
507                    )
508                        );
509            return choice;
510        }
511    
512        /**
513         * Creates the buttons panel.
514         */
515        protected JPanel createButtonPanel() {
516            JPanel panel = new JPanel();
517            panel.setLayout(new PaletteLayout(2, new Point(2,2), false));
518            return panel;
519        }
520    
521        /**
522         * Sets the tool bar containing tool buttons.
523         */
524        void setToolBar(ToolPalette newPalette) {
525            if (currentPalette != null) {
526                remove(currentPalette);
527            }
528            add(BorderLayout.WEST, newPalette);
529            currentPalette = newPalette;
530            validate();
531        }
532    
533        ToolPalette buildClassBar() {
534            Log.trace("diagram","BUILDING CLASS BAR");         
535            classPalette = new ToolPalette();
536    
537            classPalette.setDefaultToolButton(
538                classPalette.addToolButton(this, "icon_selection", "Selection Tool", 
539                                           createSelectionTool()));
540    
541            classPalette.addToolButton(this, "icon_text", "Text Tool", 
542                                       new TextTool(this, new TextFigure()));
543            classPalette.addToolButton(this, "icon_class", "Create a new class", 
544                                       new NewClassFigureCreationTool(this,getContext()));
545            classPalette.addToolButton(this, "icon_import_class", "Add an existing class", 
546                                       new ClassFigureCreationTool(this,getContext()));
547            try {
548                classPalette.addToolButton(this, "icon_see_relation", "Show existing relation", 
549                                           new RelationLinkShowTool(this,getContext()));
550            } catch (ClassNotFoundException e) {
551                e.printStackTrace();
552            }
553            classPalette.addToolButton(this, "icon_relation", "New relation link", 
554                                       new RelationLinkCreationTool(this));
555            classPalette.addToolButton(this, "icon_add_point", "Add a point", 
556                                       new ConnectionTool(this, new RelationLinkFigure()));
557            classPalette.addToolButton(this, "icon_inheritance", "Inheritance link", 
558                                       new InheritanceLinkCreationTool(this));
559            classPalette.addToolButton(this, "icon_field", "Create new attribute", 
560                                       new FieldCreationTool(this,getContext()));
561            classPalette.addToolButton(this, "icon_method", "Create new method", 
562                                       new MethodCreationTool(this,getContext()));
563            return classPalette;
564        }
565    
566        ToolPalette buildAspectBar() {
567            Log.trace("diagram","BUILDING ASPECT BAR");
568          
569            aspectPalette = new ToolPalette();
570          
571            aspectPalette.setDefaultToolButton(
572                aspectPalette.addToolButton(this, "icon_selection", "Selection Tool", 
573                                            createSelectionTool()));
574          
575            aspectPalette.addToolButton(this, "icon_text", "Text Tool", 
576                                        new TextTool(this, new TextFigure()));
577            aspectPalette.addToolButton(this, "icon_aspect", "Create a new aspect", 
578                                        new NewAspectFigureCreationTool(this,getContext()));
579            aspectPalette.addToolButton(this, "icon_import_aspect", "Add an existing aspect", 
580                                        new AspectFigureCreationTool(this,getContext()));
581            aspectPalette.addToolButton(this, "icon_pointcut", "New pointcut link", 
582                                        new PointcutLinkCreationTool(this, new PointcutLinkFigure()));
583            aspectPalette.addToolButton(this, "icon_see_pointcut", "Show existing pointcut",
584                                        new PointcutLinkShowTool(this,getContext()));
585            aspectPalette.addToolButton(this, "icon_add_point", "Add a point", 
586                                        new ConnectionTool(this, new RelationLinkFigure()));
587            aspectPalette.addToolButton(this, "icon_field", "Create new attribute", 
588                                        new FieldCreationTool(this,getContext()));
589            aspectPalette.addToolButton(this, "icon_method", "Create new configuration method", 
590                                        new MethodCreationTool(this,getContext()));
591            aspectPalette.addToolButton(this, "icon_aspect_method","Create new aspect method", 
592                                        new MethodCreationTool(this,getContext()));
593            return aspectPalette;
594        }
595    
596        ToolPalette buildInstanceBar() {
597            Log.trace("diagram","BUILDING INSTANCE BAR");
598             
599            instancePalette = new ToolPalette();
600          
601            instancePalette.setDefaultToolButton(
602                instancePalette.addToolButton(this, "icon_selection", "Selection Tool",
603                                              createSelectionTool()));
604            instancePalette.addToolButton(this, "icon_text", "Text Tool", 
605                                          new TextTool(this, new TextFigure()));      
606            instancePalette.addToolButton(this, "icon_instance", "Create a new instance", 
607                                          new NewInstanceFigureCreationTool(this,getContext()));
608            instancePalette.addToolButton(this, "icon_import_instance", "Add an existing instance", 
609                                          new InstanceFigureCreationTool(this,getContext()));
610            return instancePalette;
611        }
612    
613        ToolPalette buildGroupBar() {
614            Log.trace("diagram","BUILDING GROUP BAR");
615             
616            groupPalette = new ToolPalette();
617    
618            groupPalette.setDefaultToolButton(
619                groupPalette.addToolButton(this,"icon_selection", "Selection Tool", 
620                                           createSelectionTool()));         
621            groupPalette.addToolButton(this,"icon_text", "Text Tool", 
622                                       new TextTool(this, new TextFigure()));
623            groupPalette.addToolButton(this, "icon_group", "Create a new group", 
624                                       new NewInstanceFigureCreationTool(this,getContext()));
625            groupPalette.addToolButton(this, "icon_import_group", "Add an existing group", 
626                                       new GroupFigureShowTool(this,getContext()));
627            return groupPalette;
628        }
629    
630        /**
631         * Creates the buttons shown in the buttons panel. Override to
632         * add additional buttons.
633         * @param panel the buttons panel.
634         */
635        protected void createButtons(JPanel panel) {
636            panel.add(new Filler(24,20));
637            JLabel title = new JLabel(GuiAC.toString(diagram)+" diagram  ");
638            panel.add(title);
639    
640            panel.add(new Filler(6,20));
641    
642            JComboBox combo = new JComboBox(new Object[] {
643                "class mode",
644                "aspect mode",
645                "instance mode",
646                "group mode"}
647            );
648    
649            combo.addActionListener(
650                new ActionListener() {
651                        public void actionPerformed(ActionEvent event) {
652                            JComboBox cb = (JComboBox)event.getSource();
653                            String command = (String)cb.getSelectedItem();
654                            if (command.equals("class mode")) {
655                                setToolBar(buildClassBar());
656                            } else if (command.equals("aspect mode")) {
657                                setToolBar(buildAspectBar());
658                            } else if (command.equals("instance mode")) {
659                                setToolBar(buildInstanceBar());
660                            } else if (command.equals("group mode")) {
661                                setToolBar(buildGroupBar());
662                            }
663                            setSelected(currentPalette.getDefaultToolButton());
664                        }
665                    }
666            );
667    
668            panel.add(combo);
669            coord = new JLabel("(--,--)");
670            panel.add(coord);
671        }
672    
673        JLabel coord;
674        public void setCoord(int x, int y) {
675            coord.setText("("+x+","+y+")");
676        }
677    
678        /**
679         * Creates the tools palette.
680         */
681        protected JPanel createToolPalette() {
682            JPanel palette = new JPanel();
683            palette.setLayout(new PaletteLayout(2,new Point(2,2)));
684            return palette;
685        }
686    
687        /**
688         * Creates the selection tool used in this editor. Override to use
689         * a custom selection tool.
690         */
691        protected Tool createSelectionTool() {
692            return new SelectionTool(this,getContext());
693        }
694    
695        /**
696         * Creates the drawing used in this application.
697         * You need to override this method to use a Drawing
698         * subclass in your application. By default a standard
699         * Drawing is returned.
700         */
701        protected Drawing createDrawing() {
702            return new StandardDrawing();
703        }
704    
705        /**
706         * Creates the drawing view used in this application.
707         * You need to override this method to use a DrawingView
708         * subclass in your application. By default a standard
709         * DrawingView is returned.
710         */
711        protected DrawingView createDrawingView() {
712            IDEDrawingView view = new IDEDrawingView(this, 2000, 2000);
713            view.addMouseListener(
714                new MouseAdapter() {
715                        public void mousePressed(MouseEvent e) {
716                            // Show popup menu
717                            if (e.isPopupTrigger()) {
718                                Figure figure = drawing().findFigure(e.getX(), e.getY());
719                                if (figure instanceof ModelElementFigure) {
720                                    ModelElement element = 
721                                        ((ModelElementFigure)figure).getSubstance();
722                                    if (figure instanceof ClassFigure) {
723                                        Figure memberFigure = figure.findFigureInside(e.getX(), e.getY());
724                                        if (memberFigure instanceof MemberFigure) {
725                                            SwingEvents.showObjectsMenu(
726                                                getContext(), 
727                                                new Object[] {((ClassFigure)figure).getClassFig(),
728                                                              element,
729                                                              ((MemberFigure)memberFigure).getSubstance()}, 
730                                                e);
731                                        } else {
732                                            SwingEvents.showObjectsMenu(
733                                                getContext(), new Object[] {((ClassFigure)figure).getClassFig(),element}, e);
734                                        }
735                                    } else {
736                                        SwingEvents.showObjectMenu(getContext(), element, e);
737                                    }
738                                }
739                            }
740                        }
741                    }
742            );
743    
744            view.addKeyListener(
745                new KeyAdapter() {
746                        public void keyPressed(KeyEvent e) {
747                            int code = e.getKeyCode();
748                            if ((code == KeyEvent.VK_BACK_SPACE) || 
749                                (code == KeyEvent.VK_DELETE)) 
750                            {
751                                Log.trace("ide.diagram","DELETE");
752                                Vector selection = view().selection();
753                                for (int i=0; i<selection.size(); i++) {
754                                    Figure figure = (Figure)selection.get(i);
755                                    if (figure instanceof ClassFigure || 
756                                        figure instanceof LinkFigure) {
757                                        Log.trace("ide.diagram","removing "+figure);
758                                        ModelElement element = 
759                                            ((ModelElementFigure)figure).getSubstance();
760                                        diagram.removeElement(element);
761                                    }
762                                    if (e.isControlDown()) {
763                                        Log.trace("ide.diagram","DELETE REAL");
764                                        if (figure instanceof ClassFigure) {
765                                            Class cl = 
766                                                (Class)((ModelElementFigure)figure).getSubstance();
767                                            cl.getContainer().removeClass(cl);
768                                        } else if (figure instanceof RelationLinkFigure) {
769                                            RelationLink link = 
770                                                (RelationLink)((ModelElementFigure)figure).getSubstance();
771                                            link.setStart(null);
772                                            link.setEnd(null);
773                                        } else if (figure instanceof InheritanceLinkFigure) {
774                                            InheritanceLink link = 
775                                                (InheritanceLink)((ModelElementFigure)figure).getSubstance();
776                                            ((Class)link.getStart()).setSuperClass(null);
777                                        }
778                                    }
779                                }
780                                view().clearSelection();
781                            }
782                        }
783                    }
784            );
785            return view;
786        }
787    
788        /**
789         * Handles a user selection in the palette.
790         * @see PaletteListener
791         */
792        public void paletteUserSelected(PaletteButton button) {
793            ToolButton toolButton = (ToolButton)button;
794            Log.trace("palette","paletteUserSelected "+toolButton.getTool());
795            setTool(toolButton.getTool(), toolButton.getName());
796            setSelected(toolButton);
797        }
798    
799        /**
800         * Handles when the mouse enters or leaves a palette button.
801         * @see PaletteListener
802         */
803        public void paletteUserOver(PaletteButton button, boolean inside) {
804            if (inside) {
805                showStatus(((ToolButton)button).name());
806            } else {
807                if(fSelectedToolButton==null) {
808                    showStatus("");
809                } else {
810                    showStatus(fSelectedToolButton.name());
811                }
812            }
813        }
814    
815        /**
816         * Gets the current drawing.
817         * @see DrawingEditor
818         */
819        public Drawing drawing() {
820            return fDrawing;
821        }
822    
823        /**
824         * Gets the current tool.
825         * @see DrawingEditor
826         */
827        public Tool tool() {
828            return fTool;
829        }
830    
831        /**
832         * Gets the current drawing view.
833         * @see DrawingEditor
834         */
835        public DrawingView view() {
836            return fView;
837        }
838    
839        public DrawingView[] views() {
840            return new DrawingView[] { view() } ;
841        }
842    
843        /**
844         * Sets the default tool of the editor.
845         * @see DrawingEditor
846         */
847        public void toolDone() {
848            if (currentPalette!=null) {
849                ToolButton button = currentPalette.getDefaultToolButton();
850                if (button!=null) {
851                    setTool(button.getTool(), button.getName());
852                    setSelected(button);
853                }
854            }
855        }
856    
857        public void viewSelectionChanged(DrawingView oldView, DrawingView newView) {
858        }
859    
860        private void initDrawing() {
861            fDrawing = createDrawing();
862            view().setDrawing(fDrawing);
863            toolDone();
864        }
865    
866        private void setTool(Tool t, String name) {
867            Log.trace("palette","setTool "+t+" current="+fTool);
868            if (fTool != null) {
869                fTool.deactivate();
870            }
871            fTool = t;
872            if (fTool != null) {
873                showStatus(name);
874                fTool.activate();
875            }
876        }
877    
878        private void setSelected(ToolButton button) {
879            if (fSelectedToolButton != null) {
880                fSelectedToolButton.reset();
881            }
882            fSelectedToolButton = button;
883            if (fSelectedToolButton != null) {
884                fSelectedToolButton.select();
885            }
886        }
887    
888        protected VersionControlStrategy getVersionControlStrategy() {
889            return new StandardVersionControlStrategy(this);
890        }
891    
892        /**
893         * Subclasses should override this method to specify to which versions of
894         * JHotDraw they are compatible. A string array is returned so it is possible
895         * to specify several version numbers of JHotDraw to which the application
896         * is compatible with.
897         *
898         * @return all versions number of JHotDraw the application is compatible with.
899         */
900        public String[] getRequiredVersions() {
901            String[] requiredVersions = new String[1];
902            // return the version of the package we are in
903            requiredVersions[0] = 
904                VersionManagement.getPackageVersion(DiagramView.class.getPackage());
905            return requiredVersions;
906        }
907    
908        /**
909         * Initialize from the org.objectweb.jac.ide.Diagram
910         */
911        public void load() {
912            toolDone();
913    
914            if (diagram == null) {
915                Log.error("no diagram");
916                return;
917            }
918    
919            init=true;
920    
921            try {
922                Log.trace("diagram","initializing drawing");
923                fDrawing.release();
924                fDrawing = new StandardDrawing();
925                Vector links = new Vector();
926                Vector ilinks = new Vector();
927                Iterator i = getDiagram().getFigures().iterator();
928                while (i.hasNext()) {
929                    Object figure = i.next();
930                    try {
931                        if (figure instanceof org.objectweb.jac.ide.ClassFigure) {
932                            if (((org.objectweb.jac.ide.ClassFigure)figure).getCl() 
933                                instanceof org.objectweb.jac.ide.Aspect) {
934                                fDrawing.add(
935                                    new AspectFigure((org.objectweb.jac.ide.ClassFigure)figure,
936                                                     getDiagram().getContainer(),
937                                                     view()));
938                            } else {
939                                fDrawing.add(
940                                    new ClassFigure((org.objectweb.jac.ide.ClassFigure)figure,
941                                                    getDiagram().getContainer(),
942                                                    view()));
943                            }
944                        } else if (figure instanceof org.objectweb.jac.ide.LinkFigure) {
945                            Figure linkFigure = null;
946                            Link link = ((org.objectweb.jac.ide.LinkFigure)figure).getLink();
947                            if (link instanceof org.objectweb.jac.ide.RelationLink) {
948                                linkFigure = 
949                                    new RelationLinkFigure((org.objectweb.jac.ide.LinkFigure)figure);
950                            } else if (link instanceof org.objectweb.jac.ide.PointcutLink) {
951                                linkFigure = 
952                                    new PointcutLinkFigure((org.objectweb.jac.ide.LinkFigure)figure);
953                            } else if (link instanceof org.objectweb.jac.ide.InheritanceLink) {
954                                linkFigure = 
955                                    new InheritanceLinkFigure((org.objectweb.jac.ide.LinkFigure)figure);
956                            }
957                            links.add(linkFigure);
958                        }
959                    } catch(Exception e) {
960                        Log.error("cannot load figure "+figure);
961                        e.printStackTrace();
962                    }
963                }
964    
965                // connect links
966                i = links.iterator();
967                while (i.hasNext()) {
968                    LinkFigure linkFigure = (LinkFigure)i.next();
969                    Log.trace("diagram","importing link "+linkFigure);
970                    Link link = (Link)linkFigure.getSubstance();
971                    ClassFigure start = findClass(fDrawing,(Class)link.getStart());
972                    Log.trace("diagram","link start "+link.getStart()+" -> "+start);
973                    if (start!=null) {
974                        linkFigure.connectStart(new ChopBoxConnector(start));
975                        linkFigure.startPoint(start.getCorner().x,start.getCorner().y);
976                    }
977                    ClassFigure end = findClass(fDrawing,(Class)link.getEnd());
978                    Log.trace("diagram","link end "+link.getEnd()+" -> "+end);
979                    if (end!=null) {
980                        linkFigure.connectEnd(new ChopBoxConnector(end));
981                        linkFigure.endPoint(end.getCorner().x,end.getCorner().y);
982                    }
983                    if (start!=null && end!=null)
984                        linkFigure.updateConnection();
985                    if (start!=null && end!=null) {
986                        fDrawing.add(linkFigure);
987                        linkFigure.load(fDrawing);
988                    } else {
989                        Log.warning("diagram",
990                                    "Bad link: start = "+link.getStart()+" -> "+start+
991                                    "; end = "+link.getEnd()+" -> "+end);
992                    }
993                }
994    
995                // connect ilinks
996                /*i = ilinks.iterator();
997                  while (i.hasNext()) {
998                  InheritanceLinkFigure linkFigure
999                  = (InheritanceLinkFigure)i.next();
1000                  Log.trace("diagram","importing link "+linkFigure);
1001                  Link link = (Link)linkFigure.getLinkFigure().getLink();
1002                  ClassFigure start = findClass(fDrawing,(Class)link.getStart());
1003                  Log.trace("diagram","link start "+link.getStart()+" -> "+start);
1004                  if (start!=null) {
1005                  linkFigure.connectStart(new ChopBoxConnector(start));
1006                  linkFigure.startPoint(start.getCorner().x,start.getCorner().y);
1007                  }
1008                  ClassFigure end = findClass(fDrawing,(Class)link.getEnd());
1009                  Log.trace("diagram","link start "+link.getEnd()+" -> "+end);
1010                  if (end!=null) {
1011                  linkFigure.connectEnd(new ChopBoxConnector(end));
1012                  linkFigure.endPoint(end.getCorner().x,end.getCorner().y);
1013                  }
1014                  linkFigure.updateConnection();
1015                  fDrawing.add(linkFigure);
1016                  linkFigure.load(fDrawing);
1017                  }*/
1018    
1019                Log.trace("diagram","sets the drawing"); 
1020                view().setDrawing(fDrawing);
1021                toolDone();
1022            } catch (Exception e) {
1023                initDrawing();
1024                e.printStackTrace();
1025                showStatus("Error:" + e);
1026            } finally {
1027                init=false;
1028            }
1029        }
1030    
1031        public void showStatus(String msg) {
1032            if (getContext()!=null) {
1033                getContext().getCustomizedView().showStatus(msg);
1034            }
1035            if (!Strings.isEmpty(msg))
1036                Log.trace("diagram","Status: "+msg);
1037        }
1038    
1039        public String toString() {
1040            return Strings.hex(this);
1041        }
1042    
1043        // CollectionUpdate interface
1044    
1045        public void onChange(Object substance, 
1046                             CollectionItem collection, Object value,
1047                             Object param) {
1048        }
1049    
1050        public void onAdd(Object substance, 
1051                          CollectionItem collection, Object value,
1052                          Object added, Object param) {
1053        }
1054    
1055        public void onRemove(Object substance, CollectionItem collection, Object value,
1056                             Object removed, Object param) {
1057            Log.trace("diagram.remove","onRemove "+removed);
1058            org.objectweb.jac.ide.Figure removedFigure = (org.objectweb.jac.ide.Figure)removed;
1059            ModelElementFigure figure = findFigure(fDrawing,removedFigure.getElement());
1060            Log.trace("diagram.remove","figure = "+figure);
1061            if (figure!=null) {
1062                Figure fig = fDrawing.remove((Figure)figure);
1063                view().removeFromSelection(figure);
1064                Log.trace("diagram.remove","removed "+fig);
1065                view().repairDamage();
1066            }
1067        }
1068    
1069    }