// Copyright (c) 1996-98 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation for educational, research and non-profit // purposes, without fee, and without a written agreement is hereby granted, // provided that the above copyright notice and this paragraph appear in all // copies. Permission to incorporate this software into commercial products may // be obtained by contacting the University of California. David F. Redmiles // Department of Information and Computer Science (ICS) University of // California Irvine, California 92697-3425 Phone: 714-824-3823. This software // program and documentation are copyrighted by The Regents of the University // of California. The software program and documentation are supplied "as is", // without any accompanying services from The Regents. The Regents do not // warrant that the operation of the program will be uninterrupted or // error-free. The end-user understands that the program was developed for // research purposes and is advised not to rely exclusively on the program for // any reason. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY // DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE // SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, // ENHANCEMENTS, OR MODIFICATIONS. // File: ModeModify.java // Classes: ModeModify // Original Author: ics125b spring 1996 // $Id: ModeModify.java,v 1.13 1997/06/10 23:43:12 jrobbins Exp $ package uci.graphedit; import java.awt.Event; import java.awt.Point; /** A Mode to process events from the Editor when the user is * modifying a DiagramElement. Right now users can drag one or more * DiagramElement's around the drawing area, or they can move a handle * on a single DiagramElement. The DiagramElement is responsible for * reacting to the movement of a handle, but so far they all resize * themselves. In the future, some DiagramElement's may have handles * that set properties other than size (e.g., spline curvature). * * FEATURE: editing_modes_modify */ public class ModeModify extends Mode { /** The point relative to the original postition of the * DiagramElement where the dragging started. Keeping this point * allows the user to "grip" any part of the DiagramElement, rather * than just dragging its position (or "pin") around. */ protected Point _anchor; /** the mouse location for the most recent drag event */ protected int _lastX = 1000, _lastY = 1000; /** the mouse location for the first mouse down event*/ protected int _startX, _startY; /** has the mouse moved enough to indicate that the user really * wants to modify somthing? */ protected boolean _minDeltaAchieved; /** Minimum amoun that the user must move the mouse to indicate that he * really wants to modify something. */ public static final int MIN_DELTA = 4; /** the ID of the handle that the user is dragging */ protected Handle _curHandle = new Handle(-1); public static final int NO_CONSTRAINT = 0; public static final int HORIZONTAL_CONSTRAINT = 1; public static final int VERTICAL_CONSTRAINT = 2; protected int _constraint = NO_CONSTRAINT; /** Construct a new ModeModify with the given parent, and set the * Anchor point to a default location (the _anchor's proper position * will be determioned on mouse down). */ ModeModify(Editor par) { super(par); _anchor = new Point(0,0); } private static Point snapPt = new Point(0, 0); /** When the user drags the mouse two things can happen: (1) if the * user is dragging the body of one or more DiagramElement's then * they are all moved around the drawing area, or (2) if the user * started dragging on a handle of one DiagramElement then the user * can drag the handle around the drawing area and the * DiagramElement reacts to that. * * FEATURE: drag_object * * FEATURE: drag_object_constrained * * FEATURE: drag_handle * * FEATURE: drag_handle_constrained * * FEATURE: locked_objects * * BUG: arc_translate */ public boolean mouseDrag(Event e, int x, int y) { int dx, dy, snapX, snapY; if (!checkMinDelta(x, y)) return true; Selection sel = parent.selection(); if (sel.locked()) { Globals.showStatus("Cannot Modify Locked Objects"); return true; } synchronized (snapPt) { snapPt.move(x, y); parent.snap(snapPt); snapX = snapPt.x; snapY = snapPt.y; } dx = snapX - _lastX; dy = snapY - _lastY; if (e.controlDown() && _constraint == NO_CONSTRAINT) { if (dx != 0) _constraint = HORIZONTAL_CONSTRAINT; if (dy != 0) _constraint = VERTICAL_CONSTRAINT; } if (_constraint == HORIZONTAL_CONSTRAINT) dy = 0; if (_constraint == VERTICAL_CONSTRAINT) dx = 0; if (dx == 0 && dy == 0) return true; sel.startTrans(); if (_curHandle.index == -1) sel.translate(dx, dy); else sel.dragHandle(snapX, snapY, _anchor.x, _anchor.y, _curHandle); sel.endTrans(); _lastX = snapX; _lastY = snapY; return true; } /** When the user presses the mouse button on a DiagramElement, * this Mode starts preparing for future drag events by finding if * a handle was clicked on. This event is passed from ModeSelect. */ public boolean mouseDown(Event e, int x, int y) { start(); Selection sel = parent.selection(); if (sel.isEmpty()) { done(); } if (sel.locked()) { Globals.showStatus("Cannot Modify Locked Objects"); return true; } /* needs-more-work: _anchor point sign convention is backwards */ _anchor.x = sel.position().x - x; _anchor.y = sel.position().y - y; _curHandle.index = sel.pickHandle(x, y); sel.endTrans(); synchronized (snapPt) { snapPt.move(x, y); parent.snap(snapPt); _startX = _lastX = snapPt.x; _startY = _lastY = snapPt.y; } return true; } /** On mouse up the modification interaction is done. */ public boolean mouseUp(Event e, int x, int y) { done(); return true; } public void start() { _minDeltaAchieved = false; super.start(); } /** Reply true if the user had moved the mouse enough to signify * that (s)he really wants to make a change. * * FEATURE: minimum_modify_delta */ public boolean checkMinDelta(int x, int y) { if (x > _startX + MIN_DELTA || x < _startX - MIN_DELTA || y > _startY + MIN_DELTA || y < _startY - MIN_DELTA) _minDeltaAchieved = true; return _minDeltaAchieved; } } /* end class ModeModify */