From 5e4034b5cba89460a62fa958fc78c2b85acb3d5f Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 7 Oct 2014 09:18:33 +0200 Subject: Repackage to org.cristalise --- .../controller/MultiSelectionDragController.java | 575 +++++++++++++++++++++ 1 file changed, 575 insertions(+) create mode 100644 src/main/java/org/cristalise/gui/graph/controller/MultiSelectionDragController.java (limited to 'src/main/java/org/cristalise/gui/graph/controller/MultiSelectionDragController.java') diff --git a/src/main/java/org/cristalise/gui/graph/controller/MultiSelectionDragController.java b/src/main/java/org/cristalise/gui/graph/controller/MultiSelectionDragController.java new file mode 100644 index 0000000..e677cce --- /dev/null +++ b/src/main/java/org/cristalise/gui/graph/controller/MultiSelectionDragController.java @@ -0,0 +1,575 @@ +package org.cristalise.gui.graph.controller; + +import java.awt.Point; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import org.cristalise.gui.graph.view.EditorModeListener; +import org.cristalise.gui.graph.view.GraphPanel; +import org.cristalise.kernel.graph.model.DirectedEdge; +import org.cristalise.kernel.graph.model.GraphModelManager; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.GraphableVertex; +import org.cristalise.kernel.graph.model.Vertex; + + + +public class MultiSelectionDragController +extends MouseAdapter +implements EditorModeListener, KeyListener +{ + + private class ResizeInf + { + public int mMousePressedX = 0; + public int mMousePressedY = 0; + public Vertex mSelectedVertex = null; + public GraphPoint[] mOldOutline = null; + public int mCentreX = 0; + public int mCentreY = 0; + public int mOldHeight = 0; + public int mOldWidth = 0; + } + private ResizeInf mResizeInf = new ResizeInf(); + + private class DispForSelection + { + public int mXDisp = 0; + public int mYDisp = 0; + } + private DispForSelection mDispForSelection = null; + + private class VertexAndDisp + { + public Vertex mVertex = null; + public int mXDisp = 0; + public int mYDisp = 0; + } + + protected GraphModelManager mGraphModelManager = null; + private GraphPanel mGraphPanel = null; + + + /**********/ + /* States */ + /**********/ + protected final Integer kOtherMode = new Integer(0); + protected final Integer kWaiting = new Integer(1); + protected final Integer kResizing = new Integer(2); + protected final Integer kDraggingSelection = new Integer(3); + protected final Integer kStretching = new Integer(4); + + + /**********/ + /* Events */ + /**********/ + protected final int kSelectEntered = 0; + protected final int kOtherEntered = 1; + protected final int kPressOnEdge = 2; + protected final int kPressOnVertex = 3; + protected final int kPressOnSelection = 4; + protected final int kPressOnResizePad = 5; + protected final int kCTRLPressOnVertex = 6; + protected final int kCTRL_A = 7; + protected final int kPressOnNothing = 8; + protected final int kDrag = 9; + protected final int kRelease = 10; + protected final int kZoomIn = 11; + + /***********/ + /* Actions */ + /***********/ + + protected interface Action + { + public void doIt(Object data); + } + + + protected Action mStoreResizeInf = new Action() + { + @Override + public void doIt(Object data) + { + Point mousePoint = (Point)data; + GraphPoint centre = null; + + mResizeInf.mMousePressedX = mousePoint.x; + mResizeInf.mMousePressedY = mousePoint.y; + mResizeInf.mSelectedVertex = mGraphPanel.getSelection().mVertices[0]; + mResizeInf.mOldOutline = mResizeInf.mSelectedVertex.getOutlinePoints(); + centre = mResizeInf.mSelectedVertex.getCentrePoint(); + mResizeInf.mCentreX = centre.x; + mResizeInf.mCentreY = centre.y; + mResizeInf.mOldHeight = mResizeInf.mSelectedVertex.getHeight(); + mResizeInf.mOldWidth = mResizeInf.mSelectedVertex.getWidth(); + } + }; + + + protected Action mResizeVertex = new Action() + { + @Override + public void doIt(Object data) + { + Point mousePoint = (Point)data; + int resizeX = 0; + int resizeY = 0; + + + // Calculate how much the old outline should be resized + resizeX = mousePoint.x - mResizeInf.mMousePressedX; + resizeY = mousePoint.y - mResizeInf.mMousePressedY; + + // Clip the resize so that outline does not get any + // smaller than 10 x 10 pixels + if(resizeX < -mResizeInf.mOldWidth/2 + 10) + { + resizeX = -mResizeInf.mOldWidth/2 + 10; + } + + if(resizeY < -mResizeInf.mOldHeight/2 + 10) + { + resizeY = -mResizeInf.mOldHeight/2 + 10; + } + + if (mGraphModelManager.isEditable()) { + mResizeInf.mSelectedVertex.setOutlinePoints(newOutline(resizeX, resizeY)); + mGraphModelManager.forceNotify(); + } + } + + + private GraphPoint[] newOutline(int resizeX, int resizeY) + { + GraphPoint[] newOutline = new GraphPoint[mResizeInf.mOldOutline.length]; + int x = 0; + int y = 0; + int i = 0; + + + for(i=0; i mResizeInf.mCentreX) + { + x = mResizeInf.mOldOutline[i].x + resizeX; + } + else if(mResizeInf.mOldOutline[i].x < mResizeInf.mCentreX) + { + x = mResizeInf.mOldOutline[i].x - resizeX; + } + else + { + x = mResizeInf.mOldOutline[i].x; + } + + if(mResizeInf.mOldOutline[i].y > mResizeInf.mCentreY) + { + y = mResizeInf.mOldOutline[i].y + resizeY; + } + else if(mResizeInf.mOldOutline[i].y < mResizeInf.mCentreY) + { + y = mResizeInf.mOldOutline[i].y - resizeY; + } + else + { + y = mResizeInf.mOldOutline[i].y; + } + + newOutline[i] = new GraphPoint(x, y); + } + + return newOutline; + } + }; + + + protected Action mSelectEdge = new Action() + { + @Override + public void doIt(Object data) + { + Selection selection = new Selection((DirectedEdge)data, null, 0, 0, 0, 0); + + mGraphPanel.setSelection(selection); + } + }; + + + protected Action mSelectVertexAndStoreDisp = new Action() + { + @Override + public void doIt(Object data) + { + VertexAndDisp vertexAndDisp = (VertexAndDisp)data; + GraphPoint centrePoint = vertexAndDisp.mVertex.getCentrePoint(); + Selection selection = new Selection(null, + new Vertex[] {vertexAndDisp.mVertex}, + centrePoint.x, + centrePoint.y, + centrePoint.x, + centrePoint.y); + + mGraphPanel.setSelection(selection); + mDispForSelection = new DispForSelection(); + mDispForSelection.mXDisp = vertexAndDisp.mXDisp; + mDispForSelection.mYDisp = vertexAndDisp.mYDisp; + } + }; + + + protected Action mStoreDisp = new Action() + { + @Override + public void doIt(Object data) + { + mDispForSelection = (DispForSelection)data; + } + }; + + + protected Action mToggleVertex = new Action() + { + @Override + public void doIt(Object data) + { + Vertex vertex = (Vertex)data; + + if(mGraphPanel.inSelection(vertex)) + { + mGraphPanel.removeFromSelection(vertex); + } + else + { + mGraphPanel.addToSelection(vertex); + } + } + }; + + + protected Action mSelectAll = new Action() + { + @Override + public void doIt(Object data) + { + mGraphPanel.selectAll(); + } + }; + + + protected Action mCreateBand = new Action() + { + @Override + public void doIt(Object data) + { + Point mouse = (Point)data; + GraphPoint fixedCorner = new GraphPoint(mouse.x, mouse.y); + + mGraphPanel.setElasticBand(new ElasticBand(fixedCorner, fixedCorner)); + } + }; + + + protected Action mMoveSelection = new Action() + { + @Override + public void doIt(Object data) + { + Point mousePoint = (Point)data; + int topLeftX = mousePoint.x - mDispForSelection.mXDisp; + int topLeftY = mousePoint.y - mDispForSelection.mYDisp; + if (mGraphModelManager.isEditable()) { + mGraphPanel.moveAbsoluteSelection(topLeftX, topLeftY); + } + } + }; + + + protected Action mResizeBand = new Action() + { + @Override + public void doIt(Object data) + { + Point mouse = (Point)data; + mGraphPanel.resizeElasticBand(new GraphPoint(mouse.x, mouse.y)); + } + }; + + + protected Action mSelectContents = new Action() + { + @Override + public void doIt(Object data) + { + mGraphPanel.selectContentsOfElasticBand(); + } + }; + + protected Action mZoomIn = new Action() + { + @Override + public void doIt(Object data) // data is the clicked vertex + { + // Need to get child graph model out of the vertex before we can zoom in + if (data instanceof Vertex) { + Vertex zoomTo = (Vertex)data; + if (((GraphableVertex)zoomTo).getIsComposite()) mGraphModelManager.zoomIn(zoomTo); + } + } + }; + + /***********************************/ + /* Finite State Transition Network */ + /***********************************/ + + protected Object[][][] mFSTN = + {// OtherMode Waiting Resizing DraggingSelection Stretching + /* SelectEntered */ {{null, kWaiting}, null , null , null , null }, + /* OtherEntered */ { null , {null , kOtherMode }, null , null , null }, + /* PressOnEdge */ { null , {mSelectEdge , null }, null , null , null }, + /* PressOnVertex */ { null , {mSelectVertexAndStoreDisp, kDraggingSelection}, null , null , null }, + /* PressOnSelection */ { null , {mStoreDisp , kDraggingSelection}, null , null , null }, + /* PressOnResizePad */ { null , {mStoreResizeInf , kResizing }, null , null , null }, + /* CTRLPressOnVertex */ { null , {mToggleVertex , null }, null , null , null }, + /* CTRL_A */ { null , {mSelectAll , null }, null , null , null }, + /* PressOnNothing */ { null , {mCreateBand , kStretching }, null , null , null }, + /* Drag */ { null , null , {mResizeVertex, null }, {mMoveSelection, null }, {mResizeBand , null }}, + /* Release */ { null , null , {null , kWaiting}, {null , kWaiting}, {mSelectContents, kWaiting}}, + /* Double Click */ { null , {mZoomIn , null }, null , null , null }, + }; + + + /*****************/ + /* Current state */ + /*****************/ + + private Integer mState = kWaiting; + + /**************************/ + /* Event processing logic */ + /**************************/ + + protected void processEvent(int event, Object data) + { + Object[] transition = mFSTN[event][mState.intValue()]; + Action action = null; + Integer nextState = null; + + if(transition != null) + { + action = (Action)transition[0]; + nextState = (Integer)transition[1]; + + if(action != null) + { + action.doIt(data); + } + + if(nextState != null) + { + mState = nextState; + } + } + } + + + /********************/ + /* Public interface */ + /********************/ + + + public MultiSelectionDragController(GraphModelManager graphModelManager, + GraphPanel graphPanel) { + mGraphModelManager = graphModelManager; + mGraphPanel = graphPanel; + } + + @Override + public void editorModeChanged(String idOfNewMode) + { + if(idOfNewMode.equals("Select")) + { + processEvent(kSelectEntered, null); + } + else + { + processEvent(kOtherEntered, null); + } + } + + + @Override + public void mousePressed(MouseEvent me) + { + int modifiers = me.getModifiers(); + + if(mGraphModelManager != null) + { + if((modifiers & InputEvent.CTRL_MASK) == 0) + { + mousePressedWithoutCTRL(me.getPoint()); + } + else + { + mousePressedWithCTRL(me.getPoint()); + } + } + } + + @Override + public void mouseClicked(MouseEvent me) + { + if (me.getClickCount() == 2) { // want double click + Point clickedSpot = me.getPoint(); + GraphPoint mouseGPoint = new GraphPoint(clickedSpot.x, clickedSpot.y); + Vertex clicked = mGraphPanel.getVertex(mouseGPoint); + if (clicked != null) + processEvent(kZoomIn, clicked); + } + } + + private void mousePressedWithoutCTRL(Point mousePoint) + { + GraphPoint mouseGPoint = new GraphPoint(mousePoint.x, mousePoint.y); + DirectedEdge edge = mGraphPanel.getEdge(mouseGPoint); + Vertex vertex = mGraphPanel.getVertex(mouseGPoint); + GraphPoint vertexCentrePoint = null; + VertexAndDisp vertexAndDisp = null; + Selection selection = null; + DispForSelection dispForSelection = null; + + + // In order of priority: + // 1. Click on resize pad + // 2. Click on vertex + // 3. Click on edge + if(onResizePad(mouseGPoint)) + { + processEvent(kPressOnResizePad, mousePoint); + } + else if(vertex != null) + { + if(mGraphPanel.inSelection(vertex)) + { + selection = mGraphPanel.getSelection(); + dispForSelection = new DispForSelection(); + dispForSelection.mXDisp = mousePoint.x - selection.mTopLeftX; + dispForSelection.mYDisp = mousePoint.y - selection.mTopLeftY; + + processEvent(kPressOnSelection, dispForSelection); + } + else + { + vertexCentrePoint = vertex.getCentrePoint(); + + vertexAndDisp = new VertexAndDisp(); + vertexAndDisp.mVertex = vertex; + vertexAndDisp.mXDisp = mousePoint.x - vertexCentrePoint.x; + vertexAndDisp.mYDisp = mousePoint.y - vertexCentrePoint.y; + + processEvent(kPressOnVertex, vertexAndDisp); + } + } + // vertex == null + else + { + if(edge == null) + { + processEvent(kPressOnNothing, mousePoint); + } + else + { + processEvent(kPressOnEdge, edge); + } + } + } + + + private boolean onResizePad(GraphPoint mouseGPoint) + { + Selection selection = mGraphPanel.getSelection(); + GraphPoint vertexCentre = null; + int bottomRightX = 0; + int bottomRightY = 0; + + + if(selection.mVertices == null) return false; + + if(selection.mVertices.length == 1) + { + vertexCentre = selection.mVertices[0].getCentrePoint(); + if (vertexCentre == null) return false; + bottomRightX = vertexCentre.x + selection.mVertices[0].getWidth()/2; + bottomRightY = vertexCentre.y + selection.mVertices[0].getHeight()/2; + + return + ( + (mouseGPoint.x > bottomRightX) && + (mouseGPoint.x < bottomRightX + 10) && + (mouseGPoint.y > bottomRightY) && + (mouseGPoint.y < bottomRightY + 10) + ); + } + else + { + return false; + } + } + + + private void mousePressedWithCTRL(Point mousePoint) + { + Vertex vertex = mGraphPanel.getVertex(new GraphPoint(mousePoint.x, mousePoint.y)); + + if(vertex != null) + { + processEvent(kCTRLPressOnVertex, vertex); + } + } + + + @Override + public void mouseReleased(MouseEvent me) + { + processEvent(kRelease, null); + } + + + @Override + public void mouseMoved(MouseEvent me) + { + } + + + @Override + public void mouseDragged(MouseEvent e) + { + processEvent(kDrag, e.getPoint()); + } + + + @Override + public void keyPressed(KeyEvent e) + { + if((e.getKeyCode() == KeyEvent.VK_A) && e.isControlDown()) + { + processEvent(kCTRL_A, null); + } + } + + + @Override + public void keyReleased(KeyEvent e) + { + } + + + @Override + public void keyTyped(KeyEvent e) + { + } + +} -- cgit v1.2.3