### Eclipse Workspace Patch 1.0 #P org.eclipse.ecf.internal.provisional.docshare Index: src/org/eclipse/ecf/internal/provisional/docshare/DocShare.java =================================================================== RCS file: /cvsroot/technology/org.eclipse.ecf/plugins/org.eclipse.ecf.docshare/src/org/eclipse/ecf/internal/provisional/docshare/DocShare.java,v retrieving revision 1.4 diff -u -r1.4 DocShare.java --- src/org/eclipse/ecf/internal/provisional/docshare/DocShare.java 16 Jun 2008 16:33:45 -0000 1.4 +++ src/org/eclipse/ecf/internal/provisional/docshare/DocShare.java 18 Jul 2008 08:52:03 -0000 @@ -13,8 +13,7 @@ package org.eclipse.ecf.internal.provisional.docshare; import java.io.*; -import java.util.Iterator; -import java.util.List; +import java.util.*; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.*; @@ -31,6 +30,8 @@ import org.eclipse.ecf.internal.provisional.docshare.messages.*; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.*; +import org.eclipse.jface.text.source.*; +import org.eclipse.jface.viewers.*; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Control; @@ -48,6 +49,97 @@ */ public class DocShare extends AbstractShare { + private static class SelectionReceiver { + + private static final String SELECTION_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteSelection"; //$NON-NLS-1$ + private static final String CURSOR_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteCursor"; //$NON-NLS-1$ + + /** + * Annotation model of current document + */ + private IAnnotationModel annotationModel; + + /** + * Object to use as lock for changing in annotation model, + * null if no model is provided. + */ + private Object annotationModelLock; + + /** + * Annotation for remote selection in annotationModel + */ + private Annotation currentAnnotation; + + public SelectionReceiver(ITextEditor editor) { + if (editor == null) { + return; + } + IDocumentProvider documentProvider = editor.getDocumentProvider(); + if (documentProvider != null) { + this.annotationModel = documentProvider.getAnnotationModel(editor.getEditorInput()); + if (this.annotationModel != null) { + if (this.annotationModel instanceof ISynchronizable) { + this.annotationModelLock = ((ISynchronizable) this.annotationModel).getLockObject(); + } + if (this.annotationModelLock == null) { + this.annotationModelLock = this; + } + } + } + } + + void handleMessage(final SelectionMessage remoteMsg) { + if (this.annotationModelLock == null) { + return; + } + final Position newPosition = new Position(remoteMsg.getOffset(), remoteMsg.getLength()); + final Annotation newAnnotation = new Annotation(newPosition.getLength() > 0 ? SELECTION_ANNOTATION_ID : CURSOR_ANNOTATION_ID, false, "Remote Selection"); + synchronized (this.annotationModelLock) { + if (this.annotationModel != null) { + // initial selection, create new + if (this.currentAnnotation == null) { + this.currentAnnotation = newAnnotation; + this.annotationModel.addAnnotation(newAnnotation, newPosition); + return; + } + // selection not changed, skip + if (this.currentAnnotation.getType() == newAnnotation.getType()) { + Position oldPosition = this.annotationModel.getPosition(this.currentAnnotation); + if (oldPosition == null || newPosition.equals(oldPosition)) { + return; + } + } + // selection changed, replace annotation + if (this.annotationModel instanceof IAnnotationModelExtension) { + Annotation[] oldAnnotations = new Annotation[] {this.currentAnnotation}; + this.currentAnnotation = newAnnotation; + Map newAnnotations = Collections.singletonMap(newAnnotation, newPosition); + ((IAnnotationModelExtension) this.annotationModel).replaceAnnotations(oldAnnotations, newAnnotations); + } else { + this.annotationModel.removeAnnotation(this.currentAnnotation); + this.annotationModel.addAnnotation(newAnnotation, newPosition); + } + } + } + } + + void dispose() { + if (this.annotationModelLock == null) { + return; + } + synchronized (this.annotationModelLock) { + if (this.annotationModel != null) { + if (this.currentAnnotation != null) { + this.annotationModel.removeAnnotation(this.currentAnnotation); + this.currentAnnotation = null; + } + this.annotationModel = null; + } + } + } + + } + /** * The ID of the initiator */ @@ -83,6 +175,8 @@ // TODO provide for a user-interactive selection mechanism SynchronizationStrategy sync; + SelectionReceiver selectionReceiver; + /** * The document listener is the listener for changes to the *local* copy of * the IDocument. This listener is responsible for sending document update @@ -131,6 +225,33 @@ } }; + ISelectionChangedListener selectionListener = new ISelectionChangedListener() { + + public void selectionChanged(final SelectionChangedEvent event) { + // If the channel is gone, then no reason to handle this. + if (getChannel() == null || !Activator.getDefault().isListenerActive()) { + return; + } + // If the listener is not active, ignore input + if (!Activator.getDefault().isListenerActive()) { + // The local editor is being updated by a remote peer, so we do + // not + // wish to echo this change. + return; + } + Trace.trace(Activator.PLUGIN_ID, NLS.bind("{0}.selectionChanged[{1}]", DocShare.this, event)); //$NON-NLS-1$ + + if (!(event.getSelection() instanceof ITextSelection)) { + return; + } + final ITextSelection textSelection = (ITextSelection) event.getSelection(); + final SelectionMessage msg = new SelectionMessage(textSelection.getOffset(), textSelection.getLength()); + + sendSelectionMsg(msg); + } + + }; + /** * Create a document sharing session instance. * @@ -255,6 +376,11 @@ handleStartMessage((StartMessage) message); } else if (message instanceof UpdateMessage) { handleUpdateMessage((UpdateMessage) message); + } else if (message instanceof SelectionMessage) { + SelectionReceiver receiver = selectionReceiver; + if (receiver != null) { + receiver.handleMessage((SelectionMessage) message); + } } else if (message instanceof StopMessage) { handleStopMessage((StopMessage) message); } else { @@ -499,6 +625,13 @@ final IDocument doc = getDocumentFromEditor(); if (doc != null) doc.addDocumentListener(documentListener); + if (this.editor != null) { + ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + ((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(selectionListener); + } + selectionReceiver = new SelectionReceiver(this.editor); + } } // used to have the ColaSynchronizer.getInstanceFor(...) call here ... // TODO needs to be moved to a more appropriate spot, where ColaSynch'er @@ -508,6 +641,7 @@ } void localStopShare() { + SelectionReceiver oldSelectionReceiver; synchronized (stateLock) { this.ourID = null; this.initiatorID = null; @@ -516,8 +650,20 @@ final IDocument doc = getDocumentFromEditor(); if (doc != null) doc.removeDocumentListener(documentListener); + if (this.editor != null) { + ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + ((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(selectionListener); + } + } + oldSelectionReceiver = this.selectionReceiver; + this.selectionReceiver = null; this.editor = null; } + + if (oldSelectionReceiver != null) { + oldSelectionReceiver.dispose(); + } // clean up if necessary // TODO abstract this to work for SynchronizationStrategy ColaSynchronizer.cleanUpFor(this); @@ -534,6 +680,16 @@ } } + void sendSelectionMsg(SelectionMessage msg) { + if (isSharing()) { + try { + send(getOtherID(), msg); + } catch (final Exception e) { + logError(Messages.DocShare_EXCEPTION_SEND_MESSAGE, e); + } + } + } + void sendStopMessage() { sendStopMessage(getOtherID()); } Index: plugin.xml =================================================================== RCS file: /cvsroot/technology/org.eclipse.ecf/plugins/org.eclipse.ecf.docshare/plugin.xml,v retrieving revision 1.4 diff -u -r1.4 plugin.xml --- plugin.xml 16 Jun 2008 04:58:27 -0000 1.4 +++ plugin.xml 18 Jul 2008 08:52:02 -0000 @@ -29,5 +29,53 @@ + + + + + + + + + + + + +