/* ****************************************************************************** * 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.List; import org.eclipse.draw2d.FigureListener; import org.eclipse.draw2d.IFigure; import org.xmind.gef.GEF; import org.xmind.gef.Request; import org.xmind.gef.part.IGraphicalPart; import org.xmind.gef.part.IPart; import org.xmind.gef.policy.NavigablePolicy; import org.xmind.ui.util.MindMapUtils; public abstract class MindMapNavigablePolicyBase extends NavigablePolicy { public static final String CACHE_NAV_OUTGOING = "org.xmind.ui.cache.navigation.outgoing."; //$NON-NLS-1$ public static final String CACHE_NAV_INCOMING = "org.xmind.ui.cache.navigation.incoming."; //$NON-NLS-1$ protected void findNavParts(Request request, String navType, List<IPart> sources, List<IPart> result) { IPart navPart = findCachedNavigation(sources, invertNavType(navType)); if (navPart != null) { result.add(navPart); setNavCaches(sources, navPart, navType); return; } navPart = findNewNavParts(request, navType, sources); setNavCaches(sources, navPart, navType); if (navPart != null) { result.add(navPart); return; } super.findNavParts(request, navType, sources, result); } protected abstract IPart findNewNavParts(Request request, String navType, List<IPart> sources); protected String invertNavType(String navType) { if (GEF.REQ_NAV_UP.equals(navType)) return GEF.REQ_NAV_DOWN; if (GEF.REQ_NAV_DOWN.equals(navType)) return GEF.REQ_NAV_UP; if (GEF.REQ_NAV_LEFT.equals(navType)) return GEF.REQ_NAV_RIGHT; if (GEF.REQ_NAV_RIGHT.equals(navType)) return GEF.REQ_NAV_LEFT; return navType; } private String getCacheKey(String navType, boolean inOrOut) { String prefix = inOrOut ? CACHE_NAV_INCOMING : CACHE_NAV_OUTGOING; return prefix + navType.replaceAll("\\s", "_"); //$NON-NLS-1$ //$NON-NLS-2$ } protected IPart findCachedNavigation(List<IPart> sources, String navType) { for (IPart source : sources) { IPart navPart = getCachedNavigation(source, navType); if (navPart != null) return navPart; } return null; } protected IPart getCachedNavigation(IPart source, String navType) { String inKey = getCacheKey(navType, true); IPart target = (IPart) MindMapUtils.getCache(source, inKey); if (target != null) { if (target.getStatus().isActive() && target.hasRole(GEF.ROLE_SELECTABLE) && source == MindMapUtils.getCache(target, getCacheKey( navType, false))) { return target; } MindMapUtils.flushCache(source, inKey); } return null; } protected void setNavCaches(List<IPart> sources, IPart target, String navType) { if (!sources.isEmpty()) { setNavCache(sources.get(0), target, navType); } for (int i = 1; i < sources.size(); i++) { setNavCache(sources.get(i), null, navType); } } protected void setNavCache(final IPart source, final IPart target, String navType) { final String outKey = getCacheKey(navType, false); if (target == null || target == source) { IPart oldTarget = (IPart) MindMapUtils.getCache(source, outKey); if (oldTarget != null) { MindMapUtils.flushCache(oldTarget, getCacheKey(navType, true)); } MindMapUtils.flushCache(source, outKey); } else { MindMapUtils.setCache(source, outKey, target); if (source instanceof IGraphicalPart) { ((IGraphicalPart) source).getFigure().addFigureListener( new FigureListener() { public void figureMoved(IFigure fig) { fig.removeFigureListener(this); MindMapUtils.flushCache(source, outKey); } }); } } if (target != null) { final String inKey = getCacheKey(navType, true); MindMapUtils.setCache(target, inKey, source); if (target instanceof IGraphicalPart) { ((IGraphicalPart) target).getFigure().addFigureListener( new FigureListener() { public void figureMoved(IFigure fig) { fig.removeFigureListener(this); MindMapUtils.flushCache(target, inKey); } }); } } } }