blob: b2565dadef39c262970f84881144eb5a1019b0c2 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2003, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Mariot Chauvin <mariot.chauvin@obeo.fr> - bug 259507
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui.figures;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.DelegatingLayout;
import org.eclipse.draw2d.IClippingStrategy;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutAnimator;
import org.eclipse.draw2d.TreeSearch;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gmf.runtime.diagram.ui.internal.figures.BorderItemContainerFigure;
import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
/**
* Wrapper figure that contains the main figure and the border item figures.
* This is required to allow the main figure's layout manager to ignore the
* border items. The border item container applies a delegating layout manager
* to allow border item children to lay themselves out.
*
* @author jbruck, cmahoney, mmostafa
*/
public class BorderedNodeFigure
extends NodeFigure implements IExpandableFigure{
private BorderItemContainerFigure borderItemContainer;
private IFigure mainFigure;
private Rectangle extendedBounds = new Rectangle();
/**
* Creates a new BorderedNodeFigure figure.
*
* @param mainFigure
* the figure to use with this figure
*/
public BorderedNodeFigure(IFigure mainFigure) {
super();
setOpaque(false); // set transparent by default
setBorder(null);
setLayoutManager(null);
this.mainFigure = mainFigure;
add(getMainFigure());
add(getBorderItemContainer());
setBounds(getMainFigure().getBounds().getCopy());
getBorderItemContainer().setBounds(new Rectangle(0, 0, 1, 1));
setClippingStrategy(new BorderItemClippingStrategy());
}
/**
* Gets the border item container figure to which border item figures can be
* added with a {@link IBorderItemLocator} as the constraint and then later
* removed.
*
* @return The border item container figure
*/
public IFigure getBorderItemContainer() {
if (borderItemContainer == null) {
borderItemContainer = new BorderItemContainerFigure();
borderItemContainer
.setLayoutManager(new DelegatingLayout());
borderItemContainer.addLayoutListener(LayoutAnimator.getDefault());
borderItemContainer.setVisible(true);
}
return borderItemContainer;
}
/**
* Gets the main figure of this bordered figure.
*
* @return The "main" figure
*/
public IFigure getMainFigure() {
return mainFigure;
}
public Rectangle getClientArea(Rectangle rect) {
if (getMainFigure() != null) {
return getMainFigure().getClientArea(rect);
}
return super.getClientArea(rect);
}
/**
* gets the handle bounds of the main figure
*
* @return the hnalde bounds
*/
public Rectangle getHandleBounds() {
if (getMainFigure() instanceof NodeFigure) {
return ((NodeFigure) getMainFigure()).getHandleBounds().getCopy();
} else {
return getMainFigure().getBounds().getCopy();
}
}
/**
* Give the main figure the entire bounds of the wrapper.
*/
protected void layout() {
if (!this.getBounds().equals(getMainFigure().getBounds())) {
getMainFigure().setBounds(this.getBounds().getCopy());
getBorderItemContainer().invalidateTree();
erase();
}
}
/**
* We need to override this for smooth painting of border items.
*/
public boolean containsPoint(int x, int y) {
if (borderItemContainer.containsPoint(x, y)) {
return true;
}
return super.containsPoint(x, y);
}
protected void primTranslate(int dx, int dy) {
super.primTranslate(dx, dy);
erase();
}
public void erase() {
super.erase();
if (borderItemContainer != null)
borderItemContainer.erase();
}
/**
* Refresh adornments
*/
public void repaint() {
super.repaint();
if (borderItemContainer != null)
borderItemContainer.repaint();
}
public IFigure findFigureAt(int x, int y, TreeSearch search) {
if (search.prune(this))
return null;
IFigure result = borderItemContainer.findFigureAt(x, y, search);
if (result != null) {
return result;
}
return getMainFigure().findFigureAt(x, y, search);
}
public IFigure findMouseEventTargetAt(int x, int y) {
IFigure borderItemFigure = borderItemContainer.findMouseEventTargetAt(
x, y);
if (borderItemFigure != null)
return borderItemFigure;
return super.findMouseEventTargetAt(x, y);
}
public boolean intersects(Rectangle rect) {
if (getExtendedBounds().intersects(rect))
return true;
return super.intersects(rect);
}
public Dimension getMinimumSize(int wHint, int hHint) {
return getMainFigure().getMinimumSize(wHint, hHint);
}
public Dimension getPreferredSize(int wHint, int hHint) {
return getMainFigure().getPreferredSize(wHint, hHint);
}
public IFigure getToolTip() {
return getMainFigure().getToolTip();
}
public void setToolTip(IFigure f) {
getMainFigure().setToolTip(f);
}
public ConnectionAnchor getSourceConnectionAnchorAt(Point p) {
if (getMainFigure() instanceof NodeFigure)
return ((NodeFigure) getMainFigure())
.getSourceConnectionAnchorAt(p);
return super.getSourceConnectionAnchorAt(p);
}
public ConnectionAnchor getTargetConnectionAnchorAt(Point p) {
if (getMainFigure() instanceof NodeFigure)
return ((NodeFigure) getMainFigure())
.getTargetConnectionAnchorAt(p);
return super.getTargetConnectionAnchorAt(p);
}
public ConnectionAnchor getConnectionAnchor(String terminal) {
if (getMainFigure() instanceof NodeFigure)
return ((NodeFigure) getMainFigure()).getConnectionAnchor(terminal);
return super.getConnectionAnchor(terminal);
}
public String getConnectionAnchorTerminal(ConnectionAnchor c) {
if (getMainFigure() instanceof NodeFigure)
return ((NodeFigure) getMainFigure())
.getConnectionAnchorTerminal(c);
return super.getConnectionAnchorTerminal(c);
}
/**
* This method provides a generic way to get a target figure's parent's main
* figure where if the target figure is a border item figure, then its
* parent is considered the figure on which it borders.It is not possible to
* get a target figure's parent using <code>IFigure#getParent()</code> if
* the target figure is a border item figure, since this would return the
* border item container figure.
*
* @param target
* the target figure, may or may not be acting as a border item
* figure
* @return the parent figure or if the target figure was on a border item
* container figure, then the main figure that it borders.
*/
public static IFigure getParentFigure(IFigure target) {
IFigure parent = target.getParent();
if (parent instanceof BorderItemContainerFigure) {
return ((BorderedNodeFigure) parent.getParent()).getMainFigure();
}
return parent;
}
public Rectangle getExtendedBounds() {
if (extendedBounds == null) {
Rectangle rect = getBounds().getCopy();
if (borderItemContainer!=null){
rect = rect.union(borderItemContainer.getExtendedBounds());
}
extendedBounds = rect;
}
return extendedBounds;
}
@Override
public void invalidate() {
extendedBounds = null;
super.invalidate();
}
@Override
public void validate() {
extendedBounds = null;
super.validate();
}
@Override
protected void fireFigureMoved() {
super.fireFigureMoved();
extendedBounds = null;
}
private class BorderItemClippingStrategy implements IClippingStrategy {
public Rectangle[] getClip(IFigure childFigure) {
if (childFigure == borderItemContainer) {
return new Rectangle[] {borderItemContainer.getExtendedBounds()};
}
return new Rectangle[] {childFigure.getBounds()};
}
}
}