From b086f57f56bf0eb9dab9cf321a0f69aaaae84347 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Wed, 30 May 2012 08:37:45 +0200 Subject: Initial Maven Conversion --- .../graph/view/DefaultDirectedEdgeRenderer.java | 75 +++++ .../c2kernel/graph/view/DefaultVertexRenderer.java | 60 ++++ .../c2kernel/graph/view/DirectedEdgeRenderer.java | 11 + .../c2kernel/graph/view/EditorModeListener.java | 8 + .../java/com/c2kernel/graph/view/EditorPanel.java | 104 +++++++ .../com/c2kernel/graph/view/EditorToolBar.java | 346 +++++++++++++++++++++ .../java/com/c2kernel/graph/view/GraphPanel.java | 272 ++++++++++++++++ .../com/c2kernel/graph/view/PropertyTable.java | 40 +++ .../c2kernel/graph/view/PropertyTableModel.java | 135 ++++++++ .../c2kernel/graph/view/SelectedVertexPanel.java | 27 ++ .../c2kernel/graph/view/VertexPropertyPanel.java | 259 +++++++++++++++ .../com/c2kernel/graph/view/VertexRenderer.java | 11 + 12 files changed, 1348 insertions(+) create mode 100644 src/main/java/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java create mode 100644 src/main/java/com/c2kernel/graph/view/DefaultVertexRenderer.java create mode 100644 src/main/java/com/c2kernel/graph/view/DirectedEdgeRenderer.java create mode 100644 src/main/java/com/c2kernel/graph/view/EditorModeListener.java create mode 100644 src/main/java/com/c2kernel/graph/view/EditorPanel.java create mode 100644 src/main/java/com/c2kernel/graph/view/EditorToolBar.java create mode 100644 src/main/java/com/c2kernel/graph/view/GraphPanel.java create mode 100644 src/main/java/com/c2kernel/graph/view/PropertyTable.java create mode 100644 src/main/java/com/c2kernel/graph/view/PropertyTableModel.java create mode 100644 src/main/java/com/c2kernel/graph/view/SelectedVertexPanel.java create mode 100644 src/main/java/com/c2kernel/graph/view/VertexPropertyPanel.java create mode 100644 src/main/java/com/c2kernel/graph/view/VertexRenderer.java (limited to 'src/main/java/com/c2kernel/graph/view') diff --git a/src/main/java/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java b/src/main/java/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java new file mode 100644 index 0000000..2882141 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java @@ -0,0 +1,75 @@ +package com.c2kernel.graph.view; + +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; + +import com.c2kernel.graph.model.DirectedEdge; +import com.c2kernel.graph.model.GraphPoint; + + +public class DefaultDirectedEdgeRenderer implements DirectedEdgeRenderer +{ + private GeneralPath mArrowTemplate = new GeneralPath(); + private Paint mLinePaint = null; + + + public DefaultDirectedEdgeRenderer(Paint linePaint) + { + mLinePaint = linePaint; + + mArrowTemplate.moveTo(-5, 5); + mArrowTemplate.lineTo( 0, 0); + mArrowTemplate.lineTo( 5, 5); + } + + + @Override + public void draw(Graphics2D g2d, DirectedEdge directedEdge) + { + GraphPoint originPoint = directedEdge.getOriginPoint(); + GraphPoint terminusPoint = directedEdge.getTerminusPoint(); + GraphPoint midPoint = new GraphPoint(); + AffineTransform transform = new AffineTransform(); + Shape arrow = null; + + g2d.setPaint(mLinePaint); + g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y); + + midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x)/2; + midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y)/2; + + transform.translate(midPoint.x, midPoint.y); + transform.rotate(calcArrowAngle(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y)); + + arrow = mArrowTemplate.createTransformedShape(transform); + + g2d.draw(arrow); + } + + + private static double calcArrowAngle(int originX, int originY, int terminusX, int terminusY) { + double width = terminusX - originX; + double height = terminusY - originY; + + if((width == 0) && (height > 0)) return Math.PI; + + if((width == 0) && (height < 0)) return 0; + + if((width > 0) && (height == 0)) return Math.PI/2.0; + + if((width < 0) && (height == 0)) return -1.0 * Math.PI/2.0; + + if((width > 0) && (height > 0)) return Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width)); + + if((width > 0) && (height < 0)) return Math.atan(Math.abs(width)/Math.abs(height)); + + if((width < 0) && (height < 0)) return -1.0 * Math.atan(Math.abs(width)/Math.abs(height)); + + if((width < 0) && (height > 0)) return -1.0 * (Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width))); + + return 0.0; + } +} diff --git a/src/main/java/com/c2kernel/graph/view/DefaultVertexRenderer.java b/src/main/java/com/c2kernel/graph/view/DefaultVertexRenderer.java new file mode 100644 index 0000000..e9b92d0 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/DefaultVertexRenderer.java @@ -0,0 +1,60 @@ +package com.c2kernel.graph.view; + +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Polygon; + +import com.c2kernel.graph.model.GraphPoint; +import com.c2kernel.graph.model.Vertex; + + +public class DefaultVertexRenderer implements VertexRenderer +{ + private Paint mLinePaint = null; + private Paint mTextPaint = null; + private Paint mFillPaint = null; + + + public DefaultVertexRenderer(Paint linePaint, Paint textPaint, Paint fillPaint) + { + mLinePaint = linePaint; + mTextPaint = textPaint; + mFillPaint = fillPaint; + } + + + @Override + public void draw(Graphics2D g2d, Vertex vertex) + { + GraphPoint[] outlinePoints = vertex.getOutlinePoints(); + GraphPoint centrePoint = vertex.getCentrePoint(); + Polygon outline = new Polygon(); + + String vertexName = vertex.getName(); + FontMetrics metrics = g2d.getFontMetrics(); + int textWidth = metrics.stringWidth(vertexName); + int textHeight = metrics.getHeight(); + int textX = centrePoint.x - textWidth/2; + int textY = centrePoint.y + textHeight/3; + + int i = 0; + + + // Construct a shape in the outline of the vertex + for(i=0; i mListenerVector = new Vector(10, 10); + public EditorToolBar(boolean edgeCreationMode, // True if edges can be created + JButton[] otherButtons, GraphPanel graphP) + { + super(BoxLayout.X_AXIS); + mGraphPanel = graphP; + mEdgeCreationMode = edgeCreationMode; + mOtherButtons = otherButtons; + prepareModeButtons(); + mStartVertexController.setStartButton(mStartButton); + mDeletionController.setDeleteButton(mDeleteButton); + createLayout(); + createListeners(); + } + protected void prepareModeButtons() + { + // Set the tool tip texts + mVertexModeButton.setToolTipText(Language.translate("Create vertex")); + mSelectModeButton.setToolTipText(Language.translate("Multi-select and drag")); + mEdgeModeButton.setToolTipText(Language.translate("Create edge")); + mStartButton.setToolTipText(Language.translate("Select the start vertex of the graph")); + mDeleteButton.setToolTipText(Language.translate("Delete the selection")); + mPrintButton.setToolTipText(Language.translate("Print this graph")); + mPrintButton.setToolTipText(Language.translate("Copy an image of this graph to the clipboard")); + // Set the button margins to 0 + mVertexModeButton.setMargin(new Insets(0, 0, 0, 0)); + mSelectModeButton.setMargin(new Insets(0, 0, 0, 0)); + mEdgeModeButton.setMargin(new Insets(0, 0, 0, 0)); + // The initial mode is select mode + mSelectModeButton.setSelected(true); + // Add the mode buttons to the mode button group + mModeButtonGroup.add(mVertexModeButton); + mModeButtonGroup.add(mSelectModeButton); + mModeButtonGroup.add(mEdgeModeButton); + // Add the action listeners + mVertexModeButton.addActionListener(new ModeButtonListener("Vertex")); + mSelectModeButton.addActionListener(new ModeButtonListener("Select")); + mEdgeModeButton.addActionListener(new ModeButtonListener("Edge")); + } + public void enterSelectMode() + { + mSelectModeButton.setSelected(true); + notifyListeners("Select"); + } + public void updateVertexTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo) + { + int i = 0; + mVertexTypeBox.removeAllItems(); + for (i = 0; i < typeNameAndConstructionInfo.length; i++) + { + mVertexTypeBox.addItem(typeNameAndConstructionInfo[i]); + } + } + public void updateEdgeTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo) + { + int i = 0; + mEdgeTypeBox.removeAllItems(); + for (i = 0; i < typeNameAndConstructionInfo.length; i++) + { + mEdgeTypeBox.addItem(typeNameAndConstructionInfo[i]); + } + } + public TypeNameAndConstructionInfo getSelectedVertexType() + { + return (TypeNameAndConstructionInfo) mVertexTypeBox.getSelectedItem(); + } + public TypeNameAndConstructionInfo getSelectedEdgeType() + { + return (TypeNameAndConstructionInfo) mEdgeTypeBox.getSelectedItem(); + } + protected void createLayout() + { + int i = 0; + add(mSelectModeButton); + add(mVertexModeButton); + add(mVertexTypeBox); + add(Box.createHorizontalStrut(10)); + if (mEdgeCreationMode) + { + add(mEdgeModeButton); + add(mEdgeTypeBox); + } + add(Box.createGlue()); + mPrintButton.setEnabled(true); + mPrintButton.setMargin(new Insets(0, 0, 0, 0)); + add(mPrintButton); + mCopyButton.setEnabled(true); + mCopyButton.setMargin(new Insets(0, 0, 0, 0)); + add(mCopyButton); + mStartButton.setEnabled(false); + mStartButton.setMargin(new Insets(0, 0, 0, 0)); + mDeleteButton.setEnabled(false); + mDeleteButton.setMargin(new Insets(0, 0, 0, 0)); + add(mDeleteButton); + add(Box.createRigidArea(new Dimension(20, 0))); + add(mStartButton); + if (mOtherButtons != null) + { + for (i = 0; i < mOtherButtons.length; i++) + { + mOtherButtons[i].setMargin(new Insets(0, 0, 0, 0)); + add(mOtherButtons[i]); + } + } + } + protected void createListeners() + { + // The vertex mode button should be selected if the + // user select a vertex type from the vertex type box + mVertexTypeBox.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent ae) + { + mVertexModeButton.setSelected(true); + notifyListeners("Vertex"); + } + }); + // The edge mode button should be selected if the + // user select an edge type from the edge type box + mEdgeTypeBox.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent ae) + { + mEdgeModeButton.setSelected(true); + notifyListeners("Edge"); + } + }); + mPrintButton.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent ae) + { + PrinterJob _monJob = PrinterJob.getPrinterJob(); + if (_monJob.printDialog()) + _monJob.setPrintable(self()); + try + { + _monJob.print(); + } + catch (Exception ex) + { + } + } + }); + + try { + Class.forName("java.awt.datatransfer.DataFlavor").getDeclaredField("imageFlavor"); + mCopyButton.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent ae) + { + try + { + Image i = createImage(mGraphPanel.getWidth(),mGraphPanel.getHeight()); + Graphics g = i.getGraphics(); + mGraphPanel.paintComponent(g); + ImageTransferable it = new ImageTransferable(i, mGraphPanel.getWidth(), mGraphPanel.getHeight()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(it, it); + } + catch (Exception e) + { + Logger.error(e); + } + } + }); + } catch (Exception ex) { //image clipboard transfer not supported + mCopyButton.setEnabled(false); + } + } + + protected class ImageTransferable implements Transferable, ClipboardOwner { + Image image; + int width,height; + DataFlavor javaImg; + public ImageTransferable(Image image, int width, int height) { + this.image = image; + this.width = width; + this.height = height; + try { + javaImg = new DataFlavor("image/x-java-image; class=java.awt.Image", "AWT Image"); + } catch (Exception ex){ } + } + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { + if (!isDataFlavorSupported(flavor) || image == null) { + throw new UnsupportedFlavorException(flavor); + } + return image; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + boolean result = in(flavor, getTransferDataFlavors()); + return result; + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { javaImg }; + } + protected boolean in(DataFlavor flavor, DataFlavor[] flavors) { + int f = 0; + while ((f < flavors.length) && !flavor.equals(flavors[f])) { + f++; + } + return f < flavors.length; + } + @Override + public void lostOwnership(Clipboard clipboard, Transferable contents) { + image = null; + } + } + + protected void notifyListeners(String newModeId) + { + int i = 0; + EditorModeListener listener = null; + for (i = 0; i < mListenerVector.size(); i++) + { + listener = mListenerVector.elementAt(i); + listener.editorModeChanged(newModeId); + } + } + public void setGraphModelManager(GraphModelManager graphModelManager) + { + mStartVertexController.setGraphModelManager(graphModelManager); + mDeletionController.setGraphModelManager(graphModelManager); + } + public void setGraphPanel(GraphPanel graphPanel) + { + graphPanel.addKeyListener(mDeletionController); + } + public void addEditorModeListener(EditorModeListener listener) + { + mListenerVector.add(listener); + } + public void removeEditorModeListener(EditorModeListener listener) + { + mListenerVector.remove(listener); + } + public void setGraphEditable(boolean editable) + { + mVertexModeButton.setEnabled(editable); + mEdgeModeButton.setEnabled(editable); + } + public EditorToolBar self() + { + return this; + } + @Override + public int print(Graphics g, PageFormat pf, int i) throws PrinterException + { + if (i >= 1) + { + return Printable.NO_SUCH_PAGE; + } + Graphics2D g2d = (Graphics2D) g; + double scalex = pf.getImageableWidth() / mGraphPanel.getWidth(); + double scaley = pf.getImageableHeight() / mGraphPanel.getHeight(); + double scale = Math.min(Math.min(scalex, scaley), 1); + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.scale(scale, scale); + mGraphPanel.printComponent(g2d); + return Printable.PAGE_EXISTS; + } +} diff --git a/src/main/java/com/c2kernel/graph/view/GraphPanel.java b/src/main/java/com/c2kernel/graph/view/GraphPanel.java new file mode 100644 index 0000000..012fe25 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/GraphPanel.java @@ -0,0 +1,272 @@ +package com.c2kernel.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.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.JPanel; + +import com.c2kernel.graph.event.EntireModelChangedEvent; +import com.c2kernel.graph.event.GraphModelResizedEvent; +import com.c2kernel.graph.model.DirectedEdge; +import com.c2kernel.graph.model.ElasticBand; +import com.c2kernel.graph.model.GraphModelManager; +import com.c2kernel.graph.model.GraphPoint; +import com.c2kernel.graph.model.Selection; +import com.c2kernel.graph.model.Vertex; +import com.c2kernel.utils.Resource; +public class GraphPanel extends JPanel implements Observer +{ + protected final Paint mSelectionPaint = Color.black; + protected final Paint mStartPaint = Color.green; + protected final Image mResizePadImg = Resource.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; + 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 GraphModelResizedEvent || arg instanceof EntireModelChangedEvent) + { + setPreferredSize(new Dimension(mGraphModelManager.getModel().getWidth(), mGraphModelManager.getModel().getHeight())); + revalidate(); + } + repaint(); + } + @Override + public void paintComponent(Graphics g) + { + Graphics2D g2d = (Graphics2D) g; + DirectedEdge[] edges = null; + Vertex[] vertices = null; + Vertex startVertex = null; + Selection selection = null; + ElasticBand elasticBand = null; + Vertex newEdgeOriginVertex = null; + GraphPoint newEdgeOriginPoint = null; + Point 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); + } + // Get the present selection + selection = mGraphModelManager.getModel().getSelection(); + g2d.setPaint(mSelectionPaint); + // Draw the outline of the selected + // vertices if there are any + if (selection.mVertices != null) + { + g2d.setStroke(mDashed); + for (i = 0; i < selection.mVertices.length; i++) + { + if (selection.mVertices[i] != mGraphModelManager.getModel().getContainingVertex()) + drawVertexHighlight(g2d, selection.mVertices[i], 5); + } + // Draw the resize pads if there is one and only one vertex selected + if (selection.mVertices.length == 1 && + selection.mVertices[0] != mGraphModelManager.getModel().getContainingVertex()) + { + vertexCentre = selection.mVertices[0].getCentrePoint(); + g2d.drawImage( + mResizePadImg, + vertexCentre.x + selection.mVertices[0].getWidth() / 2, + vertexCentre.y + selection.mVertices[0].getHeight() / 2, + this); + } + } + // Draw the outline of the selected + // edge if there is one + if (selection.mEdge != null) + { + drawEdgeHighlight(g2d, selection.mEdge); + } + // Get the elastic band + elasticBand = mGraphModelManager.getModel().getElasticBand(); + // Draw the elastic band if there + // is one + if (elasticBand != null) + { + g2d.drawLine( + elasticBand.mFixedCorner.x, + elasticBand.mFixedCorner.y, + elasticBand.mMovingCorner.x, + elasticBand.mFixedCorner.y); + g2d.drawLine( + elasticBand.mMovingCorner.x, + elasticBand.mFixedCorner.y, + elasticBand.mMovingCorner.x, + elasticBand.mMovingCorner.y); + g2d.drawLine( + elasticBand.mMovingCorner.x, + elasticBand.mMovingCorner.y, + elasticBand.mFixedCorner.x, + elasticBand.mMovingCorner.y); + g2d.drawLine( + elasticBand.mFixedCorner.x, + elasticBand.mMovingCorner.y, + elasticBand.mFixedCorner.x, + elasticBand.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); + } +} diff --git a/src/main/java/com/c2kernel/graph/view/PropertyTable.java b/src/main/java/com/c2kernel/graph/view/PropertyTable.java new file mode 100644 index 0000000..c1257aa --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/PropertyTable.java @@ -0,0 +1,40 @@ +package com.c2kernel.graph.view; + +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + + +public class PropertyTable extends JTable +{ + public PropertyTable(PropertyTableModel tableModel) + { + super(tableModel); + } + + + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + + + return getDefaultRenderer(getCellClass(row, column)); + + } + + @Override +public TableCellEditor getCellEditor(int row, int column) { + + return getDefaultEditor(getCellClass(row, column)); + + } + + private Class getCellClass(int row, int column) { + Class cellClass = String.class; + + try { + cellClass = dataModel.getValueAt(row, column).getClass(); + } catch (NullPointerException ex) { } + + return cellClass; + } +} diff --git a/src/main/java/com/c2kernel/graph/view/PropertyTableModel.java b/src/main/java/com/c2kernel/graph/view/PropertyTableModel.java new file mode 100644 index 0000000..b1e69b1 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/PropertyTableModel.java @@ -0,0 +1,135 @@ +package com.c2kernel.graph.view; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; + +import javax.swing.JOptionPane; +import javax.swing.event.TableModelEvent; +import javax.swing.table.AbstractTableModel; + +import com.c2kernel.utils.Language; + +/************************************************************************** + * + * $Revision: 1.4 $ + * $Date: 2005/08/02 07:50:10 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class PropertyTableModel extends AbstractTableModel { + + private String[] mColumnNames = { Language.translate("Name"), Language.translate("Value") }; + HashMap sourceMap = new HashMap(); + ArrayList sortedNameList = new ArrayList(); + boolean isEditable = false; + + public PropertyTableModel() { + super(); + } + + @Override + public int getColumnCount() + { + return mColumnNames.length; + } + @Override + public String getColumnName(int col) + { + return mColumnNames[col]; + } + @Override + public int getRowCount() + { + synchronized (sourceMap) { + return sourceMap.size(); + } + } + @Override + public Object getValueAt(int rowIndex, int colIndex) + { + synchronized (sourceMap) { + String rowName = sortedNameList.get(rowIndex); + if (colIndex == 0) + return rowName; + else + return sourceMap.get(rowName); + } + } + + @Override + public void setValueAt(Object value, int rowIndex, int colIndex) + { + synchronized (sourceMap) { + if (colIndex == 0) return; + String rowName = sortedNameList.get(rowIndex); + Class oldElement = sourceMap.get(rowName).getClass(); + if (oldElement == Float.class && value.getClass() == String.class) + try { + value = Float.valueOf((String)value); + } catch (Exception ex) { } + if (value.getClass() != oldElement) + JOptionPane.showMessageDialog(null, "This property should contain a "+oldElement.getName()+" not a "+value.getClass().getName(), "Incorrect datatype", JOptionPane.ERROR_MESSAGE); + else { + sourceMap.put(rowName, value); + fireTableCellUpdated(rowIndex, colIndex); + } + } + } + + public void setMap(HashMap props) { + synchronized (sourceMap) { + sourceMap = props; + sortedNameList = new ArrayList(props.size()); + for (String string : props.keySet()) + sortedNameList.add(string); + + Collections.sort(sortedNameList, new Comparator() { + @Override + public int compare(String o1, String o2) { + return (o1.compareToIgnoreCase(o2)); + } + }); + } + fireTableChanged(new TableModelEvent(this)); + } + + @Override + public boolean isCellEditable(int row, int col) + { + return col==1 && isEditable; + } + + /** + * @return Returns the isEditable. + */ + public boolean isEditable() { + return isEditable; + } + /** + * @param isEditable The isEditable to set. + */ + public void setEditable(boolean isEditable) { + this.isEditable = isEditable; + } + + /** + * @param text + * @param object + */ + public void addProperty(String text, Object object) { + sourceMap.put(text,object); + setMap(sourceMap); + } + + /** + * @param object + */ + public void delProperty(Object propName) { + sourceMap.remove(propName); + setMap(sourceMap); + } +} diff --git a/src/main/java/com/c2kernel/graph/view/SelectedVertexPanel.java b/src/main/java/com/c2kernel/graph/view/SelectedVertexPanel.java new file mode 100644 index 0000000..966f527 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/SelectedVertexPanel.java @@ -0,0 +1,27 @@ +package com.c2kernel.graph.view; + +import javax.swing.JPanel; + +import com.c2kernel.graph.model.Vertex; + +/************************************************************************** + * + * $Revision: 1.1 $ + * $Date: 2005/05/12 10:12:52 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + + + +public abstract class SelectedVertexPanel extends JPanel { + + public SelectedVertexPanel() { + super(); + } + + public abstract void select(Vertex vert); + + public abstract void clear(); +} diff --git a/src/main/java/com/c2kernel/graph/view/VertexPropertyPanel.java b/src/main/java/com/c2kernel/graph/view/VertexPropertyPanel.java new file mode 100644 index 0000000..4e3e711 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/VertexPropertyPanel.java @@ -0,0 +1,259 @@ +package com.c2kernel.graph.view; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import com.c2kernel.graph.event.EntireModelChangedEvent; +import com.c2kernel.graph.event.SelectionChangedEvent; +import com.c2kernel.graph.model.DirectedEdge; +import com.c2kernel.graph.model.GraphModelManager; +import com.c2kernel.graph.model.GraphableEdge; +import com.c2kernel.graph.model.GraphableVertex; +import com.c2kernel.graph.model.Vertex; +import com.c2kernel.gui.tabs.EntityTabPane; +import com.c2kernel.utils.Language; +import com.c2kernel.utils.Logger; + +/************************************************************************** + * + * $Revision: 1.4 $ + * $Date: 2005/09/09 12:19:28 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class VertexPropertyPanel extends JPanel implements Observer, TableModelListener, ActionListener { + + private final PropertyTableModel mPropertyModel; + private final PropertyTable mPropertyTable; + private GraphModelManager mGraphModelManager; + private boolean isEditable = false; + GridBagLayout gridbag = new GridBagLayout(); + protected JLabel selObjName; + protected JLabel selObjClass; + JButton addPropButton; + JButton delPropButton; + Box newPropBox; + private JTextField newPropName; + private JComboBox newPropType; + String[] typeOptions = { "String", "Boolean", "Integer", "Float" }; + String[] typeInitVal = { "", "false", "0", "0.0"}; + SelectedVertexPanel mSelPanel; + + public VertexPropertyPanel() { + super(); + setLayout(gridbag); + mPropertyModel = new PropertyTableModel(); + mPropertyModel.addTableModelListener(this); + mPropertyTable = new PropertyTable(mPropertyModel); + } + + /** + * + */ + + @Override + public void update(Observable o, Object arg) { + Vertex[] selectedVertices = null; + DirectedEdge selectedEdge = null; + // If the selection has changed + if (arg instanceof SelectionChangedEvent) + { + SelectionChangedEvent event = (SelectionChangedEvent) arg; + selectedVertices = event.mSelection.mVertices; + if (selectedVertices != null) + { + if (selectedVertices.length == 1) + { + setVertex(selectedVertices[0]); + return; + } + } + selectedEdge = event.mSelection.mEdge; + if (selectedEdge != null) + { + setEdge(selectedEdge); + return; + } + } + if (arg instanceof SelectionChangedEvent || arg instanceof EntireModelChangedEvent){ + clear(); + } + } + + + @Override + public void tableChanged(TableModelEvent e) { + if (mGraphModelManager!=null) + mGraphModelManager.forceNotify(); + + } + + public void setVertex(Vertex vert) { + if (vert.getName().equals("domain")) + selObjName.setText("Domain Workflow"); + else + selObjName.setText(vert.getName()); + String className = vert.getClass().getName(); + selObjClass.setText(className.substring(className.lastIndexOf('.')+1)); + if (mSelPanel != null) mSelPanel.select(vert); + if (vert instanceof GraphableVertex) { + mPropertyModel.setMap(((GraphableVertex)vert).getProperties()); + addPropButton.setEnabled(isEditable); + delPropButton.setEnabled(isEditable); + } + } + + public void setEdge(DirectedEdge edge) { + selObjName.setText(edge.getName()); + String className = edge.getClass().getName(); + selObjClass.setText(className.substring(className.lastIndexOf('.')+1)); + if (edge instanceof GraphableEdge) { + mPropertyModel.setMap(((GraphableEdge)edge).getProperties()); + addPropButton.setEnabled(isEditable); + delPropButton.setEnabled(isEditable); + } + if (mSelPanel != null) mSelPanel.clear(); + } + + public void clear() { + selObjName.setText(""); + selObjClass.setText("Nothing Selected"); + mPropertyModel.setMap(new HashMap()); + if (mSelPanel != null) mSelPanel.clear(); + addPropButton.setEnabled(false); + delPropButton.setEnabled(false); + } + + /** + * @param isEditable The isEditable to set. + */ + public void setEditable(boolean editable) { + mPropertyModel.setEditable(editable); + isEditable = editable; + newPropBox.setVisible(editable); + } + + public void setGraphModelManager(GraphModelManager manager) { + mGraphModelManager = manager; + manager.addObserver(this); + } + + public void createLayout(SelectedVertexPanel selPanel) + { + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + c.weightx = 1; + c.weighty = 0; + c.anchor = GridBagConstraints.NORTHWEST; + c.ipadx = 5; + c.ipady = 5; + + selObjName = new JLabel(); + selObjName.setFont(EntityTabPane.titleFont); + gridbag.setConstraints(selObjName, c); + add(selObjName); + + c.gridy++; + selObjClass = new JLabel(); + gridbag.setConstraints(selObjClass, c); + add(selObjClass); + + c.gridy++; + JLabel title = new JLabel("Properties"); + title.setFont(EntityTabPane.titleFont); + gridbag.setConstraints(title, c); + add(title); + + c.gridy++; + c.fill = GridBagConstraints.BOTH; + c.weighty = 2; + JScrollPane scroll = new JScrollPane(mPropertyTable); + gridbag.setConstraints(scroll, c); + add(scroll); + + newPropBox = Box.createHorizontalBox(); + newPropBox.add(new JLabel(Language.translate("New :"))); + newPropBox.add(Box.createHorizontalGlue()); + newPropName = new JTextField(15); + newPropBox.add(newPropName); + newPropType = new JComboBox(typeOptions); + newPropBox.add(newPropType); + newPropBox.add(Box.createHorizontalStrut(1)); + addPropButton = new JButton("Add"); + addPropButton.setMargin(new Insets(0, 0, 0, 0)); + delPropButton = new JButton("Del"); + delPropButton.setMargin(new Insets(0, 0, 0, 0)); + addPropButton.addActionListener(this); + delPropButton.addActionListener(this); + newPropBox.add(addPropButton); + newPropBox.add(delPropButton); + + c.gridy++; + c.weighty=0; + c.fill= GridBagConstraints.HORIZONTAL; + gridbag.setConstraints(newPropBox, c); + add(newPropBox); + + if (selPanel != null) { + c.gridy++; + mSelPanel = selPanel; + gridbag.setConstraints(mSelPanel, c); + add(mSelPanel); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == addPropButton) { + if (newPropName.getText().length() < 1) { + JOptionPane.showMessageDialog(this, "Enter a name for the new property", "Cannot add property", JOptionPane.ERROR_MESSAGE); + return; + } + if (mPropertyModel.sourceMap.containsKey(newPropName.getText())) { + JOptionPane.showMessageDialog(this, "Property '"+newPropName.getText()+"' already exists.", "Cannot add property", JOptionPane.ERROR_MESSAGE); + return; + } + if (mPropertyTable.getCellEditor() != null) + mPropertyTable.getCellEditor().stopCellEditing(); + + try { + Class newPropClass = Class.forName("java.lang."+typeOptions[newPropType.getSelectedIndex()]); + Class[] params = {String.class}; + Constructor init = newPropClass.getConstructor(params); + Object[] initParams = { typeInitVal[newPropType.getSelectedIndex()] }; + mPropertyModel.addProperty(newPropName.getText(), init.newInstance(initParams)); + } catch (Exception ex) { + Logger.exceptionDialog(ex); + } + } + else if (e.getSource() == delPropButton) { + int selrow = mPropertyTable.getSelectedRow(); + if (selrow == -1) { + JOptionPane.showMessageDialog(this, "Select a property to remove", "Cannot delete property", JOptionPane.ERROR_MESSAGE); + return; + } + mPropertyModel.delProperty(mPropertyModel.sortedNameList.get(selrow)); + } + } +} diff --git a/src/main/java/com/c2kernel/graph/view/VertexRenderer.java b/src/main/java/com/c2kernel/graph/view/VertexRenderer.java new file mode 100644 index 0000000..1a8d263 --- /dev/null +++ b/src/main/java/com/c2kernel/graph/view/VertexRenderer.java @@ -0,0 +1,11 @@ +package com.c2kernel.graph.view; + +import java.awt.Graphics2D; + +import com.c2kernel.graph.model.Vertex; + + +public interface VertexRenderer +{ + public void draw(Graphics2D g2d, Vertex vertex); +} -- cgit v1.2.3