/* ****************************************************************************** * 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.layouts; import java.util.List; 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.core.IImage; import org.xmind.gef.draw2d.IMinimizable; import org.xmind.gef.draw2d.IRotatableFigure; import org.xmind.gef.draw2d.IRotatableReferenceDescriptor; import org.xmind.gef.draw2d.IRotatableReferencedLayout; import org.xmind.gef.draw2d.ReferencedLayoutData; import org.xmind.gef.draw2d.geometry.PrecisionDimension; import org.xmind.gef.draw2d.geometry.PrecisionInsets; import org.xmind.gef.draw2d.geometry.PrecisionRectangle; import org.xmind.gef.draw2d.geometry.PrecisionRotator; import org.xmind.ui.mindmap.IIconTipPart; import org.xmind.ui.mindmap.IImagePart; import org.xmind.ui.mindmap.IMarkerPart; import org.xmind.ui.mindmap.INumberingPart; import org.xmind.ui.mindmap.ITitleTextPart; import org.xmind.ui.mindmap.ITopicPart; public class TopicLayout extends MindMapLayoutBase implements IRotatableReferenceDescriptor, IRotatableReferencedLayout { private int spacing = 2; private PrecisionInsets normalRefDesc = null; private PrecisionDimension normalSize = null; private PrecisionRectangle normalClientArea = null; private Insets rotatedRefDesc = null; private Dimension rotatedSize = null; private Rectangle rotatedClientArea = null; private PrecisionRotator rotator = null; public TopicLayout(ITopicPart topic) { super(topic); } protected ITopicPart getTopic() { return (ITopicPart) super.getPart(); } public int getSpacing() { return spacing; } public void setSpacing(int spacing) { this.spacing = spacing; } protected void fillLayoutData(IFigure container, ReferencedLayoutData data) { boolean minimized = isMinimized(container); ITopicPart topic = getTopic(); ITitleTextPart title = topic.getTitle(); IImagePart image = topic.getImagePart(); if ((topic.getTopic().hasTitle() && !"".equals(topic.getTopic() //$NON-NLS-1$ .getTitleText())) || image == null) { if (title != null) { if (minimized) { data.put(title.getFigure(), createMinArea(data)); } else { fillText(title, data); } } } List<IMarkerPart> markers = topic.getMarkers(); if (!markers.isEmpty()) { for (int i = markers.size() - 1; i >= 0; i--) { IMarkerPart marker = markers.get(i); fillMarker(marker, data); } } INumberingPart numbering = topic.getNumberingPart(); if (numbering != null) { if (minimized) { data.put(numbering.getFigure(), createMinArea(data)); } else { fillNumbering(numbering, data); } } List<IIconTipPart> iconTips = topic.getIconTips(); for (IIconTipPart iconTip : iconTips) { if (minimized) { data.put(iconTip.getFigure(), createMinArea(data)); } else { fillIconTip(iconTip, data); } } if (image != null) { if (minimized) { data.put(image.getFigure(), createMinArea(data)); } else { fillImage(image, data); } } if (title != null && data.get(title.getFigure()) == null) { data.put(title.getFigure(), createMinArea(data)); } } private void fillImage(IImagePart image, ReferencedLayoutData data) { IImage imageModel = image.getImageModel(); String alignment = imageModel.getAlignment(); IFigure imageFigure = image.getFigure(); PrecisionDimension size = r() .rd(new PrecisionDimension(imageFigure.getPreferredSize())); PrecisionDimension size2 = r() .td(new PrecisionDimension(imageFigure.getPreferredSize())); Point ref = data.getReference(); Rectangle r; Rectangle area = data.getClientArea(); if (area == null) { r = createBounds(ref, size.toDraw2DDimension()); } else { if (IImage.LEFT.equals(alignment)) { data.translate((int) ((size2.width + spacing) / 2), 0); area = data.getClientArea(); r = new PrecisionRectangle( area.x - size2.width / 2 - size.width / 2 - spacing, ref.y - size.height / 2, size.width, size.height) .toDraw2DRectangle(); data.add(new PrecisionRectangle(area.x - size2.width - spacing, ref.y - size2.height / 2, size2.width, size2.height) .toDraw2DRectangle()); } else if (IImage.RIGHT.equals(alignment)) { data.translate((int) (-(size2.width + spacing) / 2), 0); area = data.getClientArea(); r = new PrecisionRectangle( area.x + area.width + spacing + size2.width / 2 - size.width / 2, ref.y - size.height / 2, size.width, size.height) .toDraw2DRectangle(); data.add(new PrecisionRectangle(area.x + area.width + spacing, ref.y - size2.height / 2, size2.width, size2.height) .toDraw2DRectangle()); } else if (IImage.BOTTOM.equals(alignment)) { data.translate(0, -(int) ((size2.height + spacing) / 2)); area = data.getClientArea(); r = new PrecisionRectangle(ref.x - size.width / 2, area.y + area.height + size2.height / 2 - size.height / 2 + spacing, size.width, size.height).toDraw2DRectangle(); data.add(new PrecisionRectangle(ref.x - size2.width / 2, area.y + area.height + spacing, size2.width, size2.height).toDraw2DRectangle()); } else /* if (IImage.TOP.equals(alignment) */ { data.translate(0, (int) ((size2.height + spacing) / 2)); area = data.getClientArea(); r = new PrecisionRectangle(ref.x - size.width / 2, area.y - size2.height / 2 - size.height / 2 - spacing, size.width, size.height).toDraw2DRectangle(); data.add(new PrecisionRectangle(ref.x - size2.width / 2, area.y - size2.height - spacing, size2.width, size2.height).toDraw2DRectangle()); } } data.put(imageFigure, r); } private void fillMarker(IMarkerPart marker, ReferencedLayoutData data) { Point ref = data.getReference(); IFigure fig = marker.getFigure(); Dimension size = getChildPreferredSize(fig); int rotatedOffset = 0; if (getRotationDegrees() != 0) { double cos = Math .abs(Math.cos(Math.toRadians(getRotationDegrees()))); rotatedOffset = (int) (size.width * cos); data.translate(rotatedOffset / 2, 0); } Rectangle area = data.getClientArea(); Rectangle r; if (area == null) { r = createBounds(ref, size); } else { int dx = (size.width + spacing) / 2; data.translate(dx, 0); area = data.getClientArea(); r = new Rectangle(area.x - size.width - rotatedOffset - spacing, ref.y - size.height / 2, size.width, size.height); } data.put(fig, r); } private void fillIconTip(IIconTipPart iconTip, ReferencedLayoutData data) { Point ref = data.getReference(); IFigure fig = iconTip.getFigure(); Dimension size = getChildPreferredSize(fig); Rectangle area = data.getClientArea(); Rectangle r; if (area == null) { r = createBounds(ref, size); } else { int dx = (size.width + spacing) / 2; data.translate(-dx, 0); area = data.getClientArea(); r = new Rectangle(area.right() + spacing, ref.y - size.height / 2, size.width, size.height); } data.put(fig, r); } private void fillNumbering(INumberingPart numbering, ReferencedLayoutData data) { Point ref = data.getReference(); IFigure fig = numbering.getFigure(); Dimension size = getChildPreferredSize(fig); Rectangle area = data.getClientArea(); Rectangle r; if (area == null) { r = createBounds(ref, size); } else { int dx = (size.width + spacing) / 2; data.translate(dx, 0); area = data.getClientArea(); r = new Rectangle(area.x - size.width - spacing, ref.y - size.height / 2, size.width, size.height); } data.put(fig, r); } protected void fillText(ITitleTextPart text, ReferencedLayoutData data) { Point ref = data.getReference(); IFigure textFigure = text.getFigure(); Dimension size = getChildPreferredSize(textFigure); Rectangle r = createBounds(ref, size); data.put(textFigure, r); } private Rectangle createMinArea(ReferencedLayoutData data) { return data.createInitBounds(); // Point ref = data.getReference(); // return new Rectangle(ref.x, ref.y, 0, 0); } private boolean isMinimized(IFigure container) { if (container instanceof IMinimizable) return ((IMinimizable) container).isMinimized(); return false; } private static Rectangle createBounds(Point ref, Dimension size) { return new Rectangle(ref.x - size.width / 2, ref.y - size.height / 2, size.width, size.height); } protected Dimension getChildPreferredSize(IFigure child) { if (child instanceof IRotatableFigure) { return ((IRotatableFigure) child).getNormalPreferredSize(-1, -1) .toDraw2DDimension(); } return child.getPreferredSize(); } protected void layoutChild(IFigure child, Rectangle bounds, Point offset) { if (getRotationDegrees() != 0) { r().setOrigin(offset.x, offset.y); bounds = r().t(new PrecisionRectangle(bounds)).toDraw2DRectangle(); } super.layoutChild(child, bounds, offset); } public void invalidate() { super.invalidate(); normalClientArea = null; normalRefDesc = null; normalSize = null; rotatedClientArea = null; rotatedRefDesc = null; rotatedSize = null; } public Insets getReferenceDescription(IFigure figure) { if (rotatedRefDesc == null) { PrecisionInsets ins = getNormalReferenceDescription(figure); if (getRotationDegrees() != 0) { ins = r().ti(ins); } rotatedRefDesc = ins.toDraw2DInsets(); } return rotatedRefDesc; } public Rectangle getPreferredClientArea(IFigure container) { if (rotatedClientArea == null) { PrecisionRectangle rect = getNormalPreferredClientArea(container); if (getRotationDegrees() != 0) { Point ref = getLayoutData(container).getReference(); r().setOrigin(ref.x, ref.y); rect = r().tr(rect); } rotatedClientArea = rect.toDraw2DRectangle(); } return rotatedClientArea; } public Dimension getPreferredSize(IFigure container, int wHint, int hHint) { if (rotatedSize == null) { PrecisionDimension d = getNormalPreferredSize(container, wHint, hHint); if (getRotationDegrees() != 0) { d = r().td(d); } rotatedSize = d.toDraw2DDimension(); } return rotatedSize; } public PrecisionInsets getNormalReferenceDescription(IFigure figure) { if (normalRefDesc == null) { Point reference = getLayoutData(figure).getReference(); PrecisionInsets description = getNormalPreferredClientArea(figure) .getInsets(reference.x, reference.y); normalRefDesc = description.add(figure.getInsets()); } return normalRefDesc; } public PrecisionRectangle getNormalPreferredClientArea(IFigure container) { if (normalClientArea == null) { normalClientArea = new PrecisionRectangle( super.getPreferredClientArea(container)); } return normalClientArea; } public PrecisionDimension getNormalPreferredSize(IFigure container, int wHint, int hHint) { if (normalSize == null) { Insets ins = container.getInsets(); normalSize = getNormalPreferredClientArea(container).getSize() .expand(ins.getWidth(), ins.getHeight()); } return normalSize; } public double getRotationDegrees() { return r().getAngle(); } public void setRotationDegrees(double angle) { r().setAngle(angle); invalidate(); } public PrecisionRotator r() { if (rotator == null) rotator = new PrecisionRotator(); return rotator; } }