/******************************************************************************* * Copyright (c) 2009-2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Paul Klint - Paul.Klint@cwi.nl - CWI *******************************************************************************/ package org.rascalmpl.eclipse.library.vis.figure.compose; import static org.rascalmpl.eclipse.library.vis.properties.Properties.HCONNECT; import static org.rascalmpl.eclipse.library.vis.properties.Properties.SHAPE_CLOSED; import static org.rascalmpl.eclipse.library.vis.properties.Properties.SHAPE_CONNECTED; import static org.rascalmpl.eclipse.library.vis.properties.Properties.SHAPE_CURVED; import static org.rascalmpl.eclipse.library.vis.properties.Properties.VCONNECT; import static org.rascalmpl.eclipse.library.vis.properties.TwoDProperties.ALIGN; import static org.rascalmpl.eclipse.library.vis.properties.TwoDProperties.POS; import static org.rascalmpl.eclipse.library.vis.properties.TwoDProperties.SHRINK; import static org.rascalmpl.eclipse.library.vis.util.vector.Dimension.HOR_VER; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import org.rascalmpl.eclipse.library.vis.figure.Figure; import org.rascalmpl.eclipse.library.vis.figure.interaction.MouseOver; import org.rascalmpl.eclipse.library.vis.graphics.GraphicsContext; import org.rascalmpl.eclipse.library.vis.graphics.Interpolation; /** * * Overlay elements by stacking them * * @author paulk * */ import org.rascalmpl.eclipse.library.vis.graphics.TypedPoint; import org.rascalmpl.eclipse.library.vis.properties.PropertyManager; import org.rascalmpl.eclipse.library.vis.swt.IFigureConstructionEnv; import org.rascalmpl.eclipse.library.vis.swt.applet.IHasSWTElement; import org.rascalmpl.eclipse.library.vis.util.FigureMath; import org.rascalmpl.eclipse.library.vis.util.NameResolver; import org.rascalmpl.eclipse.library.vis.util.vector.Coordinate; import org.rascalmpl.eclipse.library.vis.util.vector.Dimension; import org.rascalmpl.eclipse.library.vis.util.vector.Rectangle; public class Overlay extends Compose{ public Overlay(Figure[] children, PropertyManager properties) { super(children, properties); } @Override public boolean initChildren(IFigureConstructionEnv env, NameResolver resolver, MouseOver mparent, boolean swtSeen, boolean visible) { for(int i = 0; i < children.length ; i++){ if(swtSeen){ env.addAboveSWTElement(children[i]); } swtSeen = swtSeen || children[i].init(env, resolver,mparent, swtSeen, visible); } return swtSeen; } @Override public void computeMinSize() { minSize.set(0,0); for(Figure fig : children){ for(Dimension d : HOR_VER){ if(fig.prop.is2DPropertySet(d, POS)){ minSize.setMax(d, (fig.prop.get2DReal(d, POS) + (1.0 - fig.prop.get2DReal(d, ALIGN)) * fig.prop.get2DReal(d, SHRINK)) * fig.minSize.get(d)); minSize.setMax(d, fig.minSize.get(d) ); } else { minSize.setMax(d, fig.minSize.get(d) / fig.prop.get2DReal(d, SHRINK)); } } } } @Override public void resizeElement(Rectangle view) { for(Figure fig : children){ for(Dimension d : HOR_VER){ fig.size.set(d,size.get(d)*fig.prop.get2DReal(d, SHRINK)); if(fig.prop.is2DPropertySet(d, POS)){ fig.localLocation.set(d,size.get(d) * (fig.prop.get2DReal(d, POS) - fig.prop.get2DReal(d,ALIGN) * fig.prop.get2DReal(d, SHRINK))); } else { fig.localLocation.set(d,(size.get(d) - fig.size.get(d)) * fig.prop.get2DReal(d, ALIGN)); } } } } @Override public void getFiguresUnderMouse(Coordinate c,List<Figure> result){ if(!mouseInside(c)){ return; } if(handlesInput()){ Point2D.Double d = new Point2D.Double(c.getX(), c.getY()); if(makePath().contains(d)){ result.add(this); } } for(int i = children.length - 1 ; i >= 0 ; i--){ children[i].getFiguresUnderMouse(c, result); } } public Path2D.Double makePath(){ boolean closed = prop.getBool(SHAPE_CLOSED); boolean curved = prop.getBool(SHAPE_CURVED); boolean connected = prop.getBool(SHAPE_CONNECTED) || closed || curved; Path2D.Double p = new Path2D.Double(); if(connected && closed && children.length >= 0){ if(curved) { ArrayList<TypedPoint> res = new ArrayList<TypedPoint>(); for(int i = 0 ; i < children.length ; i++){ res.add(new TypedPoint(children[i].globalLocation.getX() + children[i].prop.getReal(HCONNECT) * children[i].size.getX(), children[i].globalLocation.getY() + children[i].prop.getReal(VCONNECT) * children[i].size.getY(),TypedPoint.kind.CURVED)); } Interpolation.solve(res, true); p.moveTo(Interpolation.P0[0].x, Interpolation.P0[0].y); int n = Interpolation.P0.length; for (int i = 0; i < n; i++) p.curveTo( Interpolation.P1[i].x, Interpolation.P1[i].y, Interpolation.P2[i].x, Interpolation.P2[i].y, Interpolation.P3[i].x, Interpolation.P3[i].y); } else{ p.moveTo(children[0].globalLocation.getX() + children[0].prop.getReal(HCONNECT) * children[0].size.getX(), children[0].globalLocation.getY() + children[0].prop.getReal(VCONNECT) * children[0].size.getY()); for(int i = 0 ; i < children.length ; i++){ p.lineTo(children[i].globalLocation.getX() + children[i].prop.getReal(HCONNECT) * children[i].size.getX(), children[i].globalLocation.getY() + children[i].prop.getReal(VCONNECT) * children[i].size.getY()); } } p.closePath(); } return p; } @Override public void drawElement(GraphicsContext gc, List<IHasSWTElement> visibleSWTElements){ boolean closed = prop.getBool(SHAPE_CLOSED); boolean curved = prop.getBool(SHAPE_CURVED); boolean connected = prop.getBool(SHAPE_CONNECTED) || closed || curved; if(connected){ gc.beginShape(); } if(!closed){ gc.noFill(); } if(closed && connected && children.length >= 0){ gc.vertex( children[0].globalLocation.getX() + children[0].prop.getReal(HCONNECT) * children[0].size.getX(), children[0].globalLocation.getY() + children[0].prop.getReal(VCONNECT) * children[0].size.getY() ); } if(connected){ for(int i = 0 ; i < children.length ; i++){ if(curved ){ gc.curveVertex( children[i].globalLocation.getX() + children[i].prop.getReal(HCONNECT) * children[i].size.getX(), children[i].globalLocation.getY() + children[i].prop.getReal(VCONNECT) * children[i].size.getY() ); } else { gc.vertex(children[i].globalLocation.getX() + children[i].prop.getReal(HCONNECT) * children[i].size.getX(), children[i].globalLocation.getY() + children[i].prop.getReal(VCONNECT) * children[i].size.getY() ); } //System.out.printf("child %s\n",children[i].globalLocation); } } if(connected){ if(closed){ int i = children.length-1; gc.vertex(children[i].globalLocation.getX() + children[i].prop.getReal(HCONNECT) * children[i].size.getX(), children[i].globalLocation.getY() + children[i].prop.getReal(VCONNECT) * children[i].size.getY() ); gc.endShape(FigureMath.CLOSE); } else gc.endShape(); } } public String toString(){ return "Overlay: " + super.toString(); } }