Coverage Report - org.argouml.uml.diagram.activity.ui.FigPartition
 
Classes in this File Line Coverage Branch Coverage Complexity
FigPartition
0%
0/146
0%
0/38
3.2
FigPartition$SelectionPartition
0%
0/132
0%
0/74
3.2
 
 1  
 /* $Id: FigPartition.java 18726 2010-09-10 08:37:15Z mvw $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009-2010 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    bobtarling
 11  
  *    Michiel van der Wulp
 12  
  *****************************************************************************
 13  
  *
 14  
  * Some portions of this file was previously release using the BSD License:
 15  
  */
 16  
 
 17  
 // Copyright (c) 2003-2009 The Regents of the University of California. All
 18  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 19  
 // software and its documentation without fee, and without a written
 20  
 // agreement is hereby granted, provided that the above copyright notice
 21  
 // and this paragraph appear in all copies. This software program and
 22  
 // documentation are copyrighted by The Regents of the University of
 23  
 // California. The software program and documentation are supplied "AS
 24  
 // IS", without any accompanying services from The Regents. The Regents
 25  
 // does not warrant that the operation of the program will be
 26  
 // uninterrupted or error-free. The end-user understands that the program
 27  
 // was developed for research purposes and is advised not to rely
 28  
 // exclusively on the program for any reason. IN NO EVENT SHALL THE
 29  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 30  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 31  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 32  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 33  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 34  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 35  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 36  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 37  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 38  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 39  
 
 40  
 package org.argouml.uml.diagram.activity.ui;
 41  
 
 42  
 import java.awt.Color;
 43  
 import java.awt.Dimension;
 44  
 import java.awt.Graphics;
 45  
 import java.awt.Rectangle;
 46  
 import java.util.ArrayList;
 47  
 import java.util.Iterator;
 48  
 import java.util.List;
 49  
 
 50  
 import org.argouml.model.Model;
 51  
 import org.argouml.uml.diagram.DiagramSettings;
 52  
 import org.argouml.uml.diagram.ui.FigNodeModelElement;
 53  
 import org.tigris.gef.base.Globals;
 54  
 import org.tigris.gef.base.Layer;
 55  
 import org.tigris.gef.base.Selection;
 56  
 import org.tigris.gef.presentation.Fig;
 57  
 import org.tigris.gef.presentation.FigLine;
 58  
 import org.tigris.gef.presentation.FigRect;
 59  
 import org.tigris.gef.presentation.FigText;
 60  
 import org.tigris.gef.presentation.Handle;
 61  
 
 62  
 /**
 63  
  * This class represents a Partition or Swimlane for Activity diagrams.
 64  
  *
 65  
  * @author mkl
 66  
  */
 67  0
 public class FigPartition extends FigNodeModelElement {
 68  
 
 69  
     private static final int MIN_WIDTH = 64;
 70  
     private static final int MIN_HEIGHT = 256;
 71  
     
 72  
     private FigLine leftLine;
 73  
     private FigLine rightLine;
 74  
     private FigLine topLine;
 75  
     private FigLine bottomLine;
 76  
     private FigLine seperator;
 77  
     
 78  
     private FigPartition previousPartition;
 79  
     private FigPartition nextPartition;
 80  
     
 81  
     /**
 82  
      * Construct a new FigPartition.
 83  
      * 
 84  
      * @param owner owning UML element
 85  
      * @param bounds position and size
 86  
      * @param settings rendering settings
 87  
      */
 88  
     public FigPartition(Object owner, Rectangle bounds, 
 89  
             DiagramSettings settings) {
 90  0
         super(owner, bounds, settings);
 91  0
         initFigs();
 92  0
     }
 93  
 
 94  
     @Override
 95  
     protected Fig createBigPortFig() {
 96  
         // TODO: define constants for magic numbers
 97  0
         FigRect fr = new FigRect(X0, Y0, 160, 200, DEBUG_COLOR, DEBUG_COLOR);
 98  0
         fr.setFilled(false);
 99  0
         fr.setLineWidth(0);
 100  0
         return fr;
 101  
     }
 102  
 
 103  
     private void initFigs() {
 104  
         // TODO: define constants for magic numbers
 105  0
         leftLine = new FigLine(X0, Y0, 10, 300, LINE_COLOR);
 106  0
         rightLine = new FigLine(150, Y0, 160, 300, LINE_COLOR);
 107  0
         bottomLine = new FigLine(X0, 300, 150, 300, LINE_COLOR);
 108  0
         topLine = new FigLine(X0, Y0, 150, 10, LINE_COLOR);
 109  
 
 110  0
         getNameFig().setLineWidth(0);
 111  0
         getNameFig().setBounds(X0, Y0, 50, 25);
 112  0
         getNameFig().setFilled(false);
 113  
         
 114  0
         seperator = new FigLine(X0, Y0 + 15, 150, 25, LINE_COLOR);
 115  
 
 116  0
         addFig(getBigPort());
 117  0
         addFig(rightLine);
 118  0
         addFig(leftLine);
 119  0
         addFig(topLine);
 120  0
         addFig(bottomLine);
 121  0
         addFig(getNameFig());
 122  0
         addFig(seperator);
 123  
         
 124  0
         setFilled(false);
 125  0
         setBounds(getBounds());
 126  0
     }
 127  
     
 128  
     /*
 129  
      * @see java.lang.Object#clone()
 130  
      */
 131  
     @Override
 132  
     public Object clone() {
 133  0
         FigPartition figClone = (FigPartition) super.clone();
 134  0
         Iterator it = figClone.getFigs().iterator();
 135  0
         figClone.setBigPort((FigRect) it.next());
 136  0
         figClone.rightLine = (FigLine) it.next();
 137  0
         figClone.leftLine = (FigLine) it.next();
 138  0
         figClone.bottomLine = (FigLine) it.next();
 139  0
         figClone.topLine = (FigLine) it.next();
 140  0
         figClone.setNameFig((FigText) it.next());
 141  
 //        figClone.seperator = (FigLine) it.next();
 142  0
         return figClone;
 143  
     }
 144  
 
 145  
     /*
 146  
      * @see org.tigris.gef.presentation.Fig#setLineColor(java.awt.Color)
 147  
      */
 148  
     @Override
 149  
     public void setLineColor(Color col) {
 150  0
         rightLine.setLineColor(col);
 151  0
         leftLine.setLineColor(col);
 152  0
         bottomLine.setLineColor(col);
 153  0
         topLine.setLineColor(col);
 154  0
         seperator.setLineColor(col);
 155  0
     }
 156  
 
 157  
     /*
 158  
      * @see org.tigris.gef.presentation.Fig#getLineColor()
 159  
      */
 160  
     @Override
 161  
     public Color getLineColor() {
 162  0
         return rightLine.getLineColor();
 163  
     }
 164  
 
 165  
     /*
 166  
      * @see org.tigris.gef.presentation.Fig#setFillColor(java.awt.Color)
 167  
      */
 168  
     @Override
 169  
     public void setFillColor(Color col) {
 170  0
         getBigPort().setFillColor(col);
 171  0
         getNameFig().setFillColor(col);
 172  0
     }
 173  
 
 174  
     /*
 175  
      * @see org.tigris.gef.presentation.Fig#getFillColor()
 176  
      */
 177  
     @Override
 178  
     public Color getFillColor() {
 179  0
         return getBigPort().getFillColor();
 180  
     }
 181  
 
 182  
     /*
 183  
      * @see org.tigris.gef.presentation.Fig#setFilled(boolean)
 184  
      */
 185  
     @Override
 186  
     public void setFilled(boolean f) {
 187  0
         getBigPort().setFilled(f);
 188  0
         getNameFig().setFilled(f);
 189  0
         super.setFilled(f);
 190  0
     }
 191  
     
 192  
     @Override
 193  
     public boolean isFilled() {
 194  0
         return getBigPort().isFilled();
 195  
     }
 196  
     
 197  
     /*
 198  
      * @see org.tigris.gef.presentation.Fig#setLineWidth(int)
 199  
      */
 200  
     @Override
 201  
     public void setLineWidth(int w) {
 202  0
         rightLine.setLineWidth(w);
 203  0
         leftLine.setLineWidth(w);
 204  0
     }
 205  
 
 206  
     /*
 207  
      * @see org.tigris.gef.presentation.Fig#getLineWidth()
 208  
      */
 209  
     @Override
 210  
     public int getLineWidth() {
 211  0
         return rightLine.getLineWidth();
 212  
     }
 213  
 
 214  
     /*
 215  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#placeString()
 216  
      */
 217  
     @Override
 218  
     public String placeString() {
 219  0
         return "";
 220  
     }
 221  
 
 222  
     /*
 223  
      * @see org.tigris.gef.presentation.Fig#getMinimumSize()
 224  
      */
 225  
     @Override
 226  
     public Dimension getMinimumSize() {
 227  0
         Dimension nameDim = getNameFig().getMinimumSize();
 228  0
         int w = nameDim.width;
 229  0
         int h = nameDim.height;
 230  
 
 231  
         // we want to maintain a minimum size for the partition
 232  0
         w = Math.max(MIN_WIDTH, w);
 233  0
         h = Math.max(MIN_HEIGHT, h);
 234  
 
 235  0
         return new Dimension(w, h);
 236  
     }
 237  
 
 238  
     /*
 239  
      * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
 240  
      */
 241  
     @Override
 242  
     protected void setStandardBounds(int x, int y, int w, int h) {
 243  
         
 244  0
         if (getNameFig() == null) {
 245  0
             return;
 246  
         }
 247  0
         Rectangle oldBounds = getBounds();
 248  
 
 249  0
         Rectangle nameBounds = getNameFig().getBounds();
 250  0
         getNameFig().setBounds(x, y, w, nameBounds.height);
 251  
 
 252  0
         getBigPort().setBounds(x, y, w, h);
 253  0
         leftLine.setBounds(x, y, 0, h);
 254  0
         rightLine.setBounds(x + (w - 1) , y, 0, h);
 255  0
         topLine.setBounds(x, y, w - 1, 0);
 256  0
         bottomLine.setBounds(x, y + h, w - 1, 0);
 257  0
         seperator.setBounds(x, y + nameBounds.height, w - 1, 0);
 258  
 
 259  0
         firePropChange("bounds", oldBounds, getBounds());
 260  0
         calcBounds(); //_x = x; _y = y; _w = w; _h = h;
 261  0
         updateEdges();
 262  0
     }
 263  
     
 264  
     @Override
 265  
     public Selection makeSelection() {
 266  0
         return new SelectionPartition(this);
 267  
     }
 268  
     
 269  
     /**
 270  
      * On post placement look to see if there are any other
 271  
      * FigPartitions. If so place to the right and resize height.
 272  
      *
 273  
      * @param activityGraph the UML ActivityGraph element 
 274  
      * that contains the Partition 
 275  
      */
 276  
     public void appendToPool(Object activityGraph) {
 277  0
         List partitions = getPartitions(getLayer());
 278  0
         Model.getCoreHelper().setModelElementContainer(
 279  
                 getOwner(), activityGraph);
 280  
         
 281  0
         if (partitions.size() == 1) {
 282  0
             FigPool fp = new FigPool(getBounds(), getSettings());
 283  0
             getLayer().add(fp);
 284  0
             getLayer().bringToFront(this);
 285  0
         } else if (partitions.size() > 1) {
 286  0
             FigPool fp = getFigPool();
 287  0
             fp.setWidth(fp.getWidth() + getWidth());
 288  
             
 289  0
             int x = 0;
 290  0
             Iterator it = partitions.iterator();
 291  0
             FigPartition f = null;
 292  0
             FigPartition previousFig = null;
 293  0
             while (it.hasNext()) {
 294  0
                 f = (FigPartition) it.next();
 295  0
                 if (f != this && f.getX() + f.getWidth() > x) {
 296  0
                     previousFig = f;
 297  0
                     x = f.getX();
 298  
                 }
 299  
             }
 300  0
             setPreviousPartition(previousFig);
 301  0
             previousPartition.setNextPartition(this);
 302  0
             setBounds(
 303  
                     x + previousFig.getWidth(),
 304  
                     previousFig.getY(),
 305  
                     getWidth(),
 306  
                     previousFig.getHeight());
 307  
         }
 308  0
     }
 309  
     
 310  
     @Override
 311  
     public void removeFromDiagramImpl() {
 312  0
         int width = getWidth();
 313  0
         FigPool figPool = getFigPool();
 314  0
         if (figPool == null) { //Needed for project deletion
 315  0
             super.removeFromDiagramImpl();
 316  0
             return;
 317  
         }
 318  
         
 319  0
         int newFigPoolWidth = figPool.getWidth() - width;
 320  
         
 321  0
         super.removeFromDiagramImpl();
 322  
         
 323  0
         FigPartition next = nextPartition;
 324  0
         while (next != null) {
 325  0
             next.translateWithContents(-width);
 326  0
             next = next.nextPartition;
 327  
         }
 328  
 
 329  0
         if (nextPartition == null && previousPartition == null) {
 330  
             /* We removed the last partition, so now remove the pool, too: */
 331  0
             figPool.removeFromDiagram();
 332  0
             return;
 333  
         }
 334  
 
 335  0
         if (nextPartition != null) {
 336  0
             nextPartition.setPreviousPartition(previousPartition);
 337  
         }
 338  
         
 339  0
         if (previousPartition != null) {
 340  0
             previousPartition.setNextPartition(nextPartition);
 341  
         }
 342  
         
 343  0
         setPreviousPartition(null);
 344  0
         setNextPartition(null);
 345  
         
 346  0
         figPool.setWidth(newFigPoolWidth);
 347  0
     }
 348  
     
 349  
     // TODO: Needs work. Must determine which Figs enclosed
 350  
     // in the pool are within the bounds of this Fig
 351  
     // and translate those.
 352  
     private void translateWithContents(int dx) {
 353  0
         for (Fig f : getFigPool().getEnclosedFigs()) {
 354  0
             f.setX(f.getX() + dx);
 355  
         }
 356  0
         setX(getX() + dx);
 357  0
         damage();
 358  0
     }
 359  
     
 360  
     /**
 361  
      * Get all the partitions on the same layer as this FigPartition
 362  
      * @return th partitions
 363  
      */
 364  
     private List<FigPartition> getPartitions(Layer layer) {
 365  0
         final List<FigPartition> partitions = new ArrayList<FigPartition>();
 366  
         
 367  0
         for (Object o : layer.getContents()) {
 368  0
             if (o instanceof FigPartition) {
 369  0
                 partitions.add((FigPartition) o);
 370  
             }
 371  
         }
 372  
         
 373  0
         return partitions;
 374  
     }
 375  
     
 376  
     /**
 377  
      * Get all the partitions on the same layer as this FigPartition
 378  
      * @return th partitions
 379  
      */
 380  
     private FigPool getFigPool() {
 381  0
         if (getLayer() != null) { // This test needed for project deletion
 382  0
             for (Object o : getLayer().getContents()) {
 383  0
                 if (o instanceof FigPool) {
 384  0
                     return (FigPool) o;
 385  
                 }
 386  
             }
 387  
         }
 388  
         
 389  0
         return null;
 390  
     }
 391  
     
 392  
 
 393  
     /**
 394  
      * @param nextPartition The nextPartition to set.
 395  
      */
 396  
     void setNextPartition(FigPartition next) {
 397  0
         this.nextPartition = next;
 398  0
     }
 399  
 
 400  
     /**
 401  
      * @param previousPartition The previousPartition to set.
 402  
      */
 403  
     void setPreviousPartition(FigPartition previous) {
 404  0
         this.previousPartition = previous;
 405  0
         leftLine.setVisible(previousPartition == null);
 406  0
     }
 407  
     
 408  
     /**
 409  
      * When dragging this partition drag all other partitions with it.
 410  
      * @return all the partitions to drag together.
 411  
      */
 412  
     @Override
 413  
     public List getDragDependencies() {
 414  0
         List dependents = getPartitions(getLayer());
 415  0
         dependents.add(getFigPool());
 416  0
         dependents.addAll(getFigPool().getEnclosedFigs());
 417  0
         return dependents;
 418  
     }
 419  
     
 420  
     /**
 421  
      * A specialist Selection class for FigPartitions.
 422  
      * This ensures that all swimlanes are the same length (ie height).
 423  
      * TODO: Make sure that all swimlanes appear side by side (UML spec
 424  
      * states "separated from neighboring swimlanes by vertical solid
 425  
      * lines on both sides".
 426  
      * TODO: Allow drag of the west and east edge to resize both the selected
 427  
      * Fig and the fig connected to that side.
 428  
      * TODO: Show NorthWest and SouthWest handle only on leftmost swimlane.
 429  
      * TODO: Show NorthEast and SouthEast handle only on rightmost swimlane.
 430  
      * @author Bob
 431  
      */
 432  
     private class SelectionPartition extends Selection {
 433  
 
 434  
         private int cx;
 435  
         private int cy;
 436  
         private int cw;
 437  
         private int ch;
 438  
         
 439  
         /**
 440  
          * Construct a new SelectionPartition for the given partition
 441  
          *
 442  
          * @param f the Fig
 443  
          */
 444  0
         public SelectionPartition(FigPartition f) {
 445  0
             super(f);
 446  0
         }
 447  
         
 448  
         /** Return a handle ID for the handle under the mouse, or -1 if
 449  
          *  none. Needs-More-Work: in the future, return a Handle instance or
 450  
          *  null. <p>
 451  
          *  <pre>
 452  
          *   0-------1-------2
 453  
          *   |               |
 454  
          *   3               4
 455  
          *   |               |
 456  
          *   5-------6-------7
 457  
          * </pre>
 458  
          */
 459  
         public void hitHandle(Rectangle r, Handle h) {
 460  0
             if (getContent().isResizable()) {
 461  
         
 462  0
                 updateHandleBox();
 463  0
                 Rectangle testRect = new Rectangle(0, 0, 0, 0);
 464  0
                 testRect.setBounds(
 465  
                     cx - HAND_SIZE / 2,
 466  
                     cy - HAND_SIZE / 2,
 467  
                     HAND_SIZE,
 468  
                     ch + HAND_SIZE / 2);
 469  0
                 boolean leftEdge = r.intersects(testRect);
 470  0
                 testRect.setBounds(
 471  
                     cx + cw - HAND_SIZE / 2,
 472  
                     cy - HAND_SIZE / 2,
 473  
                     HAND_SIZE,
 474  
                     ch + HAND_SIZE / 2);
 475  0
                 boolean rightEdge = r.intersects(testRect);
 476  0
                 testRect.setBounds(
 477  
                     cx - HAND_SIZE / 2,
 478  
                     cy - HAND_SIZE / 2,
 479  
                     cw + HAND_SIZE / 2,
 480  
                     HAND_SIZE);
 481  0
                 boolean topEdge = r.intersects(testRect);
 482  0
                 testRect.setBounds(
 483  
                     cx - HAND_SIZE / 2,
 484  
                     cy + ch - HAND_SIZE / 2,
 485  
                     cw + HAND_SIZE / 2,
 486  
                     HAND_SIZE);
 487  0
                 boolean bottomEdge = r.intersects(testRect);
 488  
                 // TODO: midpoints for side handles
 489  0
                 if (leftEdge && topEdge) {
 490  0
                     h.index = Handle.NORTHWEST;
 491  0
                     h.instructions = "Resize top left";
 492  0
                 } else if (rightEdge && topEdge) {
 493  0
                     h.index = Handle.NORTHEAST;
 494  0
                     h.instructions = "Resize top right";
 495  0
                 } else if (leftEdge && bottomEdge) {
 496  0
                     h.index = Handle.SOUTHWEST;
 497  0
                     h.instructions = "Resize bottom left";
 498  0
                 } else if (rightEdge && bottomEdge) {
 499  0
                     h.index = Handle.SOUTHEAST;
 500  0
                     h.instructions = "Resize bottom right";
 501  
                 }
 502  
                 // TODO: side handles
 503  
                 else {
 504  0
                     h.index = -1;
 505  0
                     h.instructions = "Move object(s)";
 506  
                 }
 507  0
             } else {
 508  0
                 h.index = -1;
 509  0
                 h.instructions = "Move object(s)";
 510  
             }
 511  
         
 512  0
         }
 513  
         
 514  
         /** Update the private variables cx etc. that represent the rectangle on
 515  
                   whose corners handles are to be drawn.*/
 516  
         private void updateHandleBox() {
 517  0
             final Rectangle cRect = getContent().getHandleBox();
 518  0
             cx = cRect.x;
 519  0
             cy = cRect.y;
 520  0
             cw = cRect.width;
 521  0
             ch = cRect.height;
 522  0
         }
 523  
         
 524  
         /** Paint the handles at the four corners and midway along each edge
 525  
          * of the bounding box.  */
 526  
         @Override
 527  
         public void paint(Graphics g) {
 528  0
             final Fig fig = getContent();
 529  0
             if (getContent().isResizable()) {
 530  
         
 531  0
                 updateHandleBox();
 532  0
                 g.setColor(Globals.getPrefs().handleColorFor(fig));
 533  0
                 g.fillRect(
 534  
                     cx - HAND_SIZE / 2,
 535  
                     cy - HAND_SIZE / 2,
 536  
                     HAND_SIZE,
 537  
                     HAND_SIZE);
 538  0
                 g.fillRect(
 539  
                     cx + cw - HAND_SIZE / 2,
 540  
                     cy - HAND_SIZE / 2,
 541  
                     HAND_SIZE,
 542  
                     HAND_SIZE);
 543  0
                 g.fillRect(
 544  
                     cx - HAND_SIZE / 2,
 545  
                     cy + ch - HAND_SIZE / 2,
 546  
                     HAND_SIZE,
 547  
                     HAND_SIZE);
 548  0
                 g.fillRect(
 549  
                     cx + cw - HAND_SIZE / 2,
 550  
                     cy + ch - HAND_SIZE / 2,
 551  
                     HAND_SIZE,
 552  
                     HAND_SIZE);
 553  
             } else {
 554  0
                 final int x = fig.getX();
 555  0
                 final int y = fig.getY();
 556  0
                 final int w = fig.getWidth();
 557  0
                 final int h = fig.getHeight();
 558  0
                 g.setColor(Globals.getPrefs().handleColorFor(fig));
 559  0
                 g.drawRect(
 560  
                     x - BORDER_WIDTH,
 561  
                     y - BORDER_WIDTH,
 562  
                     w + BORDER_WIDTH * 2 - 1,
 563  
                     h + BORDER_WIDTH * 2 - 1);
 564  0
                 g.drawRect(
 565  
                     x - BORDER_WIDTH - 1,
 566  
                     y - BORDER_WIDTH - 1,
 567  
                     w + BORDER_WIDTH * 2 + 2 - 1,
 568  
                     h + BORDER_WIDTH * 2 + 2 - 1);
 569  0
                 g.fillRect(x - HAND_SIZE, y - HAND_SIZE, HAND_SIZE, HAND_SIZE);
 570  0
                 g.fillRect(x + w, y - HAND_SIZE, HAND_SIZE, HAND_SIZE);
 571  0
                 g.fillRect(x - HAND_SIZE, y + h, HAND_SIZE, HAND_SIZE);
 572  0
                 g.fillRect(x + w, y + h, HAND_SIZE, HAND_SIZE);
 573  
             }
 574  0
         }
 575  
         
 576  
         /**
 577  
          * Change some attribute of the selected Fig when the user drags one
 578  
          * of its handles.
 579  
          */
 580  
         public void dragHandle(int mX, int mY, int anX, int anY, Handle hand) {
 581  
             
 582  0
             final Fig fig = getContent();
 583  
 
 584  0
             updateHandleBox();
 585  
         
 586  0
             final int x = cx;
 587  0
             final int y = cy;
 588  0
             final int w = cw;
 589  0
             final int h = ch;
 590  0
             int newX = x, newY = y, newWidth = w, newHeight = h;
 591  0
             Dimension minSize = fig.getMinimumSize();
 592  0
             int minWidth = minSize.width, minHeight = minSize.height;
 593  0
             switch (hand.index) {
 594  
             case -1 :
 595  0
                 fig.translate(anX - mX, anY - mY);
 596  0
                 return;
 597  
             case Handle.NORTHWEST :
 598  0
                 newWidth = x + w - mX;
 599  0
                 newWidth = (newWidth < minWidth) ? minWidth : newWidth;
 600  0
                 newHeight = y + h - mY;
 601  0
                 newHeight = (newHeight < minHeight) ? minHeight : newHeight;
 602  0
                 newX = x + w - newWidth;
 603  0
                 newY = y + h - newHeight;
 604  0
                 if ((newX + newWidth) != (x + w)) {
 605  0
                     newX += (newX + newWidth) - (x + w);
 606  
                 }
 607  0
                 if ((newY + newHeight) != (y + h)) {
 608  0
                     newY += (newY + newHeight) - (y + h);
 609  
                 }
 610  0
                 setHandleBox(
 611  
                         previousPartition, 
 612  
                         newX, 
 613  
                         newY, 
 614  
                         newWidth, 
 615  
                         newHeight);
 616  0
                 return;
 617  
             case Handle.NORTH :
 618  0
                 break;
 619  
             case Handle.NORTHEAST :
 620  0
                 newWidth = mX - x;
 621  0
                 newWidth = (newWidth < minWidth) ? minWidth : newWidth;
 622  0
                 newHeight = y + h - mY;
 623  0
                 newHeight = (newHeight < minHeight) ? minHeight : newHeight;
 624  0
                 newY = y + h - newHeight;
 625  0
                 if ((newY + newHeight) != (y + h)) {
 626  0
                     newY += (newY + newHeight) - (y + h);
 627  
                 }
 628  0
                 setHandleBox(
 629  
                         nextPartition, 
 630  
                         newX, 
 631  
                         newY, 
 632  
                         newWidth, 
 633  
                         newHeight);
 634  0
                 break;
 635  
             case Handle.WEST :
 636  0
                 break;
 637  
             case Handle.EAST :
 638  0
                 break;
 639  
             case Handle.SOUTHWEST :
 640  0
                 newWidth = x + w - mX;
 641  0
                 newWidth = (newWidth < minWidth) ? minWidth : newWidth;
 642  0
                 newHeight = mY - y;
 643  0
                 newHeight = (newHeight < minHeight) ? minHeight : newHeight;
 644  0
                 newX = x + w - newWidth;
 645  0
                 if ((newX + newWidth) != (x + w)) {
 646  0
                     newX += (newX + newWidth) - (x + w);
 647  
                 }
 648  0
                 setHandleBox(
 649  
                         previousPartition, 
 650  
                         newX, 
 651  
                         newY, 
 652  
                         newWidth, 
 653  
                         newHeight);
 654  0
                 break;
 655  
             case Handle.SOUTH :
 656  0
                 break;
 657  
             case Handle.SOUTHEAST :
 658  0
                 newWidth = mX - x;
 659  0
                 newWidth = (newWidth < minWidth) ? minWidth : newWidth;
 660  0
                 newHeight = mY - y;
 661  0
                 newHeight = (newHeight < minHeight) ? minHeight : newHeight;
 662  0
                 setHandleBox(
 663  
                         nextPartition, 
 664  
                         newX, 
 665  
                         newY, 
 666  
                         newWidth, 
 667  
                         newHeight);
 668  
                 break;
 669  
             }
 670  0
         }
 671  
         
 672  
         private void setHandleBox(
 673  
                 FigPartition neighbour, 
 674  
                 int x, 
 675  
                 int y, 
 676  
                 int width, 
 677  
                 int height) {
 678  
             
 679  0
             final List<FigPartition> partitions = getPartitions(getLayer());
 680  
             
 681  0
             int newNeighbourWidth = 0;
 682  0
             if (neighbour != null) {
 683  0
                 newNeighbourWidth = 
 684  
                     (neighbour.getWidth() + getContent().getWidth()) - width;
 685  0
                 if (neighbour.getMinimumSize().width > newNeighbourWidth) {
 686  0
                     return;
 687  
                 }
 688  
             }
 689  
             
 690  0
             int lowX = 0;
 691  0
             int totalWidth = 0;
 692  0
             for (Fig f : partitions) {
 693  0
                 if (f == getContent()) {
 694  0
                     f.setHandleBox(x, y, width, height);
 695  0
                 } else if (f == neighbour && f == previousPartition) {
 696  0
                     f.setHandleBox(f.getX(), y, newNeighbourWidth, height);
 697  0
                 } else if (f == neighbour && f == nextPartition) {
 698  0
                     f.setHandleBox(x + width, y, newNeighbourWidth, height);
 699  
                 } else {
 700  0
                     f.setHandleBox(f.getX(), y, f.getWidth(), height);
 701  
                 }
 702  0
                 if (f.getHandleBox().getX() < lowX || totalWidth == 0) {
 703  0
                     lowX = f.getHandleBox().x;
 704  
                 }
 705  0
                 totalWidth += f.getHandleBox().width;
 706  
             }
 707  0
             FigPool pool = getFigPool();
 708  0
             pool.setBounds(lowX, y, totalWidth, height);
 709  0
         }
 710  
     }
 711  
 }
 712