001    /*
002      Copyright (C) 2002 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      USA. */
018    
019    package org.objectweb.jac.ide.diagrams;
020    
021    import CH.ifa.draw.figures.LineConnection;
022    import CH.ifa.draw.figures.PolyLineFigure;
023    import CH.ifa.draw.figures.PolyLineHandle;
024    import CH.ifa.draw.framework.Drawing;
025    import CH.ifa.draw.framework.DrawingView;
026    import CH.ifa.draw.framework.Figure;
027    import CH.ifa.draw.framework.Locator;
028    import CH.ifa.draw.standard.NullHandle;
029    import org.objectweb.jac.aspects.gui.ObjectUpdate;
030    import org.objectweb.jac.core.rtti.FieldItem;
031    import org.objectweb.jac.ide.Link;
032    import org.objectweb.jac.ide.RelationLink;
033    import org.objectweb.jac.ide.RelationRole;
034    import org.objectweb.jac.ide.Role;
035    import org.objectweb.jac.util.Log;
036    import java.awt.Point;
037    import java.util.Iterator;
038    import java.util.List;
039    import java.util.Vector;
040    import org.objectweb.jac.aspects.gui.Utils;
041    
042    public class LinkFigure extends LineConnection 
043        implements ObjectUpdate, ModelElementFigure
044    {
045    
046        public final static int NAME = AttachedTextFigure.NAME;
047        public final static int START_CARDINALITY = AttachedTextFigure.START_CARDINALITY;
048        public final static int END_CARDINALITY = AttachedTextFigure.END_CARDINALITY;
049        public final static int START_ROLE = AttachedTextFigure.START_ROLE;
050        public final static int END_ROLE = AttachedTextFigure.END_ROLE;
051    
052        List attachedFigures = new Vector();
053    
054        org.objectweb.jac.ide.LinkFigure linkFig;
055    
056        org.objectweb.jac.ide.LinkFigure getLinkFigure() {
057            return linkFig;
058        }
059    
060        public LinkFigure(org.objectweb.jac.ide.LinkFigure figure) {
061            setLinkFigure(figure);
062            setDecorations();
063            layout();
064        }
065    
066        public LinkFigure() {
067            setDecorations();
068        }
069    
070        /**
071         * Set the decorations at both end of the link
072         */
073        void setDecorations() {
074            setStartDecoration(null);
075            setEndDecoration(null);
076        }
077    
078        protected void layout() {
079          
080        } 
081    
082        public void addAttachedTextFigure(AttachedTextFigure f) {
083            attachedFigures.add(f);
084        }
085    
086        public AttachedTextFigure createAttachedFigure(int type) {
087            AttachedTextFigure at = new AttachedTextFigure(linkFig,type);
088            at.connect(this);
089            at.refresh();
090            return at;    
091        }
092    
093        public AttachedTextFigure createAttachedFigure(int type,String s) {
094            AttachedTextFigure at = new AttachedTextFigure(linkFig,type);
095            at.setText(s);
096            at.connect(this);
097            return at;    
098        }
099    
100        public AttachedTextFigure createName() {
101            return createAttachedFigure(NAME);
102        }
103    
104        public AttachedTextFigure createEndRole() {
105            return createAttachedFigure(END_ROLE);
106        }
107    
108        public AttachedTextFigure createStartRole() {
109            return createAttachedFigure(START_ROLE);
110        }
111    
112        public AttachedTextFigure createStartCardinality() {
113            return createAttachedFigure(START_CARDINALITY);
114        }
115    
116        public AttachedTextFigure createEndCardinality() {
117            return createAttachedFigure(END_CARDINALITY);
118        }
119    
120    
121        public AttachedTextFigure createName(String s) {
122            return createAttachedFigure(NAME,s);
123        }
124    
125        public AttachedTextFigure createEndRole(String s) {
126            return createAttachedFigure(END_ROLE,s);
127        }
128    
129        public AttachedTextFigure createStartRole(String s) {
130            return createAttachedFigure(START_ROLE,s);
131        }
132    
133        public AttachedTextFigure createStartCardinality(String s) {
134            return createAttachedFigure(START_CARDINALITY,s);
135        }
136    
137        public AttachedTextFigure createEndCardinality(String s) {
138            return createAttachedFigure(END_CARDINALITY,s);
139        }
140    
141        Link substance;
142    
143        // View interface
144        public void setFocus(FieldItem field, Object extraOption) {}
145    
146        public void objectUpdated(Object object, Object extra) {
147            if (DiagramView.init) 
148                return;
149            Log.trace("figures.link","objectUpdated("+object+")");
150            DiagramView.init = true;
151            Link link = null;
152            if (object instanceof Link) {
153                link = (Link)object;
154            } else if (object instanceof Role) {
155                link = linkFig.getLink();
156            } else {
157                link = ((org.objectweb.jac.ide.LinkFigure)object).getLink();
158            }
159          
160            try {
161                if (link instanceof RelationLink) {
162                    RelationLink roledLink = (RelationLink)link;
163                    Iterator it = attachedFigures.iterator();
164                    while (it.hasNext()) {
165                        AttachedTextFigure cur = (AttachedTextFigure)it.next();
166                        cur.refresh();
167                    }
168                }
169             
170                setDecorations();
171                changed();
172                /*
173                  if (substance.getEnd() != ((ModelElementFigure)endFigure()).getSubstance()) {
174                  Figure newEnd = ((DiagramView)DiagramView.diagramViews.get(0))
175                  .findElement((ModelElement)substance.getEnd());
176                  if( newEnd != null ) {
177                  Log.trace("figures","reconnecting relation to "+newEnd);
178                  disconnectEnd();
179                  endPoint(newEnd.center().x,newEnd.center().y);
180                  connectEnd(newEnd.connectorAt(
181                  newEnd.center().x,newEnd.center().y));
182                  updateConnection();
183                  } else {
184                  ((DiagramView)DiagramView.diagramViews.get(0)).view().drawing().remove(this);            
185                  }
186                  }
187                  if(DiagramView.diagramViews.size()>0) {
188                  ((DiagramView)DiagramView.diagramViews.get(0)).view()
189                  .paint(((DiagramView)DiagramView.diagramViews.get(0))
190                  .view().getGraphics());
191                  }
192                */
193            } finally {
194                DiagramView.init = false;
195            }
196        }
197    
198        public void insertPointAt(Point p, int i) {
199            super.insertPointAt(p, i);
200            if(!DiagramView.init)
201                linkFig.addPoint(i,p);
202        }
203    
204        public void removePointAt(int i) {
205            super.removePointAt(i);
206            if(!DiagramView.init)
207                linkFig.removePoint(i);
208        }
209    
210        public void close() {
211            Link link = linkFig.getLink();
212            Utils.unregisterObject(link,this);
213            if (link instanceof RelationLink) {
214                RelationLink rel = (RelationLink)link;
215                Utils.unregisterObject(rel.getStartRole(),this);
216                Utils.unregisterObject(rel.getEndRole(),this);
217            }        
218        }
219       
220        /**
221         * Get the value of substance.
222         * @return value of substance.
223         */
224        public org.objectweb.jac.ide.ModelElement getSubstance() {
225            return linkFig.getLink();
226        }
227    
228        public void setLinkFigure(org.objectweb.jac.ide.LinkFigure linkFig) {
229            Link link;
230            if (this.linkFig!=null) {
231                link = this.linkFig.getLink();
232                Utils.unregisterObject(link,this);
233                if (link instanceof RelationLink) {
234                    RelationLink rel = (RelationLink)link;
235                    Utils.unregisterObject(rel.getStartRole(),this);
236                    Utils.unregisterObject(rel.getEndRole(),this);
237                }
238            }
239            this.linkFig = linkFig;
240            link = linkFig.getLink();
241            Utils.registerObject(link,this);
242            if (link instanceof RelationLink) {
243                RelationLink rel = (RelationLink)link;
244                Utils.registerObject(rel.getStartRole(),this);
245                Utils.registerObject(rel.getEndRole(),this);
246            }
247            setDecorations();
248        }
249    
250        public void handleConnect(Figure start, ModelElementFigure end) {
251            if( substance == null ) return;
252            if( end.getSubstance() != substance.getEnd() ) {
253                DiagramView.init = true;
254                substance.setEnd(end.getSubstance());
255                DiagramView.init = false;
256            }
257        }
258    
259        public void handleDisconnect(Figure start, Figure end) {
260        } 
261    
262        public Vector handles() {
263          
264            Vector handles = new Vector(fPoints.size());
265            for (int i = 0; i < fPoints.size(); i++) {
266                handles.addElement(new LinkHandle(this, locator(i), i));
267            }
268            // don't allow to reconnect the starting figure
269            handles.setElementAt(new NullHandle(this, PolyLineFigure.locator(0)), 0);
270            return handles;
271        }
272    
273        AttachedTextLocator locator=new AttachedTextLocator();
274    
275        public Locator connectedTextLocator(Figure f) {
276            return locator;
277        }
278    
279        protected void basicMoveBy(int dx, int dy) {
280            Log.trace("figures.link","link figure moved "+dx+","+dy);
281            for(int i=1;i<linkFig.getPointCount()-1;i++) {
282                linkFig.setPoint(i,pointAt(i));
283            }     
284            super.basicMoveBy(dx,dy);
285            Log.trace("figures.link","Moved done");
286        }
287    
288        /**
289         * Changes the coordinates of a point of the line connection
290         * @param p the new point
291         * @param i  index of the point to modify
292         */
293        public void setPointAt(Point p, int i) {
294            super.setPointAt(p,i);
295            linkFig.setPoint(i,p);
296        }
297    
298    
299        /**
300         * Updates the connection.
301         */
302        public void updateConnection() {
303            if (getStartConnector() != null && getEndConnector() != null) {
304                Point start = getStartConnector().findStart(this);
305    
306                if (start != null) {
307                    startPoint(start.x, start.y);
308                }
309    
310                Point end = getEndConnector().findEnd(this);
311              
312                if (end != null) {
313                    endPoint(end.x, end.y);
314                }
315            }
316        }
317    
318        /**
319         * Initialize associated text figures (cardinality, role name, ...)
320         * @param drawing a drawing to add the figures to
321         */
322        public void load(Drawing drawing) {
323            Log.trace("diagram",2,"load link "+this);
324            DiagramView.init = true;
325            try {
326                Iterator points = linkFig.getPoints().iterator();
327                int i = 1;
328                if (points.hasNext()) {
329                    points.next();
330                    while (points.hasNext()) {
331                        Point p = (Point)points.next();
332                        if (points.hasNext())
333                            insertPointAt(p,i++);
334                    }
335                }
336                Link subst = (Link)getSubstance();
337                Point p;
338                if (subst instanceof RelationLink) {
339                    RelationLink lnk = (RelationLink)subst;
340                    RelationRole start = lnk.startRole();
341                    RelationRole end = lnk.endRole();
342                    AttachedTextFigure text = createName();
343                    drawing.add(text);
344                    p = connectedTextLocator(text).locate(this,text);
345                    text.moveBy((int)(linkFig.getNameCorner().getX()
346                                      - p.getX()+text.size().getWidth()/2),
347                                (int)(linkFig.getNameCorner().getY()
348                                      - p.getY()+text.size().getHeight()/2));
349                
350                    text = createStartRole();
351                    drawing.add(text);
352                    p = connectedTextLocator(text).locate(this,text);
353                    text.moveBy((int)(linkFig.getStartRoleCorner().getX()
354                                      - p.getX()+text.size().getWidth()/2),
355                                (int)(linkFig.getStartRoleCorner().getY()
356                                      - p.getY()+text.size().getHeight()/2));
357                
358                    text = createEndRole();
359                    drawing.add(text);
360                    p = connectedTextLocator(text).locate(this,text);
361                    text.moveBy((int)(linkFig.getEndRoleCorner().getX()
362                                      - p.getX()+text.size().getWidth()/2),
363                                (int)(linkFig.getEndRoleCorner().getY()
364                                      - p.getY()+text.size().getHeight()/2));
365                
366                    text = createStartCardinality();
367                    drawing.add(text);
368                    p = connectedTextLocator(text).locate(this,text);
369                    text.moveBy((int)(linkFig.getStartCardinalityCorner().getX()
370                                      - p.getX()+text.size().getWidth()/2),
371                                (int)(linkFig.getStartCardinalityCorner().getY()
372                                      - p.getY()+text.size().getHeight()/2));
373                
374                    text = createEndCardinality();
375                    drawing.add(text);
376                    p = connectedTextLocator(text).locate(this,text);
377                    text.moveBy((int)(linkFig.getEndCardinalityCorner().getX()
378                                      - p.getX()+text.size().getWidth()/2),
379                                (int)(linkFig.getEndCardinalityCorner().getY()
380                                      - p.getY()+text.size().getHeight()/2));
381                }
382            } finally {
383                DiagramView.init=false;
384            }
385        }
386    
387        public void release() {
388            super.release();
389            close();
390            if(linkFig!=null && linkFig.getDiagram()!=null) {
391                linkFig.getDiagram().removeFigure(linkFig);
392            }
393        }
394    
395        // Helper methods
396        public void endPoint(Point p) {
397            endPoint(p.x,p.y);
398        }
399        public void startPoint(Point p) {
400            startPoint(p.x,p.y);
401        }
402    }
403    
404    class LinkHandle extends PolyLineHandle {
405        public LinkHandle(PolyLineFigure owner, Locator l, int index) {
406            super(owner, l,index);
407        }
408    
409        public void invokeStep(int x, int y, int anchorX, 
410                               int anchorY, DrawingView view) {
411            super.invokeStep(x,y,anchorX,anchorY,view);
412        }
413       
414    }