/* ****************************************************************************** * 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.mindmap; 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.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.LayoutManager; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.swt.SWT; import org.xmind.core.Core; import org.xmind.core.IBoundary; import org.xmind.core.ISheet; import org.xmind.core.ISummary; import org.xmind.core.ITopic; import org.xmind.core.event.CoreEvent; import org.xmind.core.event.ICoreEventRegister; import org.xmind.core.event.ICoreEventSource; import org.xmind.core.event.ICoreEventSupport; import org.xmind.gef.GEF; import org.xmind.gef.draw2d.IAnchor; import org.xmind.gef.draw2d.IDecoratedFigure; import org.xmind.gef.draw2d.decoration.IConnectionDecoration; import org.xmind.gef.draw2d.decoration.ICorneredDecoration; import org.xmind.gef.draw2d.decoration.IDecoration; import org.xmind.gef.draw2d.decoration.ILineDecoration; import org.xmind.gef.draw2d.decoration.IShapeDecoration; import org.xmind.gef.graphicalpolicy.IGraphicalPolicy; import org.xmind.gef.graphicalpolicy.IStructure; import org.xmind.gef.graphicalpolicy.IStyleSelector; import org.xmind.gef.part.IGraphicalEditPart; import org.xmind.gef.part.IPart; import org.xmind.gef.part.IRequestHandler; import org.xmind.ui.branch.IBranchPolicy; import org.xmind.ui.branch.IBranchStructureExtension; import org.xmind.ui.branch.IBranchStyleSelector; import org.xmind.ui.decorations.IBranchConnectionDecoration; import org.xmind.ui.decorations.IBranchConnections; import org.xmind.ui.decorations.IBranchConnections2; import org.xmind.ui.decorations.ICalloutTopicDecoration; import org.xmind.ui.internal.InfoItemContributorManager; import org.xmind.ui.internal.ModelCacheManager; import org.xmind.ui.internal.decorations.BranchConnections; import org.xmind.ui.internal.decorations.CalloutBranchConnections; import org.xmind.ui.internal.figures.BranchFigure; import org.xmind.ui.internal.layouts.BranchLayout; import org.xmind.ui.mindmap.IBoundaryPart; import org.xmind.ui.mindmap.IBranchPart; import org.xmind.ui.mindmap.IInfoPart; import org.xmind.ui.mindmap.ILabelPart; import org.xmind.ui.mindmap.IMindMapViewer; import org.xmind.ui.mindmap.INodePart; import org.xmind.ui.mindmap.IPlusMinusPart; import org.xmind.ui.mindmap.ISheetPart; import org.xmind.ui.mindmap.ISummaryPart; import org.xmind.ui.mindmap.ITopicPart; import org.xmind.ui.mindmap.MindMapUI; import org.xmind.ui.style.StyleUtils; import org.xmind.ui.style.Styles; import org.xmind.ui.util.MindMapUtils; /** * @author MANGOSOFT */ public class BranchPart extends MindMapPartBase implements IBranchPart { private ITopicPart topicPart = null; private List<IBranchPart> subBranches = null; private IPlusMinusPart plusMinus = null; private List<IBoundaryPart> boundaries = null; private List<ISummaryPart> summaries = null; private List<IBranchPart> summaryBranches = null; private List<IBranchPart> calloutBranches = null; private ILabelPart label = null; private IInfoPart infoPart = null; private boolean central = false; private ChildSorter sorter = new ChildSorter(this); private BranchConnections connections = null; private String branchPolicyId = null; private int level = -1; private CalloutBranchConnections calloutConnections; private String overrideBranchType = null; public BranchPart() { // setDecorator(BranchDecorator.getInstanceo()); } public ITopic getTopic() { return (ITopic) getRealModel(); } public IBranchPart getParentBranch() { if (getParent() instanceof IBranchPart) return (IBranchPart) getParent(); return null; } public ITopicPart getTopicPart() { return topicPart; } public void setTopicPart(ITopicPart topicPart) { this.topicPart = topicPart; } public IPlusMinusPart getPlusMinus() { return plusMinus; } public void setPlusMinus(IPlusMinusPart plusMinus) { this.plusMinus = plusMinus; } public List<IBranchPart> getSubBranches() { if (subBranches == null) { subBranches = new ArrayList<IBranchPart>(); } return subBranches; } public void addSubBranch(IBranchPart subBranch) { getSubBranches().add(subBranch); sorter.sort(getSubBranches()); int index = getSubBranches().indexOf(subBranch); getConnections().add(getFigure(), index, null); } public void removeSubBranch(IBranchPart subBranch) { int index = getSubBranches().indexOf(subBranch); getConnections().remove(getFigure(), index); getSubBranches().remove(subBranch); } public List<IBranchPart> getCalloutBranches() { if (calloutBranches == null) calloutBranches = new ArrayList<IBranchPart>(); return calloutBranches; } public void addCalloutBranch(IBranchPart calloutBranch) { getCalloutBranches().add(calloutBranch); sorter.sort(getCalloutBranches()); int index = getCalloutBranches().indexOf(calloutBranch); getCalloutConnections().add(getFigure(), index, null); } public void removeCalloutBranch(IBranchPart calloutBranch) { int index = getCalloutBranches().indexOf(calloutBranch); getCalloutConnections().remove(getFigure(), index); getCalloutBranches().remove(calloutBranch); } public List<ISummaryPart> getSummaries() { if (summaries == null) { summaries = new ArrayList<ISummaryPart>(); } return summaries; } public void addSummary(ISummaryPart summary) { getSummaries().add(summary); sorter.sort(getSummaries()); } public void removeSummary(ISummaryPart summary) { getSummaries().remove(summary); } public List<IBranchPart> getSummaryBranches() { if (summaryBranches == null) summaryBranches = new ArrayList<IBranchPart>(); return summaryBranches; } public void addSummaryBranch(IBranchPart summaryBranch) { getSummaryBranches().add(summaryBranch); sorter.sort(getSummaryBranches()); } public void removeSummaryBranch(IBranchPart summaryBranch) { getSummaryBranches().remove(summaryBranch); } public ILabelPart getLabel() { return label; } public void setLabel(ILabelPart label) { this.label = label; } public IInfoPart getInfoPart() { return infoPart; } public void setinfoPart(IInfoPart information) { this.infoPart = information; } protected IFigure createFigure() { BranchFigure branchFigure = new BranchFigure(); branchFigure.setConnections(getConnections()); branchFigure.setCalloutConnections(getCalloutConnections()); return branchFigure; } public void setParent(IPart parent) { if (getParent() instanceof BranchPart) { BranchPart parentBranch = (BranchPart) getParent(); parentBranch.removeSubBranch(this); parentBranch.removeCalloutBranch(this); parentBranch.removeSummaryBranch(this); } else if (getParent() instanceof SheetPart) { SheetPart sheet = (SheetPart) getParent(); sheet.removeFloatingBranch(this); if (sheet.getCentralBranch() == this) sheet.setCentralBranch(null); } super.setParent(parent); central = getTopic() .equals(getSite().getViewer().getAdapter(ITopic.class)); if (getParent() instanceof BranchPart) { BranchPart parentBranch = (BranchPart) getParent(); level = parentBranch.getLevel() + 1; if (ITopic.ATTACHED.equals(getTopic().getType())) { parentBranch.addSubBranch(this); } else if (ITopic.SUMMARY.equals(getTopic().getType())) { parentBranch.addSummaryBranch(this); } else if (ITopic.CALLOUT.equals(getTopic().getType())) { parentBranch.addCalloutBranch(this); } } else if (getParent() instanceof SheetPart) { SheetPart sheet = (SheetPart) getParent(); if (getTopic().equals(sheet.getCentralTopic())) { level = 0; sheet.setCentralBranch(this); } else if (ITopic.DETACHED.equals(getTopic().getType())) { level = 1; sheet.addFloatingBranch(this); } } setBranchPolicyId(findNewBranchPolicyId()); } public int getBranchIndex() { IBranchPart parentBranch = getParentBranch(); if (parentBranch != null) { if (MindMapUI.BRANCH_CALLOUT.equals(getBranchType())) { return parentBranch.getCalloutBranches().indexOf(this); } else return parentBranch.getSubBranches().indexOf(this); } return 0; } public int getLevel() { return level; } public List<IBoundaryPart> getBoundaries() { if (boundaries == null) { boundaries = new ArrayList<IBoundaryPart>(); } return boundaries; } public void addBoundary(IBoundaryPart boundary) { getBoundaries().add(boundary); sorter.sort(getBoundaries()); } public void removeBoundary(IBoundaryPart boundary) { getBoundaries().remove(boundary); } public boolean isCentral() { return central; } public boolean isFolded() { return ((BranchFigure) getFigure()).isFolded(); } public String getBranchType() { if (overrideBranchType != null) return overrideBranchType; if (isCentral()) return MindMapUI.BRANCH_CENTRAL; IPart p = getParent(); if (p instanceof IBranchPart) { IBranchPart parentBranch = (IBranchPart) p; if (parentBranch.isCentral() && parentBranch.getSubBranches().contains(this)) return MindMapUI.BRANCH_MAIN; if (parentBranch.getSummaryBranches().contains(this)) return MindMapUI.BRANCH_SUMMARY; if (parentBranch.getCalloutBranches().contains(this)) return MindMapUI.BRANCH_CALLOUT; } if (p instanceof ISheetPart && ((ISheetPart) p).getFloatingBranches().contains(this)) return MindMapUI.BRANCH_FLOATING; return MindMapUI.BRANCH_SUB; } public void setOverrideBranchType(String overrideBranchType) { this.overrideBranchType = overrideBranchType; } protected LayoutManager createLayoutManager() { return new BranchLayout(this); } protected Object[] getModelChildren(Object model) { List<Object> list = new ArrayList<Object>(); ITopic topic = getTopic(); boolean showsSubTopics = showsSubTopics(); if (showsSubTopics) { for (IBoundary b : MindMapUtils.getSortedBoundaries(topic)) { list.add(new ViewerModel(BoundaryPart.class, b)); } } else { for (IBoundary b : topic.getBoundaries()) { if (b.isMasterBoundary()) { list.add(new ViewerModel(BoundaryPart.class, b)); break; } } } list.add(new ViewerModel(TopicPart.class, topic)); if (!(InfoItemContributorManager.getInstance().getContributors() .isEmpty())) list.add(new ViewerModel(InfoPart.class, topic)); if (showsSubTopics) { List<ITopic> children = topic.getChildren(ITopic.ATTACHED); if (!children.isEmpty()) { list.add(new ViewerModel(PlusMinusPart.class, topic)); } for (ITopic subtopic : children) { list.add(new ViewerModel(BranchPart.class, subtopic)); } List<ITopic> calloutTopics = topic.getChildren(ITopic.CALLOUT); for (ITopic calloutTopic : calloutTopics) { list.add(new ViewerModel(BranchPart.class, calloutTopic)); } for (ISummary summary : topic.getSummaries()) { ITopic summaryTopic = summary.getTopic(); if (summaryTopic != null) { list.add(new SummaryViewerModel(SummaryPart.class, summary, summaryTopic)); } } for (ITopic summaryTopic : topic.getChildren(ITopic.SUMMARY)) { list.add(new ViewerModel(BranchPart.class, summaryTopic)); } } return list.toArray(); } private boolean showsSubTopics() { int maxLevel = getSite().getViewer().getProperties() .getInteger(IMindMapViewer.VIEWER_MAX_TOPIC_LEVEL, -1); return maxLevel < 0 || level < maxLevel; } protected void addChild(IPart child, int index) { super.addChild(child, index); if (getStatus().isActive()) { update(); if (child instanceof IBranchPart && child.getStatus().isActive()) { child.update(); } } } protected void removeChild(IPart child) { super.removeChild(child); if (getStatus().isActive()) { update(); } } protected void reorderChild(IPart child, int index) { int oldBranchIndex = getSubBranches().indexOf(child); int oldCallloutBranchIndex = getCalloutBranches().indexOf(child); super.reorderChild(child, index); if (oldCallloutBranchIndex >= 0) { sorter.sort(getCalloutBranches()); int newCalloutBranchIndex = getCalloutBranches().indexOf(child); getCalloutConnections().move(getFigure(), oldCallloutBranchIndex, newCalloutBranchIndex); } if (oldBranchIndex >= 0) { sorter.sort(getSubBranches()); int newBranchIndex = getSubBranches().indexOf(child); getConnections().move(getFigure(), oldBranchIndex, newBranchIndex); } else if (getBoundaries().contains(child)) { sorter.sort(getBoundaries()); } else if (getSummaries().contains(child)) { sorter.sort(getSummaries()); } else if (getSummaryBranches().contains(child)) { sorter.sort(getSummaryBranches()); } update(); } protected void registerCoreEvents(Object source, ICoreEventRegister register) { super.registerCoreEvents(source, register); register.register(Core.TopicFolded); register.register(Core.TopicAdd); register.register(Core.TopicRemove); register.register(Core.Position); register.register(Core.BoundaryAdd); register.register(Core.BoundaryRemove); register.register(Core.SummaryAdd); register.register(Core.SummaryRemove); register.register(Core.Style); register.register(Core.StructureClass); register.register(Core.Labels); register.register(Core.TopicNotes); // register.register(Core.TopicHyperlink); ISheet sheet = getTopic().getOwnedSheet(); register.setNextSourceFrom(sheet); register.register(Core.Visibility); register.register(Core.SheetSettings); } public void handleCoreEvent(final CoreEvent event) { Object modelcacheForLayout = ModelCacheManager.getInstance().getCache( getTopic(), ModelCacheManager.MODEL_CACHE_DELAYLAYOUT); if (Boolean.TRUE.equals(modelcacheForLayout)) { return; } String type = event.getType(); if (Core.TopicFolded.equals(type)) { treeUpdate(true); } else if (Core.TopicAdd.equals(type) || Core.TopicRemove.equals(type)) { Object topicType = event.getData(); if (ITopic.ATTACHED.equals(topicType) || ITopic.CALLOUT.equals(topicType)) { refresh(); } else if (ITopic.SUMMARY.equals(topicType)) { refresh(); } } else if (Core.Position.equals(type)) { org.xmind.core.util.Point newPosition = (org.xmind.core.util.Point) event .getNewValue(); Point p = MindMapUtils.toGraphicalPosition(newPosition); getCacheManager().setCache(CACHE_PREF_POSITION, p); //update(); getFigure().revalidate(); } else if (Core.BoundaryAdd.equals(type) || Core.BoundaryRemove.equals(type) || Core.SummaryAdd.equals(type) || Core.SummaryRemove.equals(type)) { refresh(); } else if (Core.Style.equals(type)) { refreshStyles(); } else if (Core.StructureClass.equals(type)) { treeUpdateBranchPolicy(); sendFakeStyleEvent(); } else if (Core.Labels.equals(type) || Core.TopicNotes.equals(type) || Core.TopicHyperlink.equals(type) || Core.Visibility.equals(type) || Core.SheetSettings.equals(type)) { refresh(); if (getInfoPart() != null) getInfoPart().refresh(); if (getTopicPart() != null) getTopicPart().refresh(); } else { super.handleCoreEvent(event); } } // Force an 'unchanged' style change be notified, so that // property sections or other style listeners can update themselves. // TODO: replace this with a better way of event dispatching, // e.g. Properties and PropertyChangeListener private void sendFakeStyleEvent() { ICoreEventSupport coreEventSupport = (ICoreEventSupport) getTopic() .getOwnedWorkbook().getAdapter(ICoreEventSupport.class); if (coreEventSupport != null) { ICoreEventSource source = (ICoreEventSource) getTopic(); String styleId = getTopic().getStyleId(); CoreEvent event = new CoreEvent(source, Core.Style, styleId, styleId); coreEventSupport.dispatch(source, event); } } public void refreshStyles() { treeFlushStyleCaches(); treeUpdate(true); treeRefresh(); floatingRefresh(); } private void treeFlushStyleCaches() { IStyleSelector ss = getGraphicalPolicy().getStyleSelector(this); if (ss instanceof IBranchStyleSelector) { ((IBranchStyleSelector) ss).flushStyleCaches(this); } for (IBranchPart subBranch : getSubBranches()) { ((BranchPart) subBranch).treeFlushStyleCaches(); } for (IBranchPart calloutBranch : getCalloutBranches()) { ((BranchPart) calloutBranch).treeFlushStyleCaches(); } for (IBranchPart summaryBranch : getSummaryBranches()) { ((BranchPart) summaryBranch).treeFlushStyleCaches(); } } protected void treeUpdateBranchPolicy() { updateBranchPolicy(); updateView(); refreshChildren(); for (IBranchPart subBranch : getSubBranches()) { ((BranchPart) subBranch).treeUpdateBranchPolicy(); } for (IBranchPart calloutBranch : getCalloutBranches()) { ((BranchPart) calloutBranch).treeUpdateBranchPolicy(); } for (IBranchPart summaryBranch : getSummaryBranches()) { ((BranchPart) summaryBranch).treeUpdateBranchPolicy(); } updateChildren(); } private void updateBranchPolicy() { String newId = findNewBranchPolicyId(); setBranchPolicyId(newId); } private void setBranchPolicyId(String newId) { IBranchPolicy newPolicy = MindMapUI.getBranchPolicyManager() .getBranchPolicy(newId); branchPolicyId = newId; setGraphicalPolicy(newPolicy); getFigure().revalidate(); } public void setGraphicalPolicy(IGraphicalPolicy graphicalPolicy) { IGraphicalPolicy oldPolicy = getGraphicalPolicy(); super.setGraphicalPolicy(graphicalPolicy); if (oldPolicy instanceof IBranchPolicy) { ((IBranchPolicy) oldPolicy).postDeactivate(this); } } public String getBranchPolicyId() { if (branchPolicyId == null) { branchPolicyId = findNewBranchPolicyId(); } return branchPolicyId; } private String findNewBranchPolicyId() { return MindMapUI.getBranchPolicyManager().calculateBranchPolicyId(this, getTopic().getStructureClass()); } public IBranchPolicy getBranchPolicy() { IGraphicalPolicy gp = getGraphicalPolicy(); if (gp instanceof IBranchPolicy) return (IBranchPolicy) gp; return MindMapUI.getBranchPolicyManager().getDefaultBranchPolicy(); } public void setModel(Object model) { super.setModel(model); Point p = MindMapUtils.toGraphicalPosition(getTopic().getPosition()); getCacheManager().setCache(CACHE_PREF_POSITION, p); } protected void onActivated() { super.onActivated(); //getBranchPolicy().activate(this); } protected void onDeactivated() { // getBranchPolicy().deactivate(this); super.onDeactivated(); } /* * (non-Javadoc) * @see org.xmind.ui.internal.mindmap.MindMapPartBase#updateView() */ @Override protected void updateView() { super.updateView(); BranchFigure branchFigure = (BranchFigure) getFigure(); branchFigure.setFolded(shouldBeFolded()); boolean animating = isFigureAnimating(); IBranchPart parent = getParentBranch(); if (parent != null) { branchFigure.setMinimized(isUnusedSummaryBranch(parent)); IFigure parentFigure = parent.getFigure(); if (parentFigure instanceof BranchFigure) { BranchFigure parentBranchFigure = (BranchFigure) parentFigure; if (!animating) { branchFigure.setVisible(!parentBranchFigure.isFolded() && parentBranchFigure.isVisible()); } } } IStyleSelector ss = getStyleSelector(this); IDecoration decoration = branchFigure.getDecoration(); String newDescId = getString(this, ss, Styles.BranchDecorationClass, Styles.DEF_BRANCH_DECORATION); if (!isSameDecoration(decoration, newDescId)) { decoration = createBranchDecoration(this, newDescId); branchFigure.setDecoration(decoration); } if (decoration != null) { decoration.setAlpha(branchFigure, 0xff); if (!animating) { decoration.setVisible(branchFigure, branchFigure.isVisible()); } } } private boolean isUnusedSummaryBranch(IBranchPart parent) { if (parent.getSummaryBranches().contains(this)) { String topicId = getTopic().getId(); for (ISummary s : parent.getTopic().getSummaries()) { if (topicId.equals(s.getTopicId())) return false; } return true; } return false; } private boolean shouldBeFolded() { if (!isPropertyModifiable(Core.TopicFolded)) return false; Object cache = MindMapUtils.getCache(this, IBranchPart.CACHE_FOLDED); if (cache != null) return Boolean.TRUE.equals(cache); return getTopic().isFolded(); } protected void updateChildren() { super.updateChildren(); BranchFigure branchFigure = (BranchFigure) getFigure(); branchFigure.setFolded(shouldBeFolded()); boolean animating = isFigureAnimating(); IBranchPart parent = getParentBranch(); if (parent != null) { IFigure parentFigure = parent.getFigure(); if (parentFigure instanceof BranchFigure) { BranchFigure parentBranchFigure = (BranchFigure) parentFigure; if (!animating) { branchFigure.setVisible(!parentBranchFigure.isFolded() && parentBranchFigure.isVisible()); } if (MindMapUI.BRANCH_CALLOUT.equals(getBranchType())) { decorateCalloutConnections(parent, parentBranchFigure, parent.getCalloutConnections(), animating); } } } if (getTopicPart() != null) { getTopicPart().update(); getTopicPart().refresh(); } if (getPlusMinus() != null) getPlusMinus().update(); if (getLabel() != null) getLabel().update(); if (getInfoPart() != null) { getInfoPart().update(); getInfoPart().refresh(); } // for (IBranchPart calloutPart : getCalloutBranches()) { // calloutPart.update(); // } for (IBoundaryPart b : getBoundaries()) { b.update(); } for (ISummaryPart s : getSummaries()) { s.update(); } IStyleSelector ss = getStyleSelector(this); decorateConnections(ss, branchFigure, getConnections(), animating); decorateCalloutConnections(this, (BranchFigure) getFigure(), getCalloutConnections(), animating); // for (IBranchPart s : getSubBranches()) { // ((BranchPart) s).updateChildren(); // } } private void decorateCalloutConnections(IBranchPart parent, BranchFigure parentFigure, IBranchConnections2 connections, boolean ignoreVisibility) { connections.setId("org.xmind.ui.calloutbranchconnections"); //$NON-NLS-1$ List<IBranchPart> calloutBranches = parent.getCalloutBranches(); for (int i = 0; i < calloutBranches.size(); i++) { decorateCalloutConnection(parent, parentFigure, connections, i, ignoreVisibility); } } private void decorateCalloutConnection(IBranchPart parent, BranchFigure parentFigure, IBranchConnections2 connections, int index, boolean ignoreVisibility) { IBranchPart calloutBranch = parent.getCalloutBranches().get(index); IDecoration connection = connections.getDecoration(index); BranchFigure calloutBranchFigure = (BranchFigure) calloutBranch .getFigure(); IDecoratedFigure topicFigure = (IDecoratedFigure) calloutBranch .getTopicPart().getFigure(); IDecoration topicDecoration = topicFigure.getDecoration(); if (topicDecoration instanceof ICalloutTopicDecoration) { ICalloutTopicDecoration ctd = (ICalloutTopicDecoration) topicDecoration; String connectionId = ctd.getFromLineClass(); if (!isSameDecoration(connection, connectionId)) { connection = createBranchConnection(calloutBranch, connectionId); ((CalloutBranchConnections) connections) .putFigureToDecoration(calloutBranchFigure, connection); connections.setDecoration(parentFigure, index, connection); } if (connection instanceof IShapeDecoration) { IShapeDecoration shapedConnection = (IShapeDecoration) connection; shapedConnection.setFillColor(parentFigure, ctd.getFromFillColor()); shapedConnection.setAlpha(parentFigure, 0xff); } if (connection instanceof ICorneredDecoration) { ((ICorneredDecoration) connection).setCornerSize(parentFigure, ctd.getFromLineCorner()); } if (connection instanceof IConnectionDecoration) { IConnectionDecoration connectedConnection = (IConnectionDecoration) connection; IAnchor sourceAnchor = null; ITopicPart topic = parent.getTopicPart(); if (topic instanceof INodePart) { sourceAnchor = ((INodePart) topic).getSourceAnchor(parent); } connectedConnection.setSourceAnchor(parentFigure, sourceAnchor); IAnchor targetAnchor = null; ITopicPart subTopic = calloutBranch.getTopicPart(); if (subTopic instanceof INodePart) { targetAnchor = ((INodePart) subTopic) .getTargetAnchor(parent); } connectedConnection.setTargetAnchor(calloutBranchFigure, targetAnchor); } if (connection instanceof ILineDecoration) { ILineDecoration linedConnection = (ILineDecoration) connection; linedConnection.setLineColor(parentFigure, ctd.getFromLineColor()); linedConnection.setLineStyle(parentFigure, ctd.getFromLineStyle()); linedConnection.setLineWidth(parentFigure, ctd.getFromLineWidth()); } if (connection instanceof IBranchConnectionDecoration) { IBranchConnectionDecoration branchConnection = (IBranchConnectionDecoration) connection; branchConnection.setSourceExpansion(parentFigure, 0); branchConnection.setSourceOrientation(parentFigure, PositionConstants.NONE); branchConnection.setTargetOrientation(calloutBranchFigure, PositionConstants.NONE); branchConnection.setTargetExpansion(calloutBranchFigure, 0); if (!ignoreVisibility) { branchConnection.setVisible(calloutBranchFigure, branchConnection.getSourceAnchor() != null && branchConnection .getTargetAnchor() != null && calloutBranchFigure.isVisible()); } } } } private void decorateConnections(IStyleSelector ss, BranchFigure figure, IBranchConnections connections, boolean ignoreVisibility) { String newConnectionId = getString(this, ss, Styles.LineClass, Styles.BRANCH_CONN_STRAIGHT); connections.setId(newConnectionId); IAnchor sourceAnchor = null; ITopicPart topic = getTopicPart(); if (topic instanceof INodePart) { sourceAnchor = ((INodePart) topic).getSourceAnchor(this); } connections.setSourceAnchor(figure, sourceAnchor); connections.setAlpha(figure, 0xff); connections.setLineColor(figure, getColor(this, ss, Styles.LineColor, newConnectionId, Styles.DEF_TOPIC_LINE_COLOR)); connections.setLineStyle(figure, getLineStyle(this, ss, newConnectionId, SWT.LINE_SOLID)); connections.setLineWidth(figure, getInteger(this, ss, Styles.LineWidth, newConnectionId, 1)); int sourceOrientation = PositionConstants.NONE; IStructure structure = getBranchPolicy().getStructure(this); if (structure instanceof IBranchStructureExtension) { sourceOrientation = ((IBranchStructureExtension) structure) .getSourceOrientation(this); } connections.setSourceOrientation(figure, sourceOrientation); int sourceExpansion = getSourceExpansion(this, ss, sourceOrientation, connections.getLineWidth(), connections.getId()); connections.setSourceExpansion(figure, sourceExpansion); connections.setTapered(figure, isBranchLineTapered(this, ss)); connections.setCornerSize(figure, getInteger(this, ss, Styles.LineCorner, newConnectionId, 5)); List<IBranchPart> subBranches = 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(this, newConnectionId); connections.setDecoration(figure, i, connection); } if (connection != null && connection instanceof IBranchConnectionDecoration) { decorateConnection(this, 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()); } } public void treeUpdate(boolean updateParent) { if (updateParent) { IBranchPart parentBranch = getParentBranch(); if (parentBranch != null) { ((BranchPart) parentBranch).updateChildren(); } } updateView(); for (IBranchPart subBranch : getSubBranches()) { subBranch.treeUpdate(false); } for (IBranchPart calloutBranch : getCalloutBranches()) { calloutBranch.treeUpdate(false); } for (IBranchPart summaryBranch : getSummaryBranches()) { summaryBranch.treeUpdate(false); } updateChildren(); } public void treeRefresh() { if (getInfoPart() != null) getInfoPart().refresh(); if (getTopicPart() != null) getTopicPart().refresh(); for (IBranchPart subBranch : getSubBranches()) { subBranch.treeRefresh(); } for (IBranchPart calloutBranch : getCalloutBranches()) { calloutBranch.treeRefresh(); } for (IBranchPart summaryBranch : getSummaryBranches()) { summaryBranch.treeRefresh(); } updateChildren(); } private void floatingRefresh() { IPart parent = getParent(); if (parent != null && parent instanceof SheetPart) { List<IBranchPart> floatings = ((SheetPart) parent) .getFloatingBranches(); for (IBranchPart floating : floatings) { IInfoPart infoPart = floating.getInfoPart(); if (infoPart != null) infoPart.refresh(); floating.treeRefresh(); } } } protected void declareEditPolicies(IRequestHandler reqHandler) { super.declareEditPolicies(reqHandler); reqHandler.installEditPolicy(GEF.ROLE_CREATABLE, MindMapUI.POLICY_TOPIC_CREATABLE); reqHandler.installEditPolicy(GEF.ROLE_EXTENDABLE, MindMapUI.POLICY_EXTENDABLE); reqHandler.installEditPolicy(GEF.ROLE_DELETABLE, MindMapUI.POLICY_DELETABLE); } public boolean isPropertyModifiable(String propertyName) { return isPropertyModifiable(propertyName, null); } public boolean isPropertyModifiable(String propertyName, String secondaryKey) { return getBranchPolicy().isPropertyModifiable(this, propertyName, secondaryKey); } public IPart findAt(Point position) { IPart ret; IPart focusedPart = getSite().getViewer().getFocusedPart(); if (focusedPart instanceof IGraphicalEditPart && getBoundaries().contains(focusedPart)) { ret = ((IGraphicalEditPart) focusedPart).findAt(position); if (ret != null) return ret; } ret = super.findAt(position); if (ret == this) return null; return ret; } public boolean canSearchChild() { BranchFigure figure = (BranchFigure) getFigure(); return !figure.isFolded() && !figure.isMinimized() && figure.isVisible() && figure.isEnabled() && (!getSubBranches().isEmpty() || !getSummaryBranches().isEmpty() || !getCalloutBranches().isEmpty()); } protected boolean isFigureAnimatable() { return true; } public IBranchConnections getConnections() { if (connections == null) { connections = new BranchConnections(); } return connections; } public IBranchConnections2 getCalloutConnections() { if (calloutConnections == null) calloutConnections = new CalloutBranchConnections(); return calloutConnections; } @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { if (adapter.isAssignableFrom(ITopic.class)) return getTopic(); if (adapter == ITopicPart.class) return getTopicPart(); if (adapter == IPlusMinusPart.class) return getPlusMinus(); if (adapter == ILabelPart.class) return getLabel(); if (adapter == IInfoPart.class) return getInfoPart(); return super.getAdapter(adapter); } }