Copyright (c) 2000, 2015 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, 2015 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.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.TextEdit; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadPositionCategoryException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentExtension; import org.eclipse.jface.text.IDocumentExtension.IReplace; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.IPositionUpdater; import org.eclipse.jface.text.Position;
The model for linked mode, umbrellas several LinkedPositionGroups. Once installed, the model propagates any changes to a position to all its siblings in the same position group.

Setting up a model consists of first adding LinkedPositionGroups to it, and then installing the model by either calling forceInstall() or tryInstall(). After installing the model, it becomes sealed and no more groups may be added.

If a document change occurs that would modify more than one position group or that would invalidate the disjointness requirement of the positions, the model is torn down and all positions are deleted. The same happens upon calling exit(int).

Nesting

A LinkedModeModel may be nested into another model. This happens when installing a model the positions of which all fit into a single position in a parent model that has previously been installed on the same document(s).

Clients may instantiate instances of this class.

Since:3.0
@noextendThis class is not intended to be subclassed by clients.
/** * The model for linked mode, umbrellas several * {@link LinkedPositionGroup}s. Once installed, the model * propagates any changes to a position to all its siblings in the same position * group. * <p> * Setting up a model consists of first adding * <code>LinkedPositionGroup</code>s to it, and then installing the * model by either calling {@link #forceInstall()} or * {@link #tryInstall()}. After installing the model, it becomes * <em>sealed</em> and no more groups may be added. * </p> * <p> * If a document change occurs that would modify more than one position * group or that would invalidate the disjointness requirement of the positions, * the model is torn down and all positions are deleted. The same happens * upon calling {@link #exit(int)}. * </p> * <h4>Nesting</h4> * <p> * A <code>LinkedModeModel</code> may be nested into another model. This * happens when installing a model the positions of which all fit into a * single position in a parent model that has previously been installed on * the same document(s). * </p> * <p> * Clients may instantiate instances of this class. * </p> * * @since 3.0 * @noextend This class is not intended to be subclassed by clients. */
public class LinkedModeModel {
Checks whether there is already a model installed on document.
Params:
  • document – the IDocument of interest
Returns:true if there is an existing model, false otherwise
/** * Checks whether there is already a model installed on <code>document</code>. * * @param document the <code>IDocument</code> of interest * @return <code>true</code> if there is an existing model, <code>false</code> * otherwise */
public static boolean hasInstalledModel(IDocument document) { // if there is a manager, there also is a model return LinkedModeManager.hasManager(document); }
Checks whether there is already a linked mode model installed on any of the documents.
Params:
  • documents – the IDocuments of interest
Returns:true if there is an existing model, false otherwise
/** * Checks whether there is already a linked mode model installed on any of * the <code>documents</code>. * * @param documents the <code>IDocument</code>s of interest * @return <code>true</code> if there is an existing model, <code>false</code> * otherwise */
public static boolean hasInstalledModel(IDocument[] documents) { // if there is a manager, there also is a model return LinkedModeManager.hasManager(documents); }
Cancels any linked mode model on the specified document. If there is no model, nothing happens.
Params:
  • document – the document whose LinkedModeModel should be canceled
/** * Cancels any linked mode model on the specified document. If there is no * model, nothing happens. * * @param document the document whose <code>LinkedModeModel</code> should * be canceled */
public static void closeAllModels(IDocument document) { LinkedModeManager.cancelManager(document); }
Returns the model currently active on document at offset, or null if there is none.
Params:
  • document – the document for which the caller asks for a model
  • offset – the offset into document, as there may be several models on a document
Returns:the model currently active on document, or null
/** * Returns the model currently active on <code>document</code> at * <code>offset</code>, or <code>null</code> if there is none. * * @param document the document for which the caller asks for a * model * @param offset the offset into <code>document</code>, as there may be * several models on a document * @return the model currently active on <code>document</code>, or * <code>null</code> */
public static LinkedModeModel getModel(IDocument document, int offset) { if (!hasInstalledModel(document)) return null; LinkedModeManager mgr= LinkedModeManager.getLinkedManager(new IDocument[] {document}, false); if (mgr != null) return mgr.getTopEnvironment(); return null; }
Encapsulates the edition triggered by a change to a linking position. Can be applied to a document as a whole.
/** * Encapsulates the edition triggered by a change to a linking position. Can * be applied to a document as a whole. */
private class Replace implements IReplace {
The edition to apply on a document.
/** The edition to apply on a document. */
private TextEdit fEdit;
Creates a new instance.
Params:
  • edit – the edition to apply to a document.
/** * Creates a new instance. * * @param edit the edition to apply to a document. */
public Replace(TextEdit edit) { fEdit= edit; } @Override public void perform(IDocument document, IDocumentListener owner) throws RuntimeException, MalformedTreeException { document.removeDocumentListener(owner); fIsChanging= true; try { fEdit.apply(document, TextEdit.UPDATE_REGIONS | TextEdit.CREATE_UNDO); } catch (BadLocationException e) { /* XXX: perform should really throw a BadLocationException * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52950 */ throw new RuntimeException(e); } finally { document.addDocumentListener(owner); fIsChanging= false; } } }
The document listener triggering the linked updating of positions managed by this model.
/** * The document listener triggering the linked updating of positions * managed by this model. */
private class DocumentListener implements IDocumentListener { private boolean fExit= false;
Checks whether event occurs within any of the positions managed by this model. If not, the linked mode is left.
Params:
  • event – {@inheritDoc}
/** * Checks whether <code>event</code> occurs within any of the positions * managed by this model. If not, the linked mode is left. * * @param event {@inheritDoc} */
@Override public void documentAboutToBeChanged(DocumentEvent event) { // don't react on changes executed by the parent model if (fParentEnvironment != null && fParentEnvironment.isChanging()) return; for (LinkedPositionGroup group : fGroups) { if (!group.isLegalEvent(event)) { fExit= true; return; } } }
Propagates a change to a linked position to all its sibling positions.
Params:
  • event – {@inheritDoc}
/** * Propagates a change to a linked position to all its sibling positions. * * @param event {@inheritDoc} */
@Override public void documentChanged(DocumentEvent event) { if (fExit) { LinkedModeModel.this.exit(ILinkedModeListener.EXTERNAL_MODIFICATION); return; } fExit= false; // don't react on changes executed by the parent model if (fParentEnvironment != null && fParentEnvironment.isChanging()) return; // collect all results Map<IDocument, TextEdit> result= null; for (LinkedPositionGroup group : fGroups) { Map<IDocument, TextEdit> map= group.handleEvent(event); if (result != null && map != null) { // exit if more than one position was changed LinkedModeModel.this.exit(ILinkedModeListener.EXTERNAL_MODIFICATION); return; } if (map != null) result= map; } if (result != null) { // edit all documents for (Entry<IDocument, TextEdit> entry : result.entrySet()) { IDocument doc = entry.getKey(); TextEdit edit= entry.getValue(); Replace replace= new Replace(edit); // apply the edition, either as post notification replace // on the calling document or directly on any other // document if (doc == event.getDocument()) { if (doc instanceof IDocumentExtension) { ((IDocumentExtension) doc).registerPostNotificationReplace(this, replace); } else { // ignore - there is no way we can log from JFace text... } } else { replace.perform(doc, this); } } } } }
The set of linked position groups.
/** The set of linked position groups. */
private final List<LinkedPositionGroup> fGroups= new ArrayList<>();
The set of documents spanned by this group.
/** The set of documents spanned by this group. */
private final Set<IDocument> fDocuments= new HashSet<>();
The position updater for linked positions.
/** The position updater for linked positions. */
private final IPositionUpdater fUpdater= new InclusivePositionUpdater(getCategory());
The document listener on the documents affected by this model.
/** The document listener on the documents affected by this model. */
private final DocumentListener fDocumentListener= new DocumentListener();
The parent model for a hierarchical set up, or null.
/** The parent model for a hierarchical set up, or <code>null</code>. */
private LinkedModeModel fParentEnvironment;
The position in fParentEnvironment that includes all positions in this object, or null if there is no parent model.
/** * The position in <code>fParentEnvironment</code> that includes all * positions in this object, or <code>null</code> if there is no parent * model. */
private LinkedPosition fParentPosition= null;
A model is sealed once it has children - no more positions can be added.
/** * A model is sealed once it has children - no more positions can be * added. */
private boolean fIsSealed= false;
true when this model is changing documents.
/** <code>true</code> when this model is changing documents. */
private boolean fIsChanging= false;
The linked listeners.
/** The linked listeners. */
private final List<ILinkedModeListener> fListeners= new ArrayList<>();
Flag telling whether we have exited:
/** Flag telling whether we have exited: */
private boolean fIsActive= true;
The sequence of document positions as we are going to iterate through them.
/** * The sequence of document positions as we are going to iterate through * them. */
private List<LinkedPosition> fPositionSequence= new ArrayList<>();
Whether we are in the process of editing documents (set by Replace, read by DocumentListener.
Returns:true if we are in the process of editing a document, false otherwise
/** * Whether we are in the process of editing documents (set by <code>Replace</code>, * read by <code>DocumentListener</code>. * * @return <code>true</code> if we are in the process of editing a * document, <code>false</code> otherwise */
private boolean isChanging() { return fIsChanging || fParentEnvironment != null && fParentEnvironment.isChanging(); }
Throws a BadLocationException if group conflicts with this model's groups.
Params:
  • group – the group being checked
Throws:
/** * Throws a <code>BadLocationException</code> if <code>group</code> * conflicts with this model's groups. * * @param group the group being checked * @throws BadLocationException if <code>group</code> conflicts with this * model's groups */
private void enforceDisjoint(LinkedPositionGroup group) throws BadLocationException { for (LinkedPositionGroup g : fGroups) { g.enforceDisjoint(group); } }
Causes this model to exit. Called either if an illegal document change is detected, or by the UI.
Params:
/** * Causes this model to exit. Called either if an illegal document change * is detected, or by the UI. * * @param flags the exit flags as defined in {@link ILinkedModeListener} */
public void exit(int flags) { if (!fIsActive) return; fIsActive= false; for (IDocument doc : fDocuments) { try { doc.removePositionCategory(getCategory()); } catch (BadPositionCategoryException e) { // won't happen Assert.isTrue(false); } doc.removePositionUpdater(fUpdater); doc.removeDocumentListener(fDocumentListener); } fDocuments.clear(); fGroups.clear(); List<ILinkedModeListener> listeners= new ArrayList<>(fListeners); fListeners.clear(); for (ILinkedModeListener listener : listeners) { listener.left(this, flags); } if (fParentEnvironment != null) fParentEnvironment.resume(flags); }
Causes this model to stop forwarding updates. The positions are not unregistered however, which will only happen when exit is called, or after the next document change.
Params:
Since:3.1
/** * Causes this model to stop forwarding updates. The positions are not * unregistered however, which will only happen when <code>exit</code> * is called, or after the next document change. * * @param flags the exit flags as defined in {@link ILinkedModeListener} * @since 3.1 */
public void stopForwarding(int flags) { fDocumentListener.fExit= true; }
Puts document into the set of managed documents. This involves registering the document listener and adding our position category.
Params:
  • document – the new document
/** * Puts <code>document</code> into the set of managed documents. This * involves registering the document listener and adding our position * category. * * @param document the new document */
private void manageDocument(IDocument document) { if (!fDocuments.contains(document)) { fDocuments.add(document); document.addPositionCategory(getCategory()); document.addPositionUpdater(fUpdater); document.addDocumentListener(fDocumentListener); } }
Returns the position category used by this model.
Returns:the position category used by this model
/** * Returns the position category used by this model. * * @return the position category used by this model */
private String getCategory() { return toString(); }
Adds a position group to this LinkedModeModel. This method may not be called if the model has been installed. Also, if a UI has been set up for this model, it may not pick up groups added afterwards.

If the positions in group conflict with any other group in this model, a BadLocationException is thrown. Also, if this model is nested inside another one, all positions in all groups of the child model have to reside within a single position in the parent model, otherwise a BadLocationException is thrown.

If group already exists, nothing happens.

Params:
  • group – the group to be added to this model
Throws:
/** * Adds a position group to this <code>LinkedModeModel</code>. This * method may not be called if the model has been installed. Also, if * a UI has been set up for this model, it may not pick up groups * added afterwards. * <p> * If the positions in <code>group</code> conflict with any other group in * this model, a <code>BadLocationException</code> is thrown. Also, * if this model is nested inside another one, all positions in all * groups of the child model have to reside within a single position in the * parent model, otherwise a <code>BadLocationException</code> is thrown. * </p> * <p> * If <code>group</code> already exists, nothing happens. * </p> * * @param group the group to be added to this model * @throws BadLocationException if the group conflicts with the other groups * in this model or violates the nesting requirements. * @throws IllegalStateException if the method is called when the * model is already sealed */
public void addGroup(LinkedPositionGroup group) throws BadLocationException { if (group == null) throw new IllegalArgumentException("group may not be null"); //$NON-NLS-1$ if (fIsSealed) throw new IllegalStateException("model is already installed"); //$NON-NLS-1$ if (fGroups.contains(group)) // nothing happens return; enforceDisjoint(group); group.seal(); fGroups.add(group); }
Creates a new model.
Since:3.1
/** * Creates a new model. * @since 3.1 */
public LinkedModeModel() { }
Installs this model, which includes registering as document listener on all involved documents and storing global information about this model. Any conflicting model already present will be closed.

If an exception is thrown, the installation failed and the model is unusable.

Throws:
  • BadLocationException – if some of the positions of this model were not valid positions on their respective documents
/** * Installs this model, which includes registering as document * listener on all involved documents and storing global information about * this model. Any conflicting model already present will be * closed. * <p> * If an exception is thrown, the installation failed and * the model is unusable. * </p> * * @throws BadLocationException if some of the positions of this model * were not valid positions on their respective documents */
public void forceInstall() throws BadLocationException { if (!install(true)) Assert.isTrue(false); }
Installs this model, which includes registering as document listener on all involved documents and storing global information about this model. If there is another model installed on the document(s) targeted by the receiver that conflicts with it, installation may fail.

The return value states whether installation was successful; if not, the model is not installed and will not work.

Throws:
  • BadLocationException – if some of the positions of this model were not valid positions on their respective documents
Returns:true if installation was successful, false otherwise
/** * Installs this model, which includes registering as document * listener on all involved documents and storing global information about * this model. If there is another model installed on the * document(s) targeted by the receiver that conflicts with it, installation * may fail. * <p> * The return value states whether installation was * successful; if not, the model is not installed and will not work. * </p> * * @return <code>true</code> if installation was successful, * <code>false</code> otherwise * @throws BadLocationException if some of the positions of this model * were not valid positions on their respective documents */
public boolean tryInstall() throws BadLocationException { return install(false); }
Installs this model, which includes registering as document listener on all involved documents and storing global information about this model. The return value states whether installation was successful; if not, the model is not installed and will not work. The return value can only then become false if force was set to false as well.
Params:
  • force – if true, any other model that cannot coexist with this one is canceled; if false, install will fail when conflicts occur and return false
Throws:
  • BadLocationException – if some of the positions of this model were not valid positions on their respective documents
Returns:true if installation was successful, false otherwise
/** * Installs this model, which includes registering as document * listener on all involved documents and storing global information about * this model. The return value states whether installation was * successful; if not, the model is not installed and will not work. * The return value can only then become <code>false</code> if * <code>force</code> was set to <code>false</code> as well. * * @param force if <code>true</code>, any other model that cannot * coexist with this one is canceled; if <code>false</code>, * install will fail when conflicts occur and return false * @return <code>true</code> if installation was successful, * <code>false</code> otherwise * @throws BadLocationException if some of the positions of this model * were not valid positions on their respective documents */
private boolean install(boolean force) throws BadLocationException { if (fIsSealed) throw new IllegalStateException("model is already installed"); //$NON-NLS-1$ enforceNotEmpty(); IDocument[] documents= getDocuments(); LinkedModeManager manager= LinkedModeManager.getLinkedManager(documents, force); // if we force creation, we require a valid manager Assert.isTrue(!(force && manager == null)); if (manager == null) return false; if (!manager.nestEnvironment(this, force)) if (force) Assert.isTrue(false); else return false; // we set up successfully. After this point, exit has to be called to // remove registered listeners... fIsSealed= true; if (fParentEnvironment != null) fParentEnvironment.suspend(); // register positions try { for (LinkedPositionGroup group : fGroups) { group.register(this); } return true; } catch (BadLocationException e){ // if we fail to add, make sure to release all listeners again exit(ILinkedModeListener.NONE); throw e; } }
Asserts that there is at least one linked position in this linked mode model, throws an IllegalStateException otherwise.
/** * Asserts that there is at least one linked position in this linked mode * model, throws an IllegalStateException otherwise. */
private void enforceNotEmpty() { boolean hasPosition= false; for (LinkedPositionGroup linkedPositionGroup : fGroups) if (!linkedPositionGroup.isEmpty()) { hasPosition= true; break; } if (!hasPosition) throw new IllegalStateException("must specify at least one linked position"); //$NON-NLS-1$ }
Collects all the documents that contained positions are set upon.
Returns:the set of documents affected by this model
/** * Collects all the documents that contained positions are set upon. * @return the set of documents affected by this model */
private IDocument[] getDocuments() { Set<IDocument> docs= new HashSet<>(); for (LinkedPositionGroup group : fGroups) { docs.addAll(Arrays.asList(group.getDocuments())); } return docs.toArray(new IDocument[docs.size()]); }
Returns whether the receiver can be nested into the given parent model. If yes, the parent model and its position that the receiver fits in are remembered.
Params:
  • parent – the parent model candidate
Returns:true if the receiver can be nested into parent, false otherwise
/** * Returns whether the receiver can be nested into the given <code>parent</code> * model. If yes, the parent model and its position that the receiver * fits in are remembered. * * @param parent the parent model candidate * @return <code>true</code> if the receiver can be nested into <code>parent</code>, <code>false</code> otherwise */
boolean canNestInto(LinkedModeModel parent) { for (LinkedPositionGroup group : fGroups) { if (!enforceNestability(group, parent)) { fParentPosition= null; return false; } } Assert.isNotNull(fParentPosition); fParentEnvironment= parent; return true; }
Called by nested models when a group is added to them. All positions in all groups of a nested model have to fit inside a single position in the parent model.
Params:
  • group – the group of the nested model to be adopted.
  • model – the model to check against
Returns:false if it failed to enforce nestability
/** * Called by nested models when a group is added to them. All * positions in all groups of a nested model have to fit inside a * single position in the parent model. * * @param group the group of the nested model to be adopted. * @param model the model to check against * @return <code>false</code> if it failed to enforce nestability */
private boolean enforceNestability(LinkedPositionGroup group, LinkedModeModel model) { Assert.isNotNull(model); Assert.isNotNull(group); try { for (LinkedPositionGroup pg : model.fGroups) { LinkedPosition pos; pos= pg.adopt(group); if (pos != null && fParentPosition != null && fParentPosition != pos) return false; // group does not fit into one parent position, which is illegal else if (fParentPosition == null && pos != null) fParentPosition= pos; } } catch (BadLocationException e) { return false; } // group must fit into exactly one of the parent's positions return fParentPosition != null; }
Returns whether this model is nested.

This method is part of the private protocol between LinkedModeUI and LinkedModeModel.

Returns:true if this model is nested, false otherwise
/** * Returns whether this model is nested. * * <p> * This method is part of the private protocol between * <code>LinkedModeUI</code> and <code>LinkedModeModel</code>. * </p> * * @return <code>true</code> if this model is nested, * <code>false</code> otherwise */
public boolean isNested() { return fParentEnvironment != null; }
Returns the positions in this model that have a tab stop, in the order they were added.

This method is part of the private protocol between LinkedModeUI and LinkedModeModel.

Returns:the positions in this model that have a tab stop, in the order they were added
/** * Returns the positions in this model that have a tab stop, in the * order they were added. * * <p> * This method is part of the private protocol between * <code>LinkedModeUI</code> and <code>LinkedModeModel</code>. * </p> * * @return the positions in this model that have a tab stop, in the * order they were added */
public List<LinkedPosition> getTabStopSequence() { return fPositionSequence; }
Adds listener to the set of listeners that are informed upon state changes.
Params:
  • listener – the new listener
/** * Adds <code>listener</code> to the set of listeners that are informed * upon state changes. * * @param listener the new listener */
public void addLinkingListener(ILinkedModeListener listener) { Assert.isNotNull(listener); if (!fListeners.contains(listener)) fListeners.add(listener); }
Removes listener from the set of listeners that are informed upon state changes.
Params:
  • listener – the new listener
/** * Removes <code>listener</code> from the set of listeners that are * informed upon state changes. * * @param listener the new listener */
public void removeLinkingListener(ILinkedModeListener listener) { fListeners.remove(listener); }
Finds the position in this model that is closest after toFind. toFind needs not be a position in this model and serves merely as an offset.

This method part of the private protocol between LinkedModeUI and LinkedModeModel.

Params:
  • toFind – the position to search from
Returns:the closest position in the same document as toFind after the offset of toFind, or null
/** * Finds the position in this model that is closest after * <code>toFind</code>. <code>toFind</code> needs not be a position in * this model and serves merely as an offset. * * <p> * This method part of the private protocol between * <code>LinkedModeUI</code> and <code>LinkedModeModel</code>. * </p> * * @param toFind the position to search from * @return the closest position in the same document as <code>toFind</code> * after the offset of <code>toFind</code>, or <code>null</code> */
public LinkedPosition findPosition(LinkedPosition toFind) { LinkedPosition position= null; for (LinkedPositionGroup group : fGroups) { position= group.getPosition(toFind); if (position != null) break; } return position; }
Registers a LinkedPosition with this model. Called by PositionGroup.
Params:
  • position – the position to register
Throws:
/** * Registers a <code>LinkedPosition</code> with this model. Called * by <code>PositionGroup</code>. * * @param position the position to register * @throws BadLocationException if the position cannot be added to its * document */
void register(LinkedPosition position) throws BadLocationException { Assert.isNotNull(position); IDocument document= position.getDocument(); manageDocument(document); try { document.addPosition(getCategory(), position); } catch (BadPositionCategoryException e) { // won't happen as the category has been added by manageDocument() Assert.isTrue(false); } int seqNr= position.getSequenceNumber(); if (seqNr != LinkedPositionGroup.NO_STOP) { fPositionSequence.add(position); } }
Suspends this model.
/** * Suspends this model. */
private void suspend() { List<ILinkedModeListener> l= new ArrayList<>(fListeners); for (ILinkedModeListener listener : l) { listener.suspend(this); } }
Resumes this model. flags can be NONE or SELECT.
Params:
  • flags – NONE or SELECT
/** * Resumes this model. <code>flags</code> can be <code>NONE</code> * or <code>SELECT</code>. * * @param flags <code>NONE</code> or <code>SELECT</code> */
private void resume(int flags) { List<ILinkedModeListener> l= new ArrayList<>(fListeners); for (ILinkedModeListener listener : l) { listener.resume(this, flags); } }
Returns whether an offset is contained by any position in this model.
Params:
  • offset – the offset to check
Returns:true if offset is included by any position (see LinkedPosition.includes(int)) in this model, false otherwise
/** * Returns whether an offset is contained by any position in this * model. * * @param offset the offset to check * @return <code>true</code> if <code>offset</code> is included by any * position (see {@link LinkedPosition#includes(int)}) in this * model, <code>false</code> otherwise */
public boolean anyPositionContains(int offset) { for (LinkedPositionGroup group : fGroups) { if (group.contains(offset)) // take the first hit - exclusion is guaranteed by enforcing // disjointness when adding positions return true; } return false; }
Returns the linked position group that contains position, or null if position is not contained in any group within this model. Group containment is tested by calling group.contains(position) for every group in this model.

This method part of the private protocol between LinkedModeUI and LinkedModeModel.

Params:
  • position – the position the group of which is requested
Returns:the first group in this model for which group.contains(position) returns true, or null if no group contains position
/** * Returns the linked position group that contains <code>position</code>, * or <code>null</code> if <code>position</code> is not contained in any * group within this model. Group containment is tested by calling * <code>group.contains(position)</code> for every <code>group</code> in * this model. * * <p> * This method part of the private protocol between * <code>LinkedModeUI</code> and <code>LinkedModeModel</code>. * </p> * * @param position the position the group of which is requested * @return the first group in this model for which * <code>group.contains(position)</code> returns <code>true</code>, * or <code>null</code> if no group contains <code>position</code> */
public LinkedPositionGroup getGroupForPosition(Position position) { for (LinkedPositionGroup group : fGroups) { if (group.contains(position)) return group; } return null; } }