/*
Violet - A program for editing UML diagrams.
Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
Alexandre de Pellegrin (http://alexdp.free.fr);
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.horstmann.violet.workspace.editorpart;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Rectangle2D.Double;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JPanel;
import com.horstmann.violet.product.diagram.abstracts.IGraph;
import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
import com.horstmann.violet.product.diagram.abstracts.node.INode;
import com.horstmann.violet.workspace.editorpart.behavior.IEditorPartBehavior;
/**
* Graph editor
*/
public class EditorPart extends JPanel implements IEditorPart
{
/**
* Default constructor
*
* @param aGraph graph which will be drawn in this editor part
*/
public EditorPart(IGraph aGraph)
{
this.graph = aGraph;
this.zoom = 1;
this.grid = new PlainGrid(this);
this.graph.setGridSticker(grid.getGridSticker());
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent event)
{
behaviorManager.fireOnMousePressed(event);
}
public void mouseReleased(MouseEvent event)
{
behaviorManager.fireOnMouseReleased(event);
}
public void mouseClicked(MouseEvent event)
{
behaviorManager.fireOnMouseClicked(event);
}
});
addMouseWheelListener(new MouseWheelListener()
{
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
behaviorManager.fireOnMouseWheelMoved(e);
}
});
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent event)
{
behaviorManager.fireOnMouseDragged(event);
}
@Override
public void mouseMoved(MouseEvent event)
{
behaviorManager.fireOnMouseMoved(event);
}
});
setBounds(0, 0, 0, 0);
setDoubleBuffered(false);
}
/*
* (non-Javadoc)
*
* @see com.horstmann.violet.framework.display.clipboard.IEditorPart#getGraph()
*/
public IGraph getGraph()
{
return this.graph;
}
/*
* (non-Javadoc)
*
* @see com.horstmann.violet.framework.display.clipboard.IEditorPart#removeSelected()
*/
public void removeSelected()
{
this.behaviorManager.fireBeforeRemovingSelectedElements();
try
{
List<INode> selectedNodes = selectionHandler.getSelectedNodes();
List<IEdge> selectedEdges = selectionHandler.getSelectedEdges();
IEdge[] edgesArray = selectedEdges.toArray(new IEdge[selectedEdges.size()]);
INode[] nodesArray = selectedNodes.toArray(new INode[selectedNodes.size()]);
graph.removeNode(nodesArray);
graph.removeEdge(edgesArray);
}
finally
{
this.selectionHandler.clearSelection();
this.behaviorManager.fireAfterRemovingSelectedElements();
}
}
public List<INode> getSelectedNodes()
{
return selectionHandler.getSelectedNodes();
}
public void clearSelection()
{
selectionHandler.clearSelection();
}
public void selectElement(INode node)
{
selectionHandler.addSelectedElement(node);
}
@Override
public Dimension getPreferredSize()
{
Dimension parentSize = getParent().getSize();
Rectangle2D bounds = graph.getClipBounds();
int width = Math.max((int) (zoom * bounds.getMaxX()), (int) parentSize.getWidth());
int height = Math.max((int) (zoom * bounds.getMaxY()), (int) parentSize.getHeight());
if (this.lastWidth != width || this.lastHeight != height) {
this.lastWidth = width;
this.lastHeight = height;
}
return new Dimension(width, height);
}
/*
* (non-Javadoc)
*
* @see com.horstmann.violet.framework.display.clipboard.IEditorPart#changeZoom(int)
*/
public void changeZoom(int steps)
{
final double FACTOR = Math.sqrt(Math.sqrt(2));
for (int i = 1; i <= steps; i++)
zoom *= FACTOR;
for (int i = 1; i <= -steps; i++)
zoom /= FACTOR;
invalidate();
repaint();
}
@Override
public double getZoomFactor()
{
return this.zoom;
}
/*
* (non-Javadoc)
*
* @see com.horstmann.violet.product.workspace.editorpart.IEditorPart#getGrid()
*/
public IGrid getGrid()
{
return this.grid;
}
/*
* (non-Javadoc)
*
* @seecom.horstmann.violet.framework.workspace.editorpart.IEditorPart# growDrawingArea()
*/
public void growDrawingArea()
{
IGraph g = getGraph();
Rectangle2D bounds = g.getClipBounds();
bounds.add(getBounds());
g.setBounds(new Double(0, 0, GROW_SCALE_FACTOR * bounds.getWidth(), GROW_SCALE_FACTOR * bounds.getHeight()));
invalidate();
repaint();
}
/*
* (non-Javadoc)
*
* @seecom.horstmann.violet.framework.workspace.editorpart.IEditorPart# clipDrawingArea()
*/
public void clipDrawingArea()
{
IGraph g = getGraph();
g.setBounds(null);
invalidate();
repaint();
}
public JComponent getSwingComponent()
{
return this;
}
@Override
public void paintImmediately(int x, int y, int w, int h)
{
getSwingComponent().invalidate();
super.paintImmediately(x, y, w, h);
}
@Override
protected void paintComponent(Graphics g)
{
boolean valid = getSwingComponent().isValid();
if (valid)
{
return;
}
getSwingComponent().revalidate(); // to inform parent scrollpane container
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
if (grid.isVisible()) grid.paint(g2);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graph.draw(g2);
for (IEditorPartBehavior behavior : this.behaviorManager.getBehaviors())
{
behavior.onPaint(g2);
}
}
@Override
public IEditorPartSelectionHandler getSelectionHandler()
{
return this.selectionHandler;
}
@Override
public IEditorPartBehaviorManager getBehaviorManager()
{
return this.behaviorManager;
}
private IGraph graph;
private IGrid grid;
private double zoom;
private IEditorPartSelectionHandler selectionHandler = new EditorPartSelectionHandler();
private int lastWidth = 0;
private int lastHeight = 0;
/**
* Scale factor used to grow drawing area
*/
private static final double GROW_SCALE_FACTOR = Math.sqrt(2);
private IEditorPartBehaviorManager behaviorManager = new EditorPartBehaviorManager();
}