Copyright (c) 2000, 2008 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jface.text.link; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Stack; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.text.IDocument;
A linked mode manager ensures exclusive access of linked position infrastructures to documents. There is at most one LinkedModeManager installed on the same document. The getManager methods will return the existing instance if any of the specified documents already have an installed manager.
Since:3.0
/** * A linked mode manager ensures exclusive access of linked position infrastructures to documents. There * is at most one <code>LinkedModeManager</code> installed on the same document. The <code>getManager</code> * methods will return the existing instance if any of the specified documents already have an installed * manager. * * @since 3.0 */
class LinkedModeManager {
Our implementation of ILinkedModeListener.
/** * Our implementation of <code>ILinkedModeListener</code>. */
private class Listener implements ILinkedModeListener { @Override public void left(LinkedModeModel model, int flags) { LinkedModeManager.this.left(model, flags); } @Override public void suspend(LinkedModeModel model) { // not interested } @Override public void resume(LinkedModeModel model, int flags) { // not interested } }
Global map from documents to managers.
/** Global map from documents to managers. */
private static Map<IDocument, LinkedModeManager> fgManagers= new HashMap<>();
Returns whether there exists a LinkedModeManager on document.
Params:
  • document – the document of interest
Returns:true if there exists a LinkedModeManager on document, false otherwise
/** * Returns whether there exists a <code>LinkedModeManager</code> on <code>document</code>. * * @param document the document of interest * @return <code>true</code> if there exists a <code>LinkedModeManager</code> on <code>document</code>, <code>false</code> otherwise */
public static boolean hasManager(IDocument document) { return fgManagers.get(document) != null; }
Returns whether there exists a LinkedModeManager on any of the documents.
Params:
  • documents – the documents of interest
Returns:true if there exists a LinkedModeManager on any of the documents, false otherwise
/** * Returns whether there exists a <code>LinkedModeManager</code> on any of the <code>documents</code>. * * @param documents the documents of interest * @return <code>true</code> if there exists a <code>LinkedModeManager</code> on any of the <code>documents</code>, <code>false</code> otherwise */
public static boolean hasManager(IDocument[] documents) { for (IDocument document : documents) { if (hasManager(document)) return true; } return false; }
Returns the manager for the given documents. If force is true, any existing conflicting managers are canceled, otherwise, the method may return null if there are conflicts.
Params:
  • documents – the documents of interest
  • force – whether to kill any conflicting managers
Returns:a manager able to cover the requested documents, or null if there is a conflict and force was set to false
/** * Returns the manager for the given documents. If <code>force</code> is * <code>true</code>, any existing conflicting managers are canceled, otherwise, * the method may return <code>null</code> if there are conflicts. * * @param documents the documents of interest * @param force whether to kill any conflicting managers * @return a manager able to cover the requested documents, or <code>null</code> if there is a conflict and <code>force</code> was set to <code>false</code> */
public static LinkedModeManager getLinkedManager(IDocument[] documents, boolean force) { if (documents == null || documents.length == 0) return null; Set<LinkedModeManager> mgrs= new HashSet<>(); LinkedModeManager mgr= null; for (IDocument document : documents) { mgr= fgManagers.get(document); if (mgr != null) mgrs.add(mgr); } if (mgrs.size() > 1) if (force) { for (LinkedModeManager m : mgrs) { m.closeAllEnvironments(); } } else { return null; } if (mgrs.isEmpty()) mgr= new LinkedModeManager(); for (IDocument document : documents) fgManagers.put(document, mgr); return mgr; }
Cancels any linked mode manager for the specified document.
Params:
  • document – the document whose LinkedModeManager should be canceled
/** * Cancels any linked mode manager for the specified document. * * @param document the document whose <code>LinkedModeManager</code> should be canceled */
public static void cancelManager(IDocument document) { LinkedModeManager mgr= fgManagers.get(document); if (mgr != null) mgr.closeAllEnvironments(); }
The hierarchy of environments managed by this manager.
/** The hierarchy of environments managed by this manager. */
private Stack<LinkedModeModel> fEnvironments= new Stack<>(); private Listener fListener= new Listener();
Notify the manager about a leaving model.
Params:
  • model – the model to nest
  • flags – the reason and commands for leaving linked mode
/** * Notify the manager about a leaving model. * * @param model the model to nest * @param flags the reason and commands for leaving linked mode */
private void left(LinkedModeModel model, int flags) { if (!fEnvironments.contains(model)) return; while (!fEnvironments.isEmpty()) { LinkedModeModel env= fEnvironments.pop(); if (env == model) break; env.exit(ILinkedModeListener.NONE); } if (fEnvironments.isEmpty()) { removeManager(); } } private void closeAllEnvironments() { while (!fEnvironments.isEmpty()) { LinkedModeModel env= fEnvironments.pop(); env.exit(ILinkedModeListener.NONE); } removeManager(); } private void removeManager() { for (Iterator<LinkedModeManager> it= fgManagers.values().iterator(); it.hasNext();) { if (it.next() == this) it.remove(); } }
Tries to nest the given LinkedModeModel onto the top of the stack of environments managed by the receiver. If force is true, any environments on the stack that create a conflict are killed.
Params:
  • model – the model to nest
  • force – whether to force the addition of the model
Returns:true if nesting was successful, false otherwise (only possible if force is false
/** * Tries to nest the given <code>LinkedModeModel</code> onto the top of * the stack of environments managed by the receiver. If <code>force</code> * is <code>true</code>, any environments on the stack that create a conflict * are killed. * * @param model the model to nest * @param force whether to force the addition of the model * @return <code>true</code> if nesting was successful, <code>false</code> otherwise (only possible if <code>force</code> is <code>false</code> */
public boolean nestEnvironment(LinkedModeModel model, boolean force) { Assert.isNotNull(model); try { while (true) { if (fEnvironments.isEmpty()) { model.addLinkingListener(fListener); fEnvironments.push(model); return true; } LinkedModeModel top= fEnvironments.peek(); if (model.canNestInto(top)) { model.addLinkingListener(fListener); fEnvironments.push(model); return true; } else if (!force) { return false; } else { // force fEnvironments.pop(); top.exit(ILinkedModeListener.NONE); // continue; } } } finally { // if we remove any, make sure the new one got inserted Assert.isTrue(!fEnvironments.isEmpty()); } }
Returns the LinkedModeModel that is on top of the stack of environments managed by the receiver.
Returns:the topmost LinkedModeModel
/** * Returns the <code>LinkedModeModel</code> that is on top of the stack of * environments managed by the receiver. * * @return the topmost <code>LinkedModeModel</code> */
public LinkedModeModel getTopEnvironment() { if (fEnvironments.isEmpty()) return null; return fEnvironments.peek(); } }