/* ******************************************************************************
* 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.decorators;
import static org.xmind.ui.style.StyleUtils.createBranchConnection;
import static org.xmind.ui.style.StyleUtils.createBranchDecoration;
import static org.xmind.ui.style.StyleUtils.getBranchConnectionColor;
import static org.xmind.ui.style.StyleUtils.getColor;
import static org.xmind.ui.style.StyleUtils.getInteger;
import static org.xmind.ui.style.StyleUtils.getLineStyle;
import static org.xmind.ui.style.StyleUtils.getString;
import static org.xmind.ui.style.StyleUtils.getStyleSelector;
import static org.xmind.ui.style.StyleUtils.isBranchLineTapered;
import static org.xmind.ui.style.StyleUtils.isSameDecoration;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.swt.SWT;
import org.xmind.core.Core;
import org.xmind.core.ISummary;
import org.xmind.gef.draw2d.IAnchor;
import org.xmind.gef.draw2d.decoration.IDecoration;
import org.xmind.gef.graphicalpolicy.IStructure;
import org.xmind.gef.graphicalpolicy.IStyleSelector;
import org.xmind.gef.part.Decorator;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.ui.branch.IBranchStructureExtension;
import org.xmind.ui.decorations.IBranchConnectionDecoration;
import org.xmind.ui.decorations.IBranchConnections;
import org.xmind.ui.internal.figures.BranchFigure;
import org.xmind.ui.mindmap.IAnimatablePart;
import org.xmind.ui.mindmap.IBranchPart;
import org.xmind.ui.mindmap.INodePart;
import org.xmind.ui.mindmap.IPlusMinusPart;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.style.StyleUtils;
import org.xmind.ui.style.Styles;
import org.xmind.ui.util.MindMapUtils;
public class BranchDecorator extends Decorator {
private static final BranchDecorator instanceo = new BranchDecorator();
public void activate(IGraphicalPart part, IFigure figure) {
super.activate(part, figure);
if (part instanceof IBranchPart && figure instanceof BranchFigure) {
IBranchPart branch = (IBranchPart) part;
BranchFigure branchFigure = (BranchFigure) figure;
branchFigure.setConnections(branch.getConnections());
}
}
public void decorate(IGraphicalPart part, IFigure figure) {
if (figure instanceof BranchFigure) {
BranchFigure branchFigure = (BranchFigure) figure;
if (part instanceof IBranchPart) {
IBranchPart branch = (IBranchPart) part;
branchFigure.setFolded(isBranchFolded(branch));
boolean animating = branch instanceof IAnimatablePart
&& ((IAnimatablePart) branch).isFigureAnimating();
IBranchPart parent = branch.getParentBranch();
if (parent != null) {
IFigure parentFigure = parent.getFigure();
if (parentFigure instanceof BranchFigure) {
BranchFigure parentBranchFigure = (BranchFigure) parentFigure;
branchFigure.setMinimized(parentBranchFigure.isFolded()
|| parentBranchFigure.isMinimized()
|| isUnusedSummaryBranch(branch));
if (!animating) {
branchFigure.setVisible(!parentBranchFigure
.isFolded()
&& parentBranchFigure.isVisible());
}
}
}
decorateBranchDecoration(part, getStyleSelector(part),
branchFigure, animating);
}
}
}
private boolean isUnusedSummaryBranch(IBranchPart branch) {
IBranchPart parent = branch.getParentBranch();
if (parent != null && parent.getSummaryBranches().contains(branch)) {
String topicId = branch.getTopic().getId();
for (ISummary s : parent.getTopic().getSummaries()) {
if (topicId.equals(s.getTopicId()))
return false;
}
return true;
}
return false;
}
protected void decorateBranchDecoration(IGraphicalPart part,
IStyleSelector ss, BranchFigure branchFigure, boolean animating) {
IDecoration decoration = branchFigure.getDecoration();
String newDescId = getString(part, ss, Styles.BranchDecorationClass,
Styles.DEF_BRANCH_DECORATION);
if (!isSameDecoration(decoration, newDescId)) {
decoration = createBranchDecoration(part, newDescId);
branchFigure.setDecoration(decoration);
}
if (decoration != null) {
decoration.setAlpha(branchFigure, 0xff);
if (!animating) {
decoration.setVisible(branchFigure, branchFigure.isVisible());
}
}
}
private boolean isBranchFolded(IBranchPart branch) {
if (!branch.isPropertyModifiable(Core.TopicFolded))
return false;
Object cache = MindMapUtils.getCache(branch, IBranchPart.CACHE_FOLDED);
if (cache != null)
return Boolean.TRUE.equals(cache);
return branch.getTopic().isFolded();
}
public void decorateChildren(IGraphicalPart part, IFigure figure) {
super.decorateChildren(part, figure);
if (figure instanceof BranchFigure) {
BranchFigure branchFigure = (BranchFigure) figure;
if (part instanceof IBranchPart) {
IBranchPart branch = (IBranchPart) part;
branchFigure.setFolded(isBranchFolded(branch));
boolean animating = branch instanceof IAnimatablePart
&& ((IAnimatablePart) branch).isFigureAnimating();
IBranchPart parent = branch.getParentBranch();
if (parent != null) {
IFigure parentFigure = parent.getFigure();
if (parentFigure instanceof BranchFigure) {
BranchFigure parentBranchFigure = (BranchFigure) parentFigure;
branchFigure.setMinimized(parentBranchFigure.isFolded()
|| parentBranchFigure.isMinimized()
|| isUnusedSummaryBranch(branch));
if (!animating) {
branchFigure.setVisible(!parentBranchFigure
.isFolded()
&& parentBranchFigure.isVisible());
}
}
}
IStyleSelector ss = getStyleSelector(part);
decorateConnections(branch, ss, branchFigure,
branch.getConnections(), animating);
}
}
}
private void decorateConnections(IBranchPart branch, IStyleSelector ss,
BranchFigure figure, IBranchConnections connections,
boolean ignoreVisibility) {
String newConnectionId = getString(branch, ss, Styles.LineClass,
Styles.BRANCH_CONN_STRAIGHT);
connections.setId(newConnectionId);
IAnchor sourceAnchor = null;
ITopicPart topic = branch.getTopicPart();
if (topic instanceof INodePart) {
sourceAnchor = ((INodePart) topic).getSourceAnchor(branch);
}
connections.setSourceAnchor(figure, sourceAnchor);
connections.setAlpha(figure, 0xff);
connections.setLineColor(
figure,
getColor(branch, ss, Styles.LineColor, newConnectionId,
Styles.DEF_TOPIC_LINE_COLOR));
connections.setLineStyle(figure,
getLineStyle(branch, ss, newConnectionId, SWT.LINE_SOLID));
connections.setLineWidth(figure,
getInteger(branch, ss, Styles.LineWidth, newConnectionId, 1));
int sourceOrientation = PositionConstants.NONE;
IStructure structure = branch.getBranchPolicy().getStructure(branch);
if (structure instanceof IBranchStructureExtension) {
sourceOrientation = ((IBranchStructureExtension) structure)
.getSourceOrientation(branch);
}
connections.setSourceOrientation(figure, sourceOrientation);
int sourceExpansion = getSourceExpansion(branch, ss, sourceOrientation,
connections.getLineWidth(), connections.getId());
connections.setSourceExpansion(figure, sourceExpansion);
connections.setTapered(figure, isBranchLineTapered(branch, ss));
connections.setCornerSize(figure,
getInteger(branch, ss, Styles.LineCorner, newConnectionId, 5));
List<IBranchPart> subBranches = branch.getSubBranches();
for (int i = 0; i < subBranches.size(); i++) {
IBranchPart subBranch = subBranches.get(i);
IDecoration connection = connections.getDecoration(i);
if (!isSameDecoration(connection, newConnectionId)) {
connection = createBranchConnection(branch, newConnectionId);
connections.setDecoration(figure, i, connection);
}
if (connection != null
&& connection instanceof IBranchConnectionDecoration) {
decorateConnection(branch, ss, figure, subBranch,
(IBranchConnectionDecoration) connection, i,
connections, ignoreVisibility);
}
}
}
private int getSourceExpansion(IBranchPart branch, IStyleSelector ss,
int sourceOrientation, int lineWidth, String decorationId) {
if (sourceOrientation == PositionConstants.NONE)
return 0;
IPlusMinusPart plusMinus = branch.getPlusMinus();
if (plusMinus != null && plusMinus.getFigure().isVisible()) {
Dimension size = plusMinus.getFigure().getPreferredSize();
return Math.max(size.width, size.height) + lineWidth + 1;
}
int spacing = StyleUtils.getInteger(branch, ss, Styles.MajorSpacing,
decorationId, -1);
if (spacing >= 0)
return spacing / 2;
return Styles.DEFAULT_EXPANSION + lineWidth;
}
private void decorateConnection(IBranchPart branch, IStyleSelector ss,
BranchFigure figure, IBranchPart subBranch,
IBranchConnectionDecoration connection, int subBranchIndex,
IBranchConnections connections, boolean ignoreVisibility) {
IAnchor targetAnchor = null;
ITopicPart subTopic = subBranch.getTopicPart();
if (subTopic instanceof INodePart) {
targetAnchor = ((INodePart) subTopic).getTargetAnchor(branch);
}
connection.setTargetAnchor(figure, targetAnchor);
int targetOrientation = PositionConstants.NONE;
IStructure structure = branch.getBranchPolicy().getStructure(branch);
if (structure instanceof IBranchStructureExtension) {
targetOrientation = ((IBranchStructureExtension) structure)
.getChildTargetOrientation(branch, subBranch);
}
connection.setTargetOrientation(figure, targetOrientation);
connection.setTargetExpansion(figure, 0);
connection.setLineColor(
figure,
getBranchConnectionColor(branch, ss, subBranch, subBranchIndex,
connections.getLineColor()));
if (!ignoreVisibility) {
connection.setVisible(
figure,
connection.getSourceAnchor() != null
&& connection.getTargetAnchor() != null
&& figure.isVisible() && !figure.isFolded());
}
}
// private IBranchStructure getStructureAlgorithm(IBranchPart branch) {
// IBranchPolicy policy = branch.getBranchPolicy();
// if (policy == null)
// return null;
// IStructure sa = policy.getStructure(branch);
// if (sa instanceof IBranchStructure)
// return (IBranchStructure) sa;
// return null;
// }
public static BranchDecorator getInstanceo() {
return instanceo;
}
}