Newer
Older
piccolo2d.java / extras / edu / umd / cs / piccolox / nodes / P3DRect.java
@Jesse Grosjean Jesse Grosjean on 5 Oct 2006 5 KB piccolo java
/*
 * Copyright (c) 2002-@year@, University of Maryland
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions
 * and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 * and the following disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the University of Maryland nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
 *
 * Piccolo was written at the Human-Computer Interaction Laboratory www.cs.umd.edu/hcil by Jesse Grosjean
 * under the supervision of Ben Bederson. The Piccolo website is www.cs.umd.edu/hcil/piccolo.
 */
package edu.umd.cs.piccolox.nodes;

import java.awt.*;
import java.awt.geom.*;
import edu.umd.cs.piccolo.*;
import edu.umd.cs.piccolo.util.*;
import edu.umd.cs.piccolox.*;

/**
 * This is a simple node that draws a "3D" rectangle within the bounds of the node.
 * Drawing a 3D rectangle in a zooming environment is a little tricky because
 * if you just use the regular (Java2D) 3D rectangle, the 3D borders get scaled,
 * and that is ugly.  This version always draws the 3D border at fixed 2 pixel width.
 * 
 * @author Ben Bederson
 */
public class P3DRect extends PNode {

	private Color topLeftOuterColor;
	private Color topLeftInnerColor;
	private Color bottomRightInnerColor;
	private Color bottomRightOuterColor;
	private GeneralPath path;
	private Stroke stroke;
	private boolean raised;
	
	public P3DRect() {
		raised = true;
		stroke = new BasicStroke(0);
		path = new GeneralPath();
	}
	
	public P3DRect(Rectangle2D bounds) {
		this(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
	}
	
	public P3DRect(double x, double y, double width, double height) {
		this();
		setBounds(x, y, width, height);
	}
	
	public void setRaised(boolean raised) {
		this.raised = raised;
		setPaint(getPaint());
	}
	
	public boolean getRaised() {
		return raised;
	}
	
	protected void paint(PPaintContext paintContext) {
		Graphics2D g2 = paintContext.getGraphics();
				
		double x = getX();
		double y = getY();
		double width = getWidth();
		double height = getHeight();
		double magX = g2.getTransform().getScaleX();
		double magY = g2.getTransform().getScaleY();
		double dx = (float)(1.0 / magX);
		double dy = (float)(1.0 / magY);
		PBounds bounds = getBounds();
		
		g2.setPaint(getPaint());
		g2.fill(bounds);
		g2.setStroke(stroke);	

		path.reset();
		path.moveTo((float)(x+width), (float)y);
		path.lineTo((float)x, (float)y);
		path.lineTo((float)x, (float)(y+height));
		g2.setPaint(topLeftOuterColor);
		g2.draw(path);

		path.reset();
		path.moveTo((float)(x+width), (float)(y+dy));
		path.lineTo((float)(x+dx), (float)(y+dy));
		path.lineTo((float)(x+dx), (float)(y+height));
		g2.setPaint(topLeftInnerColor);
		g2.draw(path);

		path.reset();
		path.moveTo((float)(x+width), (float)(y));
		path.lineTo((float)(x+width), (float)(y+height));
		path.lineTo((float)(x), (float)(y+height));
		g2.setPaint(bottomRightOuterColor);
		g2.draw(path);

		path.reset();
		path.moveTo((float)(x+width-dx), (float)(y+dy));
		path.lineTo((float)(x+width-dx), (float)(y+height-dy));
		path.lineTo((float)(x), (float)(y+height-dy));
		g2.setPaint(bottomRightInnerColor);
		g2.draw(path);
	}	

	public void setPaint(Paint newPaint) {
		super.setPaint(newPaint);
		
		if (newPaint instanceof Color) {
			Color color = (Color)newPaint;
			
			if (raised) {
				topLeftOuterColor = color.brighter();
				topLeftInnerColor = topLeftOuterColor.brighter();
				bottomRightInnerColor = color.darker();
				bottomRightOuterColor = bottomRightInnerColor.darker();
			} else {
				topLeftOuterColor = color.darker();
				topLeftInnerColor = topLeftOuterColor.darker();
				bottomRightInnerColor = color.brighter();
				bottomRightOuterColor = bottomRightInnerColor.brighter();			
			}
		} else {
			topLeftOuterColor = null;
			topLeftInnerColor = null;
			bottomRightInnerColor = null;
			bottomRightOuterColor = null;
		}
	}

	public static void main(String[] args) {
		new PFrame() {
			public void initialize() {
				getCanvas().setDefaultRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);

				P3DRect rect1 = new P3DRect(50, 50, 100, 100);
				rect1.setPaint(new Color(239, 235, 222));

				P3DRect rect2 = new P3DRect(50, 50, 100, 100);
				rect2.setPaint(new Color(239, 235, 222));
				rect2.translate(110, 0);
				rect2.setRaised(false);
				
				getCanvas().getLayer().addChild(rect1);
				getCanvas().getLayer().addChild(rect2);
			}
		};
	}
}