|
Lines 13-20
Link Here
|
| 13 |
package org.eclipse.ecf.internal.provisional.docshare; |
13 |
package org.eclipse.ecf.internal.provisional.docshare; |
| 14 |
|
14 |
|
| 15 |
import java.io.*; |
15 |
import java.io.*; |
| 16 |
import java.util.Iterator; |
16 |
import java.util.*; |
| 17 |
import java.util.List; |
|
|
| 18 |
import org.eclipse.core.filesystem.EFS; |
17 |
import org.eclipse.core.filesystem.EFS; |
| 19 |
import org.eclipse.core.filesystem.IFileStore; |
18 |
import org.eclipse.core.filesystem.IFileStore; |
| 20 |
import org.eclipse.core.runtime.*; |
19 |
import org.eclipse.core.runtime.*; |
|
Lines 31-36
Link Here
|
| 31 |
import org.eclipse.ecf.internal.provisional.docshare.messages.*; |
30 |
import org.eclipse.ecf.internal.provisional.docshare.messages.*; |
| 32 |
import org.eclipse.jface.dialogs.MessageDialog; |
31 |
import org.eclipse.jface.dialogs.MessageDialog; |
| 33 |
import org.eclipse.jface.text.*; |
32 |
import org.eclipse.jface.text.*; |
|
|
33 |
import org.eclipse.jface.text.source.*; |
| 34 |
import org.eclipse.jface.viewers.*; |
| 34 |
import org.eclipse.osgi.util.NLS; |
35 |
import org.eclipse.osgi.util.NLS; |
| 35 |
import org.eclipse.swt.custom.StyledText; |
36 |
import org.eclipse.swt.custom.StyledText; |
| 36 |
import org.eclipse.swt.widgets.Control; |
37 |
import org.eclipse.swt.widgets.Control; |
|
Lines 48-53
Link Here
|
| 48 |
*/ |
49 |
*/ |
| 49 |
public class DocShare extends AbstractShare { |
50 |
public class DocShare extends AbstractShare { |
| 50 |
|
51 |
|
|
|
52 |
private static class SelectionReceiver { |
| 53 |
|
| 54 |
private static final String SELECTION_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteSelection"; //$NON-NLS-1$ |
| 55 |
private static final String CURSOR_ANNOTATION_ID = "org.eclipse.ecf.docshare.annotations.RemoteCursor"; //$NON-NLS-1$ |
| 56 |
|
| 57 |
/** |
| 58 |
* Annotation model of current document |
| 59 |
*/ |
| 60 |
private IAnnotationModel annotationModel; |
| 61 |
|
| 62 |
/** |
| 63 |
* Object to use as lock for changing in annotation model, |
| 64 |
* <code>null</code> if no model is provided. |
| 65 |
*/ |
| 66 |
private Object annotationModelLock; |
| 67 |
|
| 68 |
/** |
| 69 |
* Annotation for remote selection in annotationModel |
| 70 |
*/ |
| 71 |
private Annotation currentAnnotation; |
| 72 |
|
| 73 |
public SelectionReceiver(ITextEditor editor) { |
| 74 |
if (editor == null) { |
| 75 |
return; |
| 76 |
} |
| 77 |
IDocumentProvider documentProvider = editor.getDocumentProvider(); |
| 78 |
if (documentProvider != null) { |
| 79 |
this.annotationModel = documentProvider.getAnnotationModel(editor.getEditorInput()); |
| 80 |
if (this.annotationModel != null) { |
| 81 |
if (this.annotationModel instanceof ISynchronizable) { |
| 82 |
this.annotationModelLock = ((ISynchronizable) this.annotationModel).getLockObject(); |
| 83 |
} |
| 84 |
if (this.annotationModelLock == null) { |
| 85 |
this.annotationModelLock = this; |
| 86 |
} |
| 87 |
} |
| 88 |
} |
| 89 |
} |
| 90 |
|
| 91 |
void handleMessage(final SelectionMessage remoteMsg) { |
| 92 |
if (this.annotationModelLock == null) { |
| 93 |
return; |
| 94 |
} |
| 95 |
final Position newPosition = new Position(remoteMsg.getOffset(), remoteMsg.getLength()); |
| 96 |
final Annotation newAnnotation = new Annotation(newPosition.getLength() > 0 ? SELECTION_ANNOTATION_ID : CURSOR_ANNOTATION_ID, false, "Remote Selection"); |
| 97 |
synchronized (this.annotationModelLock) { |
| 98 |
if (this.annotationModel != null) { |
| 99 |
// initial selection, create new |
| 100 |
if (this.currentAnnotation == null) { |
| 101 |
this.currentAnnotation = newAnnotation; |
| 102 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 103 |
return; |
| 104 |
} |
| 105 |
// selection not changed, skip |
| 106 |
if (this.currentAnnotation.getType() == newAnnotation.getType()) { |
| 107 |
Position oldPosition = this.annotationModel.getPosition(this.currentAnnotation); |
| 108 |
if (oldPosition == null || newPosition.equals(oldPosition)) { |
| 109 |
return; |
| 110 |
} |
| 111 |
} |
| 112 |
// selection changed, replace annotation |
| 113 |
if (this.annotationModel instanceof IAnnotationModelExtension) { |
| 114 |
Annotation[] oldAnnotations = new Annotation[] {this.currentAnnotation}; |
| 115 |
this.currentAnnotation = newAnnotation; |
| 116 |
Map newAnnotations = Collections.singletonMap(newAnnotation, newPosition); |
| 117 |
((IAnnotationModelExtension) this.annotationModel).replaceAnnotations(oldAnnotations, newAnnotations); |
| 118 |
} else { |
| 119 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 120 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 121 |
} |
| 122 |
} |
| 123 |
} |
| 124 |
} |
| 125 |
|
| 126 |
void dispose() { |
| 127 |
if (this.annotationModelLock == null) { |
| 128 |
return; |
| 129 |
} |
| 130 |
synchronized (this.annotationModelLock) { |
| 131 |
if (this.annotationModel != null) { |
| 132 |
if (this.currentAnnotation != null) { |
| 133 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 134 |
this.currentAnnotation = null; |
| 135 |
} |
| 136 |
this.annotationModel = null; |
| 137 |
} |
| 138 |
} |
| 139 |
} |
| 140 |
|
| 141 |
} |
| 142 |
|
| 51 |
/** |
143 |
/** |
| 52 |
* The ID of the initiator |
144 |
* The ID of the initiator |
| 53 |
*/ |
145 |
*/ |
|
Lines 83-88
Link Here
|
| 83 |
// TODO provide for a user-interactive selection mechanism |
175 |
// TODO provide for a user-interactive selection mechanism |
| 84 |
SynchronizationStrategy sync; |
176 |
SynchronizationStrategy sync; |
| 85 |
|
177 |
|
|
|
178 |
SelectionReceiver selectionReceiver; |
| 179 |
|
| 86 |
/** |
180 |
/** |
| 87 |
* The document listener is the listener for changes to the *local* copy of |
181 |
* The document listener is the listener for changes to the *local* copy of |
| 88 |
* the IDocument. This listener is responsible for sending document update |
182 |
* the IDocument. This listener is responsible for sending document update |
|
Lines 131-136
Link Here
|
| 131 |
} |
225 |
} |
| 132 |
}; |
226 |
}; |
| 133 |
|
227 |
|
|
|
228 |
ISelectionChangedListener selectionListener = new ISelectionChangedListener() { |
| 229 |
|
| 230 |
public void selectionChanged(final SelectionChangedEvent event) { |
| 231 |
// If the channel is gone, then no reason to handle this. |
| 232 |
if (getChannel() == null || !Activator.getDefault().isListenerActive()) { |
| 233 |
return; |
| 234 |
} |
| 235 |
// If the listener is not active, ignore input |
| 236 |
if (!Activator.getDefault().isListenerActive()) { |
| 237 |
// The local editor is being updated by a remote peer, so we do |
| 238 |
// not |
| 239 |
// wish to echo this change. |
| 240 |
return; |
| 241 |
} |
| 242 |
Trace.trace(Activator.PLUGIN_ID, NLS.bind("{0}.selectionChanged[{1}]", DocShare.this, event)); //$NON-NLS-1$ |
| 243 |
|
| 244 |
if (!(event.getSelection() instanceof ITextSelection)) { |
| 245 |
return; |
| 246 |
} |
| 247 |
final ITextSelection textSelection = (ITextSelection) event.getSelection(); |
| 248 |
final SelectionMessage msg = new SelectionMessage(textSelection.getOffset(), textSelection.getLength()); |
| 249 |
|
| 250 |
sendSelectionMsg(msg); |
| 251 |
} |
| 252 |
|
| 253 |
}; |
| 254 |
|
| 134 |
/** |
255 |
/** |
| 135 |
* Create a document sharing session instance. |
256 |
* Create a document sharing session instance. |
| 136 |
* |
257 |
* |
|
Lines 255-260
Link Here
|
| 255 |
handleStartMessage((StartMessage) message); |
376 |
handleStartMessage((StartMessage) message); |
| 256 |
} else if (message instanceof UpdateMessage) { |
377 |
} else if (message instanceof UpdateMessage) { |
| 257 |
handleUpdateMessage((UpdateMessage) message); |
378 |
handleUpdateMessage((UpdateMessage) message); |
|
|
379 |
} else if (message instanceof SelectionMessage) { |
| 380 |
SelectionReceiver receiver = selectionReceiver; |
| 381 |
if (receiver != null) { |
| 382 |
receiver.handleMessage((SelectionMessage) message); |
| 383 |
} |
| 258 |
} else if (message instanceof StopMessage) { |
384 |
} else if (message instanceof StopMessage) { |
| 259 |
handleStopMessage((StopMessage) message); |
385 |
handleStopMessage((StopMessage) message); |
| 260 |
} else { |
386 |
} else { |
|
Lines 499-504
Link Here
|
| 499 |
final IDocument doc = getDocumentFromEditor(); |
625 |
final IDocument doc = getDocumentFromEditor(); |
| 500 |
if (doc != null) |
626 |
if (doc != null) |
| 501 |
doc.addDocumentListener(documentListener); |
627 |
doc.addDocumentListener(documentListener); |
|
|
628 |
if (this.editor != null) { |
| 629 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 630 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 631 |
((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(selectionListener); |
| 632 |
} |
| 633 |
selectionReceiver = new SelectionReceiver(this.editor); |
| 634 |
} |
| 502 |
} |
635 |
} |
| 503 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
636 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
| 504 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
637 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
|
Lines 508-513
Link Here
|
| 508 |
} |
641 |
} |
| 509 |
|
642 |
|
| 510 |
void localStopShare() { |
643 |
void localStopShare() { |
|
|
644 |
SelectionReceiver oldSelectionReceiver; |
| 511 |
synchronized (stateLock) { |
645 |
synchronized (stateLock) { |
| 512 |
this.ourID = null; |
646 |
this.ourID = null; |
| 513 |
this.initiatorID = null; |
647 |
this.initiatorID = null; |
|
Lines 516-523
Link Here
|
| 516 |
final IDocument doc = getDocumentFromEditor(); |
650 |
final IDocument doc = getDocumentFromEditor(); |
| 517 |
if (doc != null) |
651 |
if (doc != null) |
| 518 |
doc.removeDocumentListener(documentListener); |
652 |
doc.removeDocumentListener(documentListener); |
|
|
653 |
if (this.editor != null) { |
| 654 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 655 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 656 |
((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(selectionListener); |
| 657 |
} |
| 658 |
} |
| 659 |
oldSelectionReceiver = this.selectionReceiver; |
| 660 |
this.selectionReceiver = null; |
| 519 |
this.editor = null; |
661 |
this.editor = null; |
| 520 |
} |
662 |
} |
|
|
663 |
|
| 664 |
if (oldSelectionReceiver != null) { |
| 665 |
oldSelectionReceiver.dispose(); |
| 666 |
} |
| 521 |
// clean up if necessary |
667 |
// clean up if necessary |
| 522 |
// TODO abstract this to work for SynchronizationStrategy |
668 |
// TODO abstract this to work for SynchronizationStrategy |
| 523 |
ColaSynchronizer.cleanUpFor(this); |
669 |
ColaSynchronizer.cleanUpFor(this); |
|
Lines 534-539
Link Here
|
| 534 |
} |
680 |
} |
| 535 |
} |
681 |
} |
| 536 |
|
682 |
|
|
|
683 |
void sendSelectionMsg(SelectionMessage msg) { |
| 684 |
if (isSharing()) { |
| 685 |
try { |
| 686 |
send(getOtherID(), msg); |
| 687 |
} catch (final Exception e) { |
| 688 |
logError(Messages.DocShare_EXCEPTION_SEND_MESSAGE, e); |
| 689 |
} |
| 690 |
} |
| 691 |
} |
| 692 |
|
| 537 |
void sendStopMessage() { |
693 |
void sendStopMessage() { |
| 538 |
sendStopMessage(getOtherID()); |
694 |
sendStopMessage(getOtherID()); |
| 539 |
} |
695 |
} |