/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.decorations; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Rectangle; import org.xmind.gef.draw2d.decoration.ICorneredDecoration; import org.xmind.gef.draw2d.geometry.Geometry; import org.xmind.gef.draw2d.graphics.Path; import org.xmind.ui.decorations.AbstractTopicDecoration; public class RoundedRectCalloutTopicDecoration extends AbstractTopicDecoration implements ICorneredDecoration { private static final double M = 1 - Math.sqrt(2) / 2; private static final float X = 0.2f; private int cornerSize = 0; public RoundedRectCalloutTopicDecoration() { } public RoundedRectCalloutTopicDecoration(String id) { super(id); } protected void sketch(IFigure figure, Path shape, Rectangle box, int purpose) { float x = box.x; float y = box.y; float width = box.width; float height = box.height; float tailHeight = getTailHeight( figure.getBounds().height - figure.getInsets().getHeight()); height -= tailHeight; float r = x + width; float b = y + height; float x0 = x + width / 2; float y0 = y + height / 2; float corner = getAppliedCornerSize(); float x1 = Math.min(x + corner, x0); shape.moveTo(x1, y); float y1 = Math.min(y + corner, y0); float cx1 = x + (x1 - x) / 4; float cy1 = y + (y1 - y) / 4; shape.cubicTo(cx1, y, x, cy1, x, y1); float y2 = Math.max(b - corner, y0); shape.lineTo(x, y2); float cy2 = b - (b - y2) / 4; shape.cubicTo(x, cy2, cx1, b, x1, b); shape.lineTo(x, b + tailHeight); shape.lineTo(x + width * X, b); float x2 = Math.max(r - corner, x0); shape.lineTo(x2, b); float cx2 = r - (r - x2) / 4; shape.cubicTo(cx2, b, r, cy2, r, y2); shape.lineTo(r, y1); shape.cubicTo(r, cy1, cx2, y, x2, y); // float y1 = Math.min(y + corner, y0); // shape.moveTo(x, y1); // // float x1 = Math.min(x + corner, x0); // float cx1 = x + (x1 - x) / 4; // float cy1 = y + (y1 - y) / 4; // shape.cubicTo(x, cy1, cx1, y, x1, y); // // float x2 = Math.max(r - corner, x0); // shape.lineTo(x2, y); // // float cx2 = r - (r - x2) / 4; // shape.cubicTo(cx2, y, r, cy1, r, y1); // // float y2 = Math.max(b - corner, y0); // shape.lineTo(r, y2); // // float cy2 = b - (b - y2) / 4; // shape.cubicTo(r, cy2, cx2, b, x2, b); // // shape.lineTo(x + width * X, b); // shape.lineTo(x, b + tailHeight); // shape.lineTo(x1, b); // // shape.cubicTo(cx1, b, x, cy2, x, y2); shape.close(); } public Insets getPreferredInsets(IFigure figure, int width, int height) { int c = (int) (M * getAppliedCornerSize()) + getLineWidth(); Insets ins = super.getPreferredInsets(figure, width, height); ins = Geometry.union(ins, c, c, c, c); ins.bottom += getTailHeight(height); return ins; } private int getTailHeight(int clientHeight) { return clientHeight / 3; } public int getCornerSize() { return cornerSize; } protected int getAppliedCornerSize() { return getCornerSize();// * getLineWidth(); } public void setCornerSize(IFigure figure, int cornerSize) { if (cornerSize == this.cornerSize) return; this.cornerSize = cornerSize; invalidate(); if (figure != null) { figure.revalidate(); figure.repaint(); } } }