|
Lines 15-20
Link Here
|
| 15 |
package org.eclipse.ecf.docshare; |
15 |
package org.eclipse.ecf.docshare; |
| 16 |
|
16 |
|
| 17 |
import java.io.*; |
17 |
import java.io.*; |
|
|
18 |
import java.util.Collections; |
| 19 |
import java.util.Map; |
| 18 |
import org.eclipse.core.filesystem.EFS; |
20 |
import org.eclipse.core.filesystem.EFS; |
| 19 |
import org.eclipse.core.filesystem.IFileStore; |
21 |
import org.eclipse.core.filesystem.IFileStore; |
| 20 |
import org.eclipse.core.runtime.*; |
22 |
import org.eclipse.core.runtime.*; |
|
Lines 36-41
Link Here
|
| 36 |
import org.eclipse.ecf.sync.doc.IDocumentSynchronizationStrategyFactory; |
38 |
import org.eclipse.ecf.sync.doc.IDocumentSynchronizationStrategyFactory; |
| 37 |
import org.eclipse.jface.dialogs.MessageDialog; |
39 |
import org.eclipse.jface.dialogs.MessageDialog; |
| 38 |
import org.eclipse.jface.text.*; |
40 |
import org.eclipse.jface.text.*; |
|
|
41 |
import org.eclipse.jface.text.source.*; |
| 42 |
import org.eclipse.jface.viewers.*; |
| 39 |
import org.eclipse.osgi.util.NLS; |
43 |
import org.eclipse.osgi.util.NLS; |
| 40 |
import org.eclipse.swt.custom.StyledText; |
44 |
import org.eclipse.swt.custom.StyledText; |
| 41 |
import org.eclipse.swt.widgets.*; |
45 |
import org.eclipse.swt.widgets.*; |
|
Lines 50-55
Link Here
|
| 50 |
*/ |
54 |
*/ |
| 51 |
public class DocShare extends AbstractShare { |
55 |
public class DocShare extends AbstractShare { |
| 52 |
|
56 |
|
|
|
57 |
public static class SelectionReceiver { |
| 58 |
|
| 59 |
private static final String SELECTION_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteSelection"; //$NON-NLS-1$ |
| 60 |
private static final String CURSOR_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteCursor"; //$NON-NLS-1$ |
| 61 |
|
| 62 |
/** |
| 63 |
* Annotation model of current document |
| 64 |
*/ |
| 65 |
private IAnnotationModel annotationModel; |
| 66 |
|
| 67 |
/** |
| 68 |
* Object to use as lock for changing in annotation model, |
| 69 |
* <code>null</code> if no model is provided. |
| 70 |
*/ |
| 71 |
private Object annotationModelLock; |
| 72 |
|
| 73 |
/** |
| 74 |
* Annotation for remote selection in annotationModel |
| 75 |
*/ |
| 76 |
private Annotation currentAnnotation; |
| 77 |
|
| 78 |
public SelectionReceiver(ITextEditor editor) { |
| 79 |
if (editor == null) { |
| 80 |
return; |
| 81 |
} |
| 82 |
IDocumentProvider documentProvider = editor.getDocumentProvider(); |
| 83 |
if (documentProvider != null) { |
| 84 |
this.annotationModel = documentProvider.getAnnotationModel(editor.getEditorInput()); |
| 85 |
if (this.annotationModel != null) { |
| 86 |
if (this.annotationModel instanceof ISynchronizable) { |
| 87 |
this.annotationModelLock = ((ISynchronizable) this.annotationModel).getLockObject(); |
| 88 |
} |
| 89 |
if (this.annotationModelLock == null) { |
| 90 |
this.annotationModelLock = this; |
| 91 |
} |
| 92 |
} |
| 93 |
} |
| 94 |
} |
| 95 |
|
| 96 |
public void handleMessage(final SelectionMessage remoteMsg) { |
| 97 |
if (this.annotationModelLock == null) { |
| 98 |
return; |
| 99 |
} |
| 100 |
final Position newPosition = new Position(remoteMsg.getOffset(), remoteMsg.getLength()); |
| 101 |
final Annotation newAnnotation = new Annotation(newPosition.getLength() > 0 ? SELECTION_ANNOTATION_ID : CURSOR_ANNOTATION_ID, false, "Remote Selection"); |
| 102 |
synchronized (this.annotationModelLock) { |
| 103 |
if (this.annotationModel != null) { |
| 104 |
// initial selection, create new |
| 105 |
if (this.currentAnnotation == null) { |
| 106 |
this.currentAnnotation = newAnnotation; |
| 107 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 108 |
return; |
| 109 |
} |
| 110 |
// selection not changed, skip |
| 111 |
if (this.currentAnnotation.getType() == newAnnotation.getType()) { |
| 112 |
Position oldPosition = this.annotationModel.getPosition(this.currentAnnotation); |
| 113 |
if (oldPosition == null || newPosition.equals(oldPosition)) { |
| 114 |
return; |
| 115 |
} |
| 116 |
} |
| 117 |
// selection changed, replace annotation |
| 118 |
if (this.annotationModel instanceof IAnnotationModelExtension) { |
| 119 |
Annotation[] oldAnnotations = new Annotation[] {this.currentAnnotation}; |
| 120 |
this.currentAnnotation = newAnnotation; |
| 121 |
Map newAnnotations = Collections.singletonMap(newAnnotation, newPosition); |
| 122 |
((IAnnotationModelExtension) this.annotationModel).replaceAnnotations(oldAnnotations, newAnnotations); |
| 123 |
} else { |
| 124 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 125 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 126 |
} |
| 127 |
} |
| 128 |
} |
| 129 |
} |
| 130 |
|
| 131 |
public void dispose() { |
| 132 |
if (this.annotationModelLock == null) { |
| 133 |
return; |
| 134 |
} |
| 135 |
synchronized (this.annotationModelLock) { |
| 136 |
if (this.annotationModel != null) { |
| 137 |
if (this.currentAnnotation != null) { |
| 138 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 139 |
this.currentAnnotation = null; |
| 140 |
} |
| 141 |
this.annotationModel = null; |
| 142 |
} |
| 143 |
} |
| 144 |
} |
| 145 |
|
| 146 |
} |
| 147 |
|
| 53 |
/** |
148 |
/** |
| 54 |
* The ID of the initiator |
149 |
* The ID of the initiator |
| 55 |
*/ |
150 |
*/ |
|
Lines 91-96
Link Here
|
| 91 |
IDocumentSynchronizationStrategyFactory factory; |
186 |
IDocumentSynchronizationStrategyFactory factory; |
| 92 |
|
187 |
|
| 93 |
/** |
188 |
/** |
|
|
189 |
* Handler for SelectionMessage (painting remote selection) |
| 190 |
*/ |
| 191 |
SelectionReceiver selectionReceiver; |
| 192 |
|
| 193 |
/** |
| 94 |
* Create a document sharing session instance. |
194 |
* Create a document sharing session instance. |
| 95 |
* |
195 |
* |
| 96 |
* @param adapter |
196 |
* @param adapter |
|
Lines 210-215
Link Here
|
| 210 |
} |
310 |
} |
| 211 |
}; |
311 |
}; |
| 212 |
|
312 |
|
|
|
313 |
ISelectionChangedListener selectionListener = new ISelectionChangedListener() { |
| 314 |
|
| 315 |
public void selectionChanged(final SelectionChangedEvent event) { |
| 316 |
// If the channel is gone, then no reason to handle this. |
| 317 |
if (getChannel() == null || !Activator.getDefault().isListenerActive()) { |
| 318 |
return; |
| 319 |
} |
| 320 |
// If the listener is not active, ignore input |
| 321 |
if (!Activator.getDefault().isListenerActive()) { |
| 322 |
// The local editor is being updated by a remote peer, so we do |
| 323 |
// not |
| 324 |
// wish to echo this change. |
| 325 |
return; |
| 326 |
} |
| 327 |
Trace.trace(Activator.PLUGIN_ID, NLS.bind("{0}.selectionChanged[{1}]", DocShare.this, event)); //$NON-NLS-1$ |
| 328 |
|
| 329 |
if (!(event.getSelection() instanceof ITextSelection)) { |
| 330 |
return; |
| 331 |
} |
| 332 |
final ITextSelection textSelection = (ITextSelection) event.getSelection(); |
| 333 |
final SelectionMessage msg = new SelectionMessage(textSelection.getOffset(), textSelection.getLength()); |
| 334 |
|
| 335 |
try { |
| 336 |
sendMessage(getOtherID(), msg.serialize()); |
| 337 |
} catch (final Exception e) { |
| 338 |
logError(Messages.DocShare_EXCEPTION_SEND_MESSAGE, e); |
| 339 |
} |
| 340 |
} |
| 341 |
|
| 342 |
}; |
| 343 |
|
| 213 |
/** |
344 |
/** |
| 214 |
* Start sharing an editor's contents between two participants. This will |
345 |
* Start sharing an editor's contents between two participants. This will |
| 215 |
* send a request to start sharing with the target identified by the |
346 |
* send a request to start sharing with the target identified by the |
|
Lines 283-288
Link Here
|
| 283 |
|
414 |
|
| 284 |
if (message instanceof DocumentChangeMessage) { |
415 |
if (message instanceof DocumentChangeMessage) { |
| 285 |
handleUpdateMessage((DocumentChangeMessage) message); |
416 |
handleUpdateMessage((DocumentChangeMessage) message); |
|
|
417 |
} else if (message instanceof SelectionMessage) { |
| 418 |
SelectionReceiver receiver = selectionReceiver; |
| 419 |
if (receiver != null) { |
| 420 |
receiver.handleMessage((SelectionMessage) message); |
| 421 |
} |
| 286 |
} else if (message instanceof StartMessage) { |
422 |
} else if (message instanceof StartMessage) { |
| 287 |
handleStartMessage((StartMessage) message); |
423 |
handleStartMessage((StartMessage) message); |
| 288 |
} else if (message instanceof StopMessage) { |
424 |
} else if (message instanceof StopMessage) { |
|
Lines 590-600
Link Here
|
| 590 |
final IDocument doc = getDocumentFromEditor(); |
726 |
final IDocument doc = getDocumentFromEditor(); |
| 591 |
if (doc != null) |
727 |
if (doc != null) |
| 592 |
doc.addDocumentListener(documentListener); |
728 |
doc.addDocumentListener(documentListener); |
|
|
729 |
if (this.editor != null) { |
| 730 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 731 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 732 |
((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(selectionListener); |
| 733 |
} |
| 734 |
selectionReceiver = new SelectionReceiver(this.editor); |
| 735 |
} |
| 593 |
} |
736 |
} |
| 594 |
|
737 |
|
| 595 |
} |
738 |
} |
| 596 |
|
739 |
|
| 597 |
void localStopShare() { |
740 |
void localStopShare() { |
|
|
741 |
SelectionReceiver oldSelectionReceiver; |
| 598 |
synchronized (stateLock) { |
742 |
synchronized (stateLock) { |
| 599 |
if (rosterManager != null) |
743 |
if (rosterManager != null) |
| 600 |
rosterManager.removeRosterListener(rosterListener); |
744 |
rosterManager.removeRosterListener(rosterListener); |
|
Lines 606-617
Link Here
|
| 606 |
final IDocument doc = getDocumentFromEditor(); |
750 |
final IDocument doc = getDocumentFromEditor(); |
| 607 |
if (doc != null) |
751 |
if (doc != null) |
| 608 |
doc.removeDocumentListener(documentListener); |
752 |
doc.removeDocumentListener(documentListener); |
| 609 |
if (editor != null) { |
753 |
if (this.editor != null) { |
| 610 |
editor.getSite().getPage().removePartListener(partListener); |
754 |
this.editor.getSite().getPage().removePartListener(partListener); |
|
|
755 |
|
| 756 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 757 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 758 |
((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(selectionListener); |
| 759 |
} |
| 611 |
} |
760 |
} |
|
|
761 |
oldSelectionReceiver = this.selectionReceiver; |
| 762 |
this.selectionReceiver = null; |
| 763 |
|
| 612 |
this.editor = null; |
764 |
this.editor = null; |
| 613 |
} |
765 |
} |
| 614 |
|
766 |
|
|
|
767 |
if (oldSelectionReceiver != null) { |
| 768 |
oldSelectionReceiver.dispose(); |
| 769 |
} |
| 615 |
} |
770 |
} |
| 616 |
|
771 |
|
| 617 |
void sendStopMessage() { |
772 |
void sendStopMessage() { |