/*
* EventNodeFigure.java
*
* This file is part of the STS-Tool project.
* Copyright (c) 2011-2012 "University of Trento - DISI" All rights reserved.
*
* Is strictly forbidden to remove this copyright notice from this source code.
*
* Disclaimer of Warranty:
* STS-Tool (this software) is provided "as-is" and without warranty of any kind,
* express, implied or otherwise, including without limitation, any warranty of
* merchantability or fitness for a particular purpose.
* In no event shall the copyright holder or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused and on
* any theory of liability, whether in contract, strict liability, or tort (including
* negligence or otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* "University of Trento - DISI","University of Trento - DISI" DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://www.sts-tool.eu/License.php
*
* For more information, please contact STS-Tool group at this
* address: ststool@disi.unitn.it
*
*/
package eu.aniketos.wp1.ststool.diagram.custom.figure.nodes;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
import org.eclipse.swt.graphics.Color;
import eu.aniketos.wp1.ststool.diagram.custom.figure.ISTSErrorMarker;
import eu.aniketos.wp1.ststool.diagram.custom.figure.STSErrorType;
import eu.aniketos.wp1.ststool.diagram.custom.figure.StsWrappingLabel;
public class EventNodeFigure extends RectangleFigure implements ISTSErrorMarker {
public final static Dimension THIS_DIMENSION = new Dimension(90, 60);
private final static int TRIANGLE_HEIGHT = 24;
private final static int TRIANGLE_WIDTH = 30;
private StsWrappingLabel nameLabel;
private Triangle t;
public EventNodeFigure() {
super();
setFill(false);
setOutline(false);
ToolbarLayout layout = new ToolbarLayout(false);
layout.setSpacing(0);
layout.setMinorAlignment(ToolbarLayout.ALIGN_CENTER);
super.setLayoutManager(layout);
t = new Triangle();
t.setSize(TRIANGLE_WIDTH, TRIANGLE_HEIGHT);
t.setPreferredSize(TRIANGLE_WIDTH, TRIANGLE_HEIGHT);
add(t);
super.setMinimumSize(THIS_DIMENSION);
super.setPreferredSize(THIS_DIMENSION);
super.setMaximumSize(THIS_DIMENSION);
super.setSize(THIS_DIMENSION);
}
private void initLabel(){
nameLabel = new StsWrappingLabel("<Event...>");
nameLabel.setAlignment(PositionConstants.CENTER);
nameLabel.setTextWrap(true);
add(nameLabel);
}
public WrappingLabel getNameLabel(){
if (nameLabel == null) initLabel();
return nameLabel;
}
@Override
public IFigure getToolTip(){
if (nameLabel != null) {
Label result = new Label(nameLabel.getText());
return result;
}
return null;
}
@Override
public void setBackgroundColor(Color bg){
//super.setBackgroundColor(THIS_BACK);
}
@Override
public void setForegroundColor(Color fg){
//super.setForegroundColor(THIS_FORE);
}
@Override
public void setPreferredSize(Dimension size){
// TODO Auto-generated method stub
//super.setPreferredSize(size);
}
@Override
public void setLayoutManager(LayoutManager manager){
}
@Override
public Dimension getMaximumSize(){
// TODO Auto-generated method stub
return THIS_DIMENSION;
}
@Override
public Dimension getMinimumSize(int wHint,int hHint){
return THIS_DIMENSION;
}
@Override
public Dimension getPreferredSize(int wHint,int hHint){
return THIS_DIMENSION;
}
@Override
public void setError(STSErrorType errorType){
switch (errorType) {
case NO_ERROR:
super.setForegroundColor(ColorConstants.black);
break;
case WARNING:
super.setForegroundColor(ColorConstants.orange);
break;
case ERROR:
super.setForegroundColor(ColorConstants.red);
break;
}
}
public ConnectionAnchor getConnectionAnchor(){
return new ChopboxAnchor(t) {
@Override
public Point getLocation(Point ref){
Point p = intersection(ref);
if (p == null) {
Rectangle b = nameLabel.getBounds().getCopy();
t.translateToAbsolute(b);
p = b.getBottom().getCopy();
}
return p;
}
private Point intersection(Point ref){
Point center = t.getBounds().getCenter().getCopy();
t.translateToAbsolute(center);
if (center.x == ref.x && center.y < ref.y) return null;
PointList line = new PointList(3);
Point bottomLeft = t.getBounds().getBottomLeft().getCopy();
t.translateToAbsolute(bottomLeft);
line.addPoint(bottomLeft);
Point topCenter = t.getBounds().getTop().getCopy();
t.translateToAbsolute(topCenter);
line.addPoint(topCenter);
Point bottomRight = t.getBounds().getBottomRight().getCopy();
t.translateToAbsolute(bottomRight);
line.addPoint(bottomRight);
Point result = null;
for (int i = 0; i < line.size() - 1 && result == null; i++) {
result = intersection(center, ref, line.getPoint(i), line.getPoint(i + 1));
}
return result;
}
public Point intersection(Point p1,Point p2,Point p3,Point p4){
return intersection(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
}
/**
* Computes the intersection between two lines.
*
* @param x1
* Point 1 of Line 1
* @param y1
* Point 1 of Line 1
* @param x2
* Point 2 of Line 1
* @param y2
* Point 2 of Line 1
* @param x3
* Point 1 of Line 2
* @param y3
* Point 1 of Line 2
* @param x4
* Point 2 of Line 2
* @param y4
* Point 2 of Line 2
* @return Point where the segments intersect, or null if they don't
*/
public Point intersection(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (d == 0) return null;
double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
Point p = new Point((int) xi, (int) yi);
if (xi < Math.min(x1, x2) || xi > Math.max(x1, x2)) return null;
if (xi < Math.min(x3, x4) || xi > Math.max(x3, x4)) return null;
return p;
}
};
}
@SuppressWarnings("unused")
private class Triangle extends Shape {
private Triangle() {
setForegroundColor(ColorConstants.white);
setBackgroundColor(ColorConstants.red);
setLineWidth(2);
}
PointList pointlist = new PointList(3);
Rectangle lastBounds;
@Override
protected void fillShape(Graphics g){
if (lastBounds == null || !lastBounds.equals(getBounds())) {
lastBounds = getBounds().getCopy();
pointlist.removeAllPoints();
pointlist.addPoint(lastBounds.getBottomLeft().getCopy());
pointlist.addPoint(lastBounds.getTopLeft().x + (lastBounds.getSize().width / 2), lastBounds.getTopLeft().y);
pointlist.addPoint(lastBounds.getBottomRight().getCopy());
}
g.fillPolygon(pointlist);
}
@Override
protected void outlineShape(Graphics g){
Rectangle bounds = getBounds().getCopy();
final int thunderWidth = 3;
final int thunderHeight = 6;
int midX = bounds.getTopLeft().x + (bounds.getSize().width / 2);
int midY = bounds.getTopLeft().y + (bounds.getSize().height / 2) + 2;
g.drawLine(new Point(midX + (thunderWidth), midY - (thunderHeight)), new Point(midX - (thunderWidth), midY));
g.drawLine(new Point(midX - (thunderWidth), midY), new Point(midX + (thunderWidth), midY));
g.drawLine(new Point(midX + (thunderWidth), midY), new Point(midX - (thunderWidth), midY + thunderHeight));
}
public Point getTop(){
Point p = pointlist.getPoint(2);
translateToAbsolute(p);
return p;
}
public Point getBottomLeft(){
Point p = pointlist.getPoint(2);
translateToAbsolute(p);
return p;
}
public Point getBottomRight(){
Point p = pointlist.getPoint(2);
translateToAbsolute(p);
return p;
}
}
}