/* ****************************************************************************** * 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.editpolicies; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.xmind.gef.GEF; import org.xmind.gef.Request; import org.xmind.gef.graphicalpolicy.IStructure; import org.xmind.gef.part.IPart; import org.xmind.ui.branch.INavigableBranchStructureExtension; import org.xmind.ui.mindmap.IBranchPart; import org.xmind.ui.mindmap.ISheetPart; import org.xmind.ui.mindmap.ITopicPart; import org.xmind.ui.mindmap.MindMapUI; import org.xmind.ui.util.MindMapUtils; public class TopicNavigablePolicy extends MindMapNavigablePolicyBase { private boolean ignoreCache = true; public boolean understands(String requestType) { return super.understands(requestType) || MindMapUI.REQ_NAV_CHILD.equals(requestType) || MindMapUI.REQ_NAV_SIBLING.equals(requestType); } public void handle(Request request) { String reqType = request.getType(); if (MindMapUI.REQ_NAV_CHILD.equals(reqType)) { navChild(request); } else if (MindMapUI.REQ_NAV_SIBLING.equals(reqType)) { navSibling(request); } else { super.handle(request); } } private void navChild(Request request) { IPart source = request.getPrimaryTarget(); if (source instanceof ITopicPart) { ITopicPart topicPart = (ITopicPart) source; IBranchPart branch = topicPart.getOwnerBranch(); if (branch != null) { IBranchPart child = findFirstChild(branch); if (child != null) { ITopicPart childTopicPart = child.getTopicPart(); if (childTopicPart != null) setNavigationResult(request, Arrays.asList(childTopicPart)); } } } } private void navSibling(Request request) { IPart source = request.getPrimaryTarget(); if (source instanceof ITopicPart) { ITopicPart topicPart = (ITopicPart) source; IBranchPart branch = topicPart.getOwnerBranch(); if (branch != null) { if (branch.isCentral()) { IBranchPart child = findFirstChild(branch); if (child != null) { setNavigationResult(request, Arrays.asList(child.getTopicPart())); } } IBranchPart sibling = findSucceedingSiblingOrAncestor(branch); if (sibling != branch) { setNavigationResult(request, Arrays.asList(sibling.getTopicPart())); } } } } protected IPart findNewNavParts(Request request, String navType, List<IPart> sources) { ITopicPart topicPart = MindMapUtils.findTopicPart(request .getPrimaryTarget()); if (topicPart != null) { IBranchPart branch = topicPart.getOwnerBranch(); if (branch != null) { IPart navPart = findNavPart(branch, navType); if (navPart != null && navPart.getStatus().isActive()) { return navPart; } } } return null; } private IPart findNavPart(IBranchPart branch, String navType) { IStructure structure = branch.getBranchPolicy().getStructure(branch); if (structure instanceof INavigableBranchStructureExtension) { IPart navPart = ((INavigableBranchStructureExtension) structure) .calcNavigation(branch, navType); if (navPart == null) { IBranchPart parent = branch.getParentBranch(); if (parent != null) { IStructure parentStructure = parent.getBranchPolicy() .getStructure(parent); if (parentStructure instanceof INavigableBranchStructureExtension) { navPart = ((INavigableBranchStructureExtension) parentStructure) .calcChildNavigation(parent, branch, navType, false); } } else { navPart = calcNavThroughFloatingAndCentral(branch, navType); } if (navPart == null) { ignoreCache = true; navPart = calcNavByPosition(branch, navType); } } return navPart; } return null; } protected void setNavCaches(List<IPart> sources, IPart target, String navType) { if (!ignoreCache) { // super.setNavCaches(sources, target, navType); } ignoreCache = false; } private IPart calcNavThroughFloatingAndCentral(IBranchPart branch, String navType) { return calcNavByPosition(branch, navType); } private IPart calcNavByPosition(IBranchPart branch, String navType) { return new PositionSearcher(branch, navType).search(); } protected void findSequentialNavParts(Request request, String navType, IPart sequenceStart, List<IPart> sources, List<IPart> result) { ITopicPart startTopic = MindMapUtils.findTopicPart(sequenceStart); if (startTopic != null) { ITopicPart sourceTopic = MindMapUtils.findTopicPart(request .getPrimaryTarget()); if (sourceTopic != null && isSibling(sourceTopic, startTopic)) { IBranchPart startBranch = startTopic.getOwnerBranch(); IBranchPart sourceBranch = sourceTopic.getOwnerBranch(); IBranchPart sourceParentBranch = sourceBranch.getParentBranch(); if (sourceParentBranch != null) { IStructure parentStructure = sourceParentBranch .getBranchPolicy().getStructure(sourceParentBranch); if (parentStructure instanceof INavigableBranchStructureExtension) { INavigableBranchStructureExtension ext = (INavigableBranchStructureExtension) parentStructure; IPart endPart = ext .calcChildNavigation(sourceParentBranch, sourceBranch, navType, true); IBranchPart endBranch = MindMapUtils .findBranch(endPart); if (endBranch == null) { endBranch = sourceBranch; } List<IBranchPart> list = new ArrayList<IBranchPart>(); ext.calcSequentialNavigation(sourceParentBranch, startBranch, endBranch, list); for (IBranchPart branch : list) { result.add(branch.getTopicPart()); } request.setResult(GEF.RESULT_NEW_FOCUS, endBranch.getTopicPart()); } } else { addSeqPartsFromFloatingAndCentral(navType, sourceBranch, startBranch, result); } } if (!result.contains(startTopic)) result.add(startTopic); } else { super.findSequentialNavParts(request, navType, sequenceStart, sources, result); } } private void addSeqPartsFromFloatingAndCentral(String navType, IBranchPart sourceBranch, IBranchPart startBranch, List<IPart> result) { } private boolean isSibling(ITopicPart t1, ITopicPart t2) { IBranchPart b1 = t1.getOwnerBranch(); IBranchPart b2 = t2.getOwnerBranch(); if (b1 != null && b2 != null) { return b1.getParentBranch() == b2.getParentBranch(); } return false; } protected IPart findNextOrPrev(IPart source, boolean nextOrPrev) { if (source != null) return findNextOrPrevTopic(source, nextOrPrev); return super.findNextOrPrev(source, nextOrPrev); } private IPart findNextOrPrevTopic(IPart current, boolean nextOrPrev) { if (current instanceof ITopicPart) { IBranchPart branch = ((ITopicPart) current).getOwnerBranch(); if (branch != null) { IBranchPart result; if (nextOrPrev) { result = findFirstChild(branch); if (result == null) { result = findSucceedingSiblingOrAncestor(branch); } } else { result = findPrecedingBranch(branch); } if (result != null) { return result.getTopicPart(); } } } return current; } private IBranchPart findFirstChild(IBranchPart current) { List<IBranchPart> subBranches = current.getSubBranches(); if (!subBranches.isEmpty()) { return subBranches.get(0); } subBranches = current.getSummaryBranches(); if (!subBranches.isEmpty()) { return subBranches.get(0); } return null; } private IBranchPart findSucceedingSiblingOrAncestor(IBranchPart current) { IBranchPart parent = current.getParentBranch(); if (parent != null) { List<IBranchPart> branches = parent.getSubBranches(); int index = branches.indexOf(current); if (index >= 0 && index < branches.size() - 1) { return branches.get(index + 1); } int lastBranchIndex = branches.size() - 1; branches = parent.getSummaryBranches(); if (branches.size() > 0 && index == lastBranchIndex) { return branches.get(0); } index = branches.indexOf(current); if (index >= 0 && index < branches.size() - 1) { return branches.get(index + 1); } return findSucceedingSiblingOrAncestor(parent); } else if (current.getParent() instanceof ISheetPart) { ISheetPart sheet = (ISheetPart) current.getParent(); List<IBranchPart> floatingBranches = sheet.getFloatingBranches(); if (current == sheet.getCentralBranch()) { if (!floatingBranches.isEmpty()) { return floatingBranches.get(0); } } else { int index = floatingBranches.indexOf(current); if (index >= 0) { if (index < floatingBranches.size() - 1) { IBranchPart floatBranch = floatingBranches .get(index + 1); return floatBranch; } return sheet.getCentralBranch(); } } } return current; } private IBranchPart findPrecedingBranch(IBranchPart current) { IBranchPart parent = current.getParentBranch(); if (parent != null) { List<IBranchPart> branches = parent.getSubBranches(); int index = branches.indexOf(current); if (index > 0) { return findLastDescendant(branches.get(index - 1)); } int lastBranchIndex = branches.size() - 1; branches = parent.getSummaryBranches(); index = branches.indexOf(current); if (index == 0) { return parent.getSubBranches().get(lastBranchIndex); } if (index > 0) { return findLastDescendant(branches.get(index - 1)); } return parent; } else if (current.getParent() instanceof ISheetPart) { ISheetPart sheet = ((ISheetPart) current.getParent()); List<IBranchPart> floatingBranches = sheet.getFloatingBranches(); if (current == sheet.getCentralBranch()) { if (!floatingBranches.isEmpty()) { IBranchPart lastFloating = floatingBranches .get(floatingBranches.size() - 1); return findLastDescendant(lastFloating); } else { return findLastDescendant(current); } } else if (floatingBranches.contains(current)) { int index = floatingBranches.indexOf(current); if (index == 0) { return findLastDescendant(sheet.getCentralBranch()); } return findLastDescendant(floatingBranches.get(index - 1)); } } return current; } private IBranchPart findLastDescendant(IBranchPart branch) { List<IBranchPart> summaryBranches = branch.getSummaryBranches(); if (!summaryBranches.isEmpty()) { return findLastDescendant(summaryBranches.get(summaryBranches .size() - 1)); } List<IBranchPart> subBranches = branch.getSubBranches(); if (!subBranches.isEmpty()) { return findLastDescendant(subBranches.get(subBranches.size() - 1)); } return branch; } }