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 --- .../org/cristalise/gui/graph/view/GraphPanel.java | 612 +++++++++++++++++++++ 1 file changed, 612 insertions(+) create mode 100644 src/main/java/org/cristalise/gui/graph/view/GraphPanel.java (limited to 'src/main/java/org/cristalise/gui/graph/view/GraphPanel.java') diff --git a/src/main/java/org/cristalise/gui/graph/view/GraphPanel.java b/src/main/java/org/cristalise/gui/graph/view/GraphPanel.java new file mode 100644 index 0000000..1076d1b --- /dev/null +++ b/src/main/java/org/cristalise/gui/graph/view/GraphPanel.java @@ -0,0 +1,612 @@ +package org.cristalise.gui.graph.view; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Observable; +import java.util.Observer; +import java.util.Vector; + +import javax.swing.JPanel; + +import org.cristalise.gui.ImageLoader; +import org.cristalise.gui.graph.controller.ElasticBand; +import org.cristalise.gui.graph.controller.Selection; +import org.cristalise.gui.graph.event.ElasticBandResizedEvent; +import org.cristalise.gui.graph.event.ElasticBandSetEvent; +import org.cristalise.gui.graph.event.SelectionChangedEvent; +import org.cristalise.gui.graph.event.SelectionMovedEvent; +import org.cristalise.kernel.graph.event.EntireModelChangedEvent; +import org.cristalise.kernel.graph.event.GraphModelResizedEvent; +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.Vertex; + +public class GraphPanel extends JPanel implements Observer +{ + // There should always be a Selection object + protected Selection mSelection = new Selection(null, null, 0, 0, 0, 0); + private ElasticBand mElasticBand = null; + protected final Paint mSelectionPaint = Color.black; + protected final Paint mStartPaint = Color.green; + protected final Image mResizePadImg = ImageLoader.findImage("graph/resizepad.gif").getImage(); + protected final BasicStroke mDashed = + new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] { 5.0f }, 0.0f); + protected GraphModelManager mGraphModelManager = null; + protected VertexRenderer mVertexRenderer = null; + protected DirectedEdgeRenderer mDirectedEdgeRenderer = null; + private final SelectionChangedEvent mSelectionChangedEvent = new SelectionChangedEvent(); + private final SelectionMovedEvent mSelectionMovedEvent = new SelectionMovedEvent(); + private final ElasticBandResizedEvent mElasticBandResizedEvent = new ElasticBandResizedEvent(); + private final ElasticBandSetEvent mElasticBandSetEvent = new ElasticBandSetEvent(); + + public GraphPanel(DirectedEdgeRenderer eRenderer, VertexRenderer vRenderer) + { + mVertexRenderer = vRenderer; + mDirectedEdgeRenderer = eRenderer; + // Request the keyboard focus if the mouse + // is pressed on the graph panel + addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent me) + { + requestFocus(); + } + }); + } + public void setGraphModelManager(GraphModelManager graphModelManager) + { + mGraphModelManager = graphModelManager; + } + @Override + public void update(Observable o, Object arg) + { + if (arg instanceof EntireModelChangedEvent) + { + mSelection = new Selection(null, null, 0, 0, 0, 0); + } + if (arg instanceof GraphModelResizedEvent || arg instanceof EntireModelChangedEvent) + { + setPreferredSize(new Dimension(mGraphModelManager.getModel().getWidth(), mGraphModelManager.getModel().getHeight())); + revalidate(); + } + repaint(); + } + // Updates the top left and bottom right corners of the selection + private void updateSelectionCorners() { + Vertex vertex = mSelection.mVertices[0]; + GraphPoint centrePoint = vertex.getCentrePoint(); + if (centrePoint == null) return; + mSelection.mTopLeftX = centrePoint.x; + mSelection.mTopLeftY = centrePoint.y; + mSelection.mBottomRightX = centrePoint.x; + mSelection.mBottomRightY = centrePoint.y; + for (Vertex mVertice : mSelection.mVertices) { + vertex = mVertice; + centrePoint = vertex.getCentrePoint(); + if (centrePoint.x < mSelection.mTopLeftX) { + mSelection.mTopLeftX = centrePoint.x; + } + if (centrePoint.y < mSelection.mTopLeftY) { + mSelection.mTopLeftY = centrePoint.y; + } + if (centrePoint.x > mSelection.mBottomRightX) { + mSelection.mBottomRightX = centrePoint.x; + } + if (centrePoint.y > mSelection.mBottomRightY) { + mSelection.mBottomRightY = centrePoint.y; + } + } + } + + public void deleteSelection() { + int i = 0; + if (mSelection.mVertices != null) { + for (i = 0; i < mSelection.mVertices.length; i++) { + mGraphModelManager.getModel().removeVertex(mSelection.mVertices[i]); + } + } + else if (mSelection.mEdge != null) { + mGraphModelManager.getModel().removeEdge(mSelection.mEdge); + } + // Make sure nothing is selected + if ((mSelection.mEdge != null) || (mSelection.mVertices != null)) { + mSelection.mEdge = null; + mSelection.mVertices = null; + mSelectionChangedEvent.mSelection = mSelection; + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + } + + public void selectAll() { + Vertex[] allVertices = mGraphModelManager.getModel().getVertices(); + if (allVertices.length > 0) { + mSelection.mEdge = null; + mSelection.mVertices = allVertices; + updateSelectionCorners(); + mSelectionChangedEvent.mSelection = mSelection; + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + } + + public void selectContentsOfElasticBand() { + if (mElasticBand == null) return; + Polygon bandPolygon = new Polygon(); + Vertex[] allVertices = mGraphModelManager.getModel().getVertices(); + GraphPoint centrePoint = null; + Vector verticesInside = new Vector(10, 10); + int i = 0; + // Create a polygon representing the elastic band + bandPolygon.addPoint(mElasticBand.mFixedCorner.x, mElasticBand.mFixedCorner.y); + bandPolygon.addPoint(mElasticBand.mMovingCorner.x, mElasticBand.mFixedCorner.y); + bandPolygon.addPoint(mElasticBand.mMovingCorner.x, mElasticBand.mMovingCorner.y); + bandPolygon.addPoint(mElasticBand.mFixedCorner.x, mElasticBand.mMovingCorner.y); + // Create a vector of all of the vertices within the elastic band polygon + for (i = 0; i < allVertices.length; i++) { + centrePoint = allVertices[i].getCentrePoint(); + if (bandPolygon.contains(centrePoint.x, centrePoint.y)) { + verticesInside.add(allVertices[i]); + } + } + + // Select the vertices found within the elastic band polygon + if (verticesInside.size() == 0) { + mSelection.mTopLeftX = 0; + mSelection.mTopLeftY = 0; + mSelection.mBottomRightX = 0; + mSelection.mBottomRightY = 0; + mSelection.mEdge = null; + // select parent vertex if we have selected the 'paper' + if (mGraphModelManager.getModel().getContainingVertex() != null) + verticesInside.add(mGraphModelManager.getModel().getContainingVertex()); + else + mSelection.mVertices = null; + } + + if (verticesInside.size() > 0) { + mSelection.mEdge = null; + mSelection.mVertices = new Vertex[verticesInside.size()]; + for (i = 0; i < verticesInside.size(); i++) { + mSelection.mVertices[i] = verticesInside.elementAt(i); + } + updateSelectionCorners(); + } + // Remove the elastic band + mElasticBand = null; + mSelectionChangedEvent.mSelection = mSelection; + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + + + + public void setSelectedVertexToBeStart() { + if (mSelection.mVertices != null) { + if (mSelection.mVertices.length == 1) { + mGraphModelManager.getModel().setStartVertexId(mSelection.mVertices[0].getID()); + } + } + } + + public Selection getSelection() { + return mSelection; + } + + public void setElasticBand(ElasticBand elasticBand) { + mElasticBand = elasticBand; + mGraphModelManager.notifyObservers(mElasticBandSetEvent); + } + + public void resizeElasticBand(GraphPoint movingCorner) { + mElasticBand.mMovingCorner = movingCorner; + mGraphModelManager.notifyObservers(mElasticBandResizedEvent); + } + + public boolean inSelection(Vertex v) { + int i = 0; + if (mSelection.mVertices == null) { + return false; + } + else { + for (i = 0; i < mSelection.mVertices.length; i++) { + if (mSelection.mVertices[i] == v) { + return true; + } + } + return false; + } + } + + // Only use this method to remove one vertex. + // If you wish to remove more, it would + // propably be more efficient to create a + // new Selection object. + public void removeFromSelection(Vertex v) { + Vertex[] vertices = null; + int i = 0; + int j = 0; + if (mSelection.mVertices.length == 1) { + mSelection.mVertices = null; + mSelection.mTopLeftX = 0; + mSelection.mTopLeftY = 0; + mSelection.mBottomRightX = 0; + mSelection.mBottomRightY = 0; + } + else { + vertices = new Vertex[mSelection.mVertices.length - 1]; + for (i = 0; i < mSelection.mVertices.length; i++) { + if (mSelection.mVertices[i] != v) { + vertices[j] = mSelection.mVertices[i]; + j++; + } + } + mSelection.mVertices = vertices; + updateSelectionCorners(); + } + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + + // Only use this method to add one vertex. + // If you wish to add more, it would + // propably be more efficient to create a + // new Selection object. + public void addToSelection(Vertex v) { + Vertex[] vertices = new Vertex[mSelection.mVertices.length + 1]; + GraphPoint centrePoint = null; + int i = 0; + if (mSelection.mVertices == null) { + centrePoint = v.getCentrePoint(); + mSelection.mVertices = new Vertex[] { v }; + mSelection.mTopLeftX = centrePoint.x; + mSelection.mTopLeftY = centrePoint.y; + mSelection.mBottomRightX = centrePoint.x; + mSelection.mBottomRightY = centrePoint.y; + } + else { + for (i = 0; i < mSelection.mVertices.length; i++) { + vertices[i] = mSelection.mVertices[i]; + } + vertices[mSelection.mVertices.length] = v; + mSelection.mVertices = vertices; + updateSelectionCorners(); + } + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + public void moveAbsoluteSelection(int newTopLeftX, int newTopLeftY) { + int selectionHeight = mSelection.mBottomRightY - mSelection.mTopLeftY; + int selectionWidth = mSelection.mBottomRightX - mSelection.mTopLeftX; + int bottomRightX = newTopLeftX + selectionWidth; + int bottomRightY = newTopLeftY + selectionHeight; + GraphPoint oldCentrePoint = null; + GraphPoint newCentrePoint = null; + int distXFromTopLeft = 0; + int distYFromTopLeft = 0; + int i = 0; + // Make sure the selection does not move + // outside the boundaries of the graph + if (newTopLeftX < 0) newTopLeftX = 0; + if (newTopLeftY < 0) newTopLeftY = 0; + int graphWidth = mGraphModelManager.getModel().getWidth(); + if (bottomRightX > graphWidth) newTopLeftX = graphWidth - selectionWidth; + int graphHeight = mGraphModelManager.getModel().getHeight(); + if (bottomRightY > graphHeight) newTopLeftY = graphHeight - selectionHeight; + // For each selected vertex + for (i = 0; i < mSelection.mVertices.length; i++) { + // Calculate the new centre point of the vertex. + // First calculate the distance of the centre point + // from the old top left hand corner of the selection, + // then move the point to the new top left hand + // corner plus the distance. + oldCentrePoint = mSelection.mVertices[i].getCentrePoint(); + distXFromTopLeft = oldCentrePoint.x - mSelection.mTopLeftX; + distYFromTopLeft = oldCentrePoint.y - mSelection.mTopLeftY; + newCentrePoint = new GraphPoint(newTopLeftX + distXFromTopLeft, newTopLeftY + distYFromTopLeft); + mGraphModelManager.getModel().moveAbsoluteVertex(mSelection.mVertices[i], newCentrePoint); + } + // Update the top left and bottom right corners + mSelection.mTopLeftX = newTopLeftX; + mSelection.mTopLeftY = newTopLeftY; + mSelection.mBottomRightX = newTopLeftX + selectionWidth; + mSelection.mBottomRightY = newTopLeftY + selectionHeight; + mGraphModelManager.notifyObservers(mSelectionMovedEvent); + } + + // If the specified point is within more than one vertex, + // then the smallest vertex is returned. + public Vertex getVertex(GraphPoint p) { + Object[] vertexObjs = mGraphModelManager.getModel().getVertices(); + Vertex vertex = null; + Vector vertexVector = new Vector(10, 10); + int numVerticesFound = 0; + Vertex smallestVertex = null; + int sizeOfSmallestVertex = 0; + int sizeOfVertex = 0; + int i = 0; + for (i = 0; i < vertexObjs.length; i++) { + vertex = (Vertex)vertexObjs[i]; + if (vertex.containsPoint(p)) { + vertexVector.add(vertex); + } + } + numVerticesFound = vertexVector.size(); + if (numVerticesFound == 0) { + return null; + } + else { + smallestVertex = vertexVector.elementAt(0); + sizeOfSmallestVertex = smallestVertex.getHeight() * smallestVertex.getWidth(); + // Determine the smallest vertex + for (i = 1; i < numVerticesFound; i++) { + vertex = vertexVector.elementAt(i); + sizeOfVertex = vertex.getHeight() * vertex.getWidth(); + if (sizeOfVertex < sizeOfSmallestVertex) { + smallestVertex = vertex; + sizeOfSmallestVertex = sizeOfVertex; + } + } + return smallestVertex; + } + } + + public DirectedEdge getEdge(GraphPoint p) { + Object[] edgeObjs = mGraphModelManager.getModel().getEdges(); + DirectedEdge edge = null; + int i = 0; + for (i = 0; i < edgeObjs.length; i++) { + edge = (DirectedEdge)edgeObjs[i]; + if (edge.containsPoint(p)) { + return edge; + } + } + return null; + } + + + public void setSelection(Selection s) { + // If the there is a change + if (selectionChanged(s)) { + mSelection = s; + mSelectionChangedEvent.mSelection = s; + mGraphModelManager.notifyObservers(mSelectionChangedEvent); + } + } + + private boolean selectionChanged(Selection newValue) { + int i = 0; + if (mSelection.mEdge != newValue.mEdge) { + return true; + } + if (mSelection.mVertices == null) { + if (newValue.mVertices == null) { + return false; + } + else { + return true; + } + } + else { + if (newValue.mVertices == null) { + return true; + } + else { + if (mSelection.mVertices.length != newValue.mVertices.length) { + return true; + } + for (i = 0; i < mSelection.mVertices.length; i++) { + if (mSelection.mVertices[i] != newValue.mVertices[i]) { + return true; + } + } + return false; + } + } + } + @Override + public void paintComponent(Graphics g) + { + Graphics2D g2d = (Graphics2D) g; + DirectedEdge[] edges = null; + Vertex[] vertices = null; + Vertex startVertex = null; + Vertex newEdgeOriginVertex = null; + GraphPoint newEdgeOriginPoint = null; + GraphPoint newEdgeEndPoint = null; + GraphPoint vertexCentre = null; + int i = 0; + super.paintComponent(g); + if (mGraphModelManager != null) + { + // Get the edges and vertices from the model + edges = mGraphModelManager.getModel().getEdges(); + vertices = mGraphModelManager.getModel().getVertices(); + //graphable = mGraphModelManager.getModel(). + // Draw the edges + for (i = 0; i < edges.length; i++) + { + mDirectedEdgeRenderer.draw(g2d, edges[i]); + } + // Draw the vertices + for (i = 0; i < vertices.length; i++) + { + mVertexRenderer.draw(g2d, vertices[i]); + } + g2d.setPaint(mStartPaint); + // Highlight the start vertex if there is one + startVertex = mGraphModelManager.getModel().getStartVertex(); + if (startVertex != null) + { + drawVertexHighlight(g2d, startVertex, 1); + } + g2d.setPaint(mSelectionPaint); + // Draw the outline of the selected + // vertices if there are any + if (mSelection.mVertices != null) + { + g2d.setStroke(mDashed); + for (i = 0; i < mSelection.mVertices.length; i++) + { + if (mSelection.mVertices[i] != mGraphModelManager.getModel().getContainingVertex()) + drawVertexHighlight(g2d, mSelection.mVertices[i], 5); + } + // Draw the resize pads if there is one and only one vertex selected + if (mSelection.mVertices.length == 1 && + mSelection.mVertices[0] != mGraphModelManager.getModel().getContainingVertex()) + { + vertexCentre = mSelection.mVertices[0].getCentrePoint(); + g2d.drawImage( + mResizePadImg, + vertexCentre.x + mSelection.mVertices[0].getWidth() / 2, + vertexCentre.y + mSelection.mVertices[0].getHeight() / 2, + this); + } + } + // Draw the outline of the selected + // edge if there is one + if (mSelection.mEdge != null) + { + drawEdgeHighlight(g2d, mSelection.mEdge); + } + // Draw the elastic band if there + // is one + if (mElasticBand != null) + { + g2d.drawLine( + mElasticBand.mFixedCorner.x, + mElasticBand.mFixedCorner.y, + mElasticBand.mMovingCorner.x, + mElasticBand.mFixedCorner.y); + g2d.drawLine( + mElasticBand.mMovingCorner.x, + mElasticBand.mFixedCorner.y, + mElasticBand.mMovingCorner.x, + mElasticBand.mMovingCorner.y); + g2d.drawLine( + mElasticBand.mMovingCorner.x, + mElasticBand.mMovingCorner.y, + mElasticBand.mFixedCorner.x, + mElasticBand.mMovingCorner.y); + g2d.drawLine( + mElasticBand.mFixedCorner.x, + mElasticBand.mMovingCorner.y, + mElasticBand.mFixedCorner.x, + mElasticBand.mFixedCorner.y); + } + // Draw the new edge under construction if there is one + newEdgeEndPoint = mGraphModelManager.getModel().getNewEdgeEndPoint(); + newEdgeOriginVertex = mGraphModelManager.getModel().getNewEdgeOriginVertex(); + if ((newEdgeEndPoint != null) && (newEdgeOriginVertex != null)) + { + newEdgeOriginPoint = newEdgeOriginVertex.getCentrePoint(); + g2d.setPaint(Color.black); + g2d.drawLine(newEdgeOriginPoint.x, newEdgeOriginPoint.y, newEdgeEndPoint.x, newEdgeEndPoint.y); + } + } + } + // Draws the highlight of the specified vertex the specified dist from its outline + protected void drawVertexHighlight(Graphics2D g2d, Vertex vertex, int dist) + { + GraphPoint[] outlinePoints = vertex.getOutlinePoints(); + GraphPoint centrePoint = vertex.getCentrePoint(); + int i = 0; + /* + * float dash1[] ={5.0f}; BasicStroke bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,10.0f, dash1,0.0f); + */ + for (i = 0; i < outlinePoints.length - 1; i++) + { + drawShiftedLine(dist, g2d, centrePoint, outlinePoints[i].x, outlinePoints[i].y, outlinePoints[i + 1].x, outlinePoints[i + 1].y); + } + drawShiftedLine( + dist, + g2d, + centrePoint, + outlinePoints[outlinePoints.length - 1].x, + outlinePoints[outlinePoints.length - 1].y, + outlinePoints[0].x, + outlinePoints[0].y); + } + // Draws the specifed line the specified distance away from the specified centre point + private static void drawShiftedLine(int dist, Graphics2D g2d, GraphPoint centrePoint, int x1, int y1, int x2, int y2) + { + if (x1 > centrePoint.x) + x1 += dist; + if (x1 < centrePoint.x) + x1 -= dist; + if (y1 > centrePoint.y) + y1 += dist; + if (y1 < centrePoint.y) + y1 -= dist; + if (x2 > centrePoint.x) + x2 += dist; + if (x2 < centrePoint.x) + x2 -= dist; + if (y2 > centrePoint.y) + y2 += dist; + if (y2 < centrePoint.y) + y2 -= dist; + g2d.drawLine(x1, y1, x2, y2); + } + // Draws the highlight of the specified edge + protected void drawEdgeHighlight(Graphics2D g2d, DirectedEdge edge) + { + GraphPoint originPoint = edge.getOriginPoint(); + GraphPoint terminusPoint = edge.getTerminusPoint(); + int midX = originPoint.x + (terminusPoint.x - originPoint.x) / 2; + int midY = originPoint.y + (terminusPoint.y - originPoint.y) / 2; + int minX = midX - 10; + int minY = midY - 10; + int maxX = midX + 10; + int maxY = midY + 10; + g2d.drawLine(minX, minY, maxX, minY); + g2d.drawLine(maxX, minY, maxX, maxY); + g2d.drawLine(maxX, maxY, minX, maxY); + g2d.drawLine(minX, maxY, minX, minY); + } + @Override + public void printComponent(Graphics g) + { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + DirectedEdge[] edges = null; + Vertex[] vertices = null; + Vertex startVertex = null; + int i = 0; + g.setColor(Color.white); + g2d.fillRect(0,0,getWidth(),getHeight()); + if (mGraphModelManager != null) + { + // Get the edges and vertices from the model + edges = mGraphModelManager.getModel().getEdges(); + vertices = mGraphModelManager.getModel().getVertices(); + //graphable = mGraphModelManager.getModel(). + // Draw the edges + for (i = 0; i < edges.length; i++) + { + mDirectedEdgeRenderer.draw(g2d, edges[i]); + } + // Draw the vertices + for (i = 0; i < vertices.length; i++) + { + mVertexRenderer.draw(g2d, vertices[i]); + } + g2d.setPaint(mStartPaint); + // Highlight the start vertex if there is one + startVertex = mGraphModelManager.getModel().getStartVertex(); + if (startVertex != null) + { + drawVertexHighlight(g2d, startVertex, 1); + } + } + } + + protected void superPaint(Graphics g) + { + super.paintComponent(g); + } +} -- cgit v1.2.3