/* ******************************************************************************
* 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.tools;
import static org.xmind.ui.mindmap.MindMapUI.SEARCH_RANGE;
import org.eclipse.draw2d.IFigure;
import org.xmind.gef.graphicalpolicy.IStructure;
import org.xmind.gef.part.IGraphicalEditPart;
import org.xmind.gef.part.IPart;
import org.xmind.ui.branch.IInsertableBranchStructureExtension;
import org.xmind.ui.mindmap.IBranchPart;
import org.xmind.ui.mindmap.ITopicPart;
public class ParentSearcher {
private static final int FARTHEST_RANGE = SEARCH_RANGE * SEARCH_RANGE;
private int minDistance = Integer.MAX_VALUE;
private IBranchPart targetParent = null;
private boolean canDropInsideTopic;
public ParentSearcher(boolean canDropInsideTopic) {
this.canDropInsideTopic = canDropInsideTopic;
}
public ParentSearcher() {
this(false);
}
public IBranchPart searchTargetParent(IPart root, ParentSearchKey key) {
minDistance = Integer.MAX_VALUE;
targetParent = null;
search(root, key);
if (minDistance > FARTHEST_RANGE)
targetParent = null;
return targetParent;
}
private void search(IPart parent, ParentSearchKey key) {
if (parent instanceof IBranchPart) {
searchBranch((IBranchPart) parent, key);
} else {
for (IPart p : parent.getChildren()) {
search(p, key);
}
}
}
private void searchBranch(IBranchPart branch, ParentSearchKey key) {
ITopicPart topic = branch.getTopicPart();
if (topic == null)
return;
IFigure topicFigure = topic.getFigure();
if (topicFigure == null || !topicFigure.isEnabled())
return;
if (canDropInsideTopic
&& ((IGraphicalEditPart) topic).containsPoint(key
.getCursorPos())) {
minDistance = 0;
targetParent = branch;
return;
}
IStructure sa = branch.getBranchPolicy().getStructure(branch);
if (sa instanceof IInsertableBranchStructureExtension) {
int distance = ((IInsertableBranchStructureExtension) sa)
.calcChildDistance(branch, key);
if (distance >= 0 && distance < minDistance) {
minDistance = distance;
targetParent = branch;
}
}
if (branch.canSearchChild()) {
for (IBranchPart subBranch : branch.getSubBranches()) {
searchBranch(subBranch, key);
}
for (IBranchPart summaryBranch : branch.getSummaryBranches()) {
searchBranch(summaryBranch, key);
}
for (IBranchPart callout : branch.getCalloutBranches()) {
searchBranch(callout, key);
}
}
}
public int getIndex(IBranchPart targetParent, ParentSearchKey key) {
if (targetParent != null) {
if (canDropInsideTopic
&& ((IGraphicalEditPart) targetParent.getTopicPart())
.containsPoint(key.getCursorPos()))
return -1;
IStructure sa = targetParent.getBranchPolicy().getStructure(
targetParent);
if (sa instanceof IInsertableBranchStructureExtension) {
return ((IInsertableBranchStructureExtension) sa)
.calcChildIndex(targetParent, key);
}
}
return -1;
}
}