/* ******************************************************************************
* 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.gef.draw2d;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.xmind.gef.draw2d.geometry.Geometry;
public class ReferencedLayer extends FreeformLayer implements IReferencedFigure {
private IReferenceDescriptor referenceDescriptor = null;
private Insets refDesc = null;
private Point reference = null;
private Point lastReference = null;
public int getOrientation() {
return Geometry.getOrientation(getReference(), getOrigin());
}
public Rectangle getPreferredBounds(Point reference) {
return Geometry.getExpanded(reference, getReferenceDescription());
}
public Rectangle getPreferredBounds(Rectangle rect, Point reference) {
Insets ins = getReferenceDescription();
rect.setLocation(reference.x - ins.left, reference.y - ins.top);
rect.setSize(ins.getWidth(), ins.getHeight());
return rect;
}
public Rectangle getPreferredClientArea(Point reference) {
if (getLayoutManager() instanceof IReferencedLayout) {
Rectangle area = ((IReferencedLayout) getLayoutManager())
.getPreferredClientArea(this);
return area.getTranslated(reference);
}
return new Rectangle(0, 0, 0, 0);
}
public Point getReference() {
if (reference == null) {
reference = calculateReference(getBounds());
lastReference = reference;
}
return reference;
}
protected Point calculateReference(Rectangle bounds) {
Insets ins = getReferenceDescription();
int insWidth = ins.getWidth();
int insHeight = ins.getHeight();
int x = bounds.x;
int y = bounds.y;
if (bounds.width == insWidth) {
x += ins.left;
} else if (insWidth > 0) {
x += bounds.width * ins.left / insWidth;
}
if (bounds.height == insHeight) {
y += ins.top;
} else if (insHeight > 0) {
y += bounds.height * ins.top / insHeight;
}
return new Point(x, y);
}
public Insets getReferenceDescription() {
if (refDesc != null)
return refDesc;
IReferenceDescriptor descriptor = getReferenceDescriptor();
if (descriptor != null) {
refDesc = descriptor.getReferenceDescription(this);
}
if (refDesc == null) {
refDesc = calculateDefaultReferenceDescription(getPreferredSize());
}
return refDesc;
}
protected Insets calculateDefaultReferenceDescription(
Dimension preferredSize) {
int h = preferredSize.height / 2;
int w = preferredSize.width / 2;
return new Insets(h, w, preferredSize.height - h, preferredSize.width
- w);
}
public IReferenceDescriptor getReferenceDescriptor() {
return referenceDescriptor;
}
public void setReference(Point reference) {
if (reference != null)
setReference(reference.x, reference.y);
}
public void setReference(int referenceX, int referenceY) {
setLocation(calculateLocation(referenceX, referenceY));
}
protected Point calculateLocation(int refX, int refY) {
int width = bounds.width;
int height = bounds.height;
Insets ins = getReferenceDescription();
int insWidth = ins.getWidth();
int insHeight = ins.getHeight();
if (width == insWidth) {
refX -= ins.left;
} else if (insWidth > 0) {
refX -= width * ins.left / insWidth;
}
if (height == insHeight) {
refY -= ins.top;
} else if (insHeight > 0) {
refY -= height * ins.top / insHeight;
}
return new Point(refX, refY);
}
public void setReferenceDescriptor(IReferenceDescriptor descriptor) {
if (descriptor == this.referenceDescriptor)
return;
this.referenceDescriptor = descriptor;
revalidate();
}
public Point getOrigin() {
IOriginBased originBased = getOriginBasedAncestor(this);
if (originBased != null)
return originBased.getOrigin();
return getReference();
}
private IOriginBased getOriginBasedAncestor(IFigure fig) {
IFigure parent = fig.getParent();
if (parent == null)
return null;
if (parent instanceof IOriginBased)
return (IOriginBased) parent;
return getOriginBasedAncestor(parent);
}
public void invalidate() {
refDesc = null;
reference = null;
super.invalidate();
}
/*
* (non-Javadoc)
*
* @see org.xmind.gef.draw2d.IReferencedFigure#getLastReference()
*/
public Point getLastReference() {
if (lastReference == null) {
lastReference = getReference();
}
return lastReference;
}
}