|
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 |
*/ |
| 65 |
private Object annotationModelLock; |
| 66 |
|
| 67 |
/** |
| 68 |
* Annotation for remote selection in annotationModel |
| 69 |
*/ |
| 70 |
private Annotation currentAnnotation; |
| 71 |
|
| 72 |
public SelectionReceiver(ITextEditor editor) { |
| 73 |
if (editor == null) { |
| 74 |
return; |
| 75 |
} |
| 76 |
IDocumentProvider documentProvider = editor.getDocumentProvider(); |
| 77 |
if (documentProvider != null) { |
| 78 |
this.annotationModel = documentProvider.getAnnotationModel(editor.getEditorInput()); |
| 79 |
} |
| 80 |
if (this.annotationModel instanceof ISynchronizable) { |
| 81 |
this.annotationModelLock = ((ISynchronizable) this.annotationModel).getLockObject(); |
| 82 |
} |
| 83 |
if (this.annotationModelLock == null) { |
| 84 |
this.annotationModelLock = this; |
| 85 |
} |
| 86 |
|
| 87 |
} |
| 88 |
|
| 89 |
void handleMessage(final SelectionMessage remoteMsg) { |
| 90 |
final Position newPosition = new Position(remoteMsg.getOffset(), remoteMsg.getLength()); |
| 91 |
final Annotation newAnnotation = new Annotation(newPosition.getLength() > 0 ? SELECTION_ANNOTATION_ID : CURSOR_ANNOTATION_ID, false, "Remote Selection"); |
| 92 |
if (this.annotationModel != null) { |
| 93 |
synchronized (this.annotationModelLock) { |
| 94 |
// initial selection, create new |
| 95 |
if (this.currentAnnotation == null) { |
| 96 |
this.currentAnnotation = newAnnotation; |
| 97 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 98 |
return; |
| 99 |
} |
| 100 |
// selection not changed, skip |
| 101 |
if (this.currentAnnotation.getType() == newAnnotation.getType()) { |
| 102 |
Position oldPosition = this.annotationModel.getPosition(this.currentAnnotation); |
| 103 |
if (oldPosition == null || newPosition.equals(oldPosition)) { |
| 104 |
return; |
| 105 |
} |
| 106 |
} |
| 107 |
// selection changed, replace annotation |
| 108 |
if (this.annotationModel instanceof IAnnotationModelExtension) { |
| 109 |
Annotation[] oldAnnotations = new Annotation[] {this.currentAnnotation}; |
| 110 |
this.currentAnnotation = newAnnotation; |
| 111 |
Map newAnnotations = new TreeMap(); |
| 112 |
newAnnotations.put(newAnnotation, newPosition); |
| 113 |
((IAnnotationModelExtension) this.annotationModel).replaceAnnotations(oldAnnotations, newAnnotations); |
| 114 |
} else { |
| 115 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 116 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
| 117 |
} |
| 118 |
} |
| 119 |
} |
| 120 |
} |
| 121 |
|
| 122 |
void dispose() { |
| 123 |
if (this.annotationModel != null) { |
| 124 |
synchronized (this.annotationModelLock) { |
| 125 |
if (this.currentAnnotation != null) { |
| 126 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
| 127 |
this.currentAnnotation = null; |
| 128 |
} |
| 129 |
} |
| 130 |
} |
| 131 |
} |
| 132 |
|
| 133 |
} |
| 134 |
|
| 51 |
/** |
135 |
/** |
| 52 |
* The ID of the initiator |
136 |
* The ID of the initiator |
| 53 |
*/ |
137 |
*/ |
|
Lines 83-88
Link Here
|
| 83 |
// TODO provide for a user-interactive selection mechanism |
167 |
// TODO provide for a user-interactive selection mechanism |
| 84 |
SynchronizationStrategy sync; |
168 |
SynchronizationStrategy sync; |
| 85 |
|
169 |
|
|
|
170 |
SelectionReceiver selectionReceiver; |
| 171 |
|
| 86 |
/** |
172 |
/** |
| 87 |
* The document listener is the listener for changes to the *local* copy of |
173 |
* The document listener is the listener for changes to the *local* copy of |
| 88 |
* the IDocument. This listener is responsible for sending document update |
174 |
* the IDocument. This listener is responsible for sending document update |
|
Lines 131-136
Link Here
|
| 131 |
} |
217 |
} |
| 132 |
}; |
218 |
}; |
| 133 |
|
219 |
|
|
|
220 |
ISelectionChangedListener selectionListener = new ISelectionChangedListener() { |
| 221 |
|
| 222 |
public void selectionChanged(final SelectionChangedEvent event) { |
| 223 |
// If the channel is gone, then no reason to handle this. |
| 224 |
if (getChannel() == null || !Activator.getDefault().isListenerActive()) { |
| 225 |
return; |
| 226 |
} |
| 227 |
// If the listener is not active, ignore input |
| 228 |
if (!Activator.getDefault().isListenerActive()) { |
| 229 |
// The local editor is being updated by a remote peer, so we do |
| 230 |
// not |
| 231 |
// wish to echo this change. |
| 232 |
return; |
| 233 |
} |
| 234 |
Trace.trace(Activator.PLUGIN_ID, NLS.bind("{0}.selectionChanged[{1}]", DocShare.this, event)); //$NON-NLS-1$ |
| 235 |
|
| 236 |
if (!(event.getSelection() instanceof ITextSelection)) { |
| 237 |
return; |
| 238 |
} |
| 239 |
final ITextSelection textSelection = (ITextSelection) event.getSelection(); |
| 240 |
final SelectionMessage msg = new SelectionMessage(textSelection.getOffset(), textSelection.getLength()); |
| 241 |
|
| 242 |
sendSelectionMsg(msg); |
| 243 |
} |
| 244 |
|
| 245 |
}; |
| 246 |
|
| 134 |
/** |
247 |
/** |
| 135 |
* Create a document sharing session instance. |
248 |
* Create a document sharing session instance. |
| 136 |
* |
249 |
* |
|
Lines 255-260
Link Here
|
| 255 |
handleStartMessage((StartMessage) message); |
368 |
handleStartMessage((StartMessage) message); |
| 256 |
} else if (message instanceof UpdateMessage) { |
369 |
} else if (message instanceof UpdateMessage) { |
| 257 |
handleUpdateMessage((UpdateMessage) message); |
370 |
handleUpdateMessage((UpdateMessage) message); |
|
|
371 |
} else if (message instanceof SelectionMessage) { |
| 372 |
SelectionReceiver receiver = selectionReceiver; |
| 373 |
if (receiver != null) { |
| 374 |
receiver.handleMessage((SelectionMessage) message); |
| 375 |
} |
| 258 |
} else if (message instanceof StopMessage) { |
376 |
} else if (message instanceof StopMessage) { |
| 259 |
handleStopMessage((StopMessage) message); |
377 |
handleStopMessage((StopMessage) message); |
| 260 |
} else { |
378 |
} else { |
|
Lines 499-504
Link Here
|
| 499 |
final IDocument doc = getDocumentFromEditor(); |
617 |
final IDocument doc = getDocumentFromEditor(); |
| 500 |
if (doc != null) |
618 |
if (doc != null) |
| 501 |
doc.addDocumentListener(documentListener); |
619 |
doc.addDocumentListener(documentListener); |
|
|
620 |
if (this.editor != null) { |
| 621 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 622 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 623 |
((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(selectionListener); |
| 624 |
} |
| 625 |
selectionReceiver = new SelectionReceiver(this.editor); |
| 626 |
} |
| 502 |
} |
627 |
} |
| 503 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
628 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
| 504 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
629 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
|
Lines 508-513
Link Here
|
| 508 |
} |
633 |
} |
| 509 |
|
634 |
|
| 510 |
void localStopShare() { |
635 |
void localStopShare() { |
|
|
636 |
SelectionReceiver oldSelectionReceiver; |
| 511 |
synchronized (stateLock) { |
637 |
synchronized (stateLock) { |
| 512 |
this.ourID = null; |
638 |
this.ourID = null; |
| 513 |
this.initiatorID = null; |
639 |
this.initiatorID = null; |
|
Lines 516-523
Link Here
|
| 516 |
final IDocument doc = getDocumentFromEditor(); |
642 |
final IDocument doc = getDocumentFromEditor(); |
| 517 |
if (doc != null) |
643 |
if (doc != null) |
| 518 |
doc.removeDocumentListener(documentListener); |
644 |
doc.removeDocumentListener(documentListener); |
|
|
645 |
if (this.editor != null) { |
| 646 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
| 647 |
if (selectionProvider instanceof IPostSelectionProvider) { |
| 648 |
((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(selectionListener); |
| 649 |
} |
| 650 |
} |
| 651 |
oldSelectionReceiver = this.selectionReceiver; |
| 652 |
this.selectionReceiver = null; |
| 519 |
this.editor = null; |
653 |
this.editor = null; |
| 520 |
} |
654 |
} |
|
|
655 |
|
| 656 |
if (oldSelectionReceiver != null) { |
| 657 |
oldSelectionReceiver.dispose(); |
| 658 |
} |
| 521 |
// clean up if necessary |
659 |
// clean up if necessary |
| 522 |
// TODO abstract this to work for SynchronizationStrategy |
660 |
// TODO abstract this to work for SynchronizationStrategy |
| 523 |
ColaSynchronizer.cleanUpFor(this); |
661 |
ColaSynchronizer.cleanUpFor(this); |
|
Lines 534-539
Link Here
|
| 534 |
} |
672 |
} |
| 535 |
} |
673 |
} |
| 536 |
|
674 |
|
|
|
675 |
void sendSelectionMsg(SelectionMessage msg) { |
| 676 |
if (isSharing()) { |
| 677 |
try { |
| 678 |
send(getOtherID(), msg); |
| 679 |
} catch (final Exception e) { |
| 680 |
logError(Messages.DocShare_EXCEPTION_SEND_MESSAGE, e); |
| 681 |
} |
| 682 |
} |
| 683 |
} |
| 684 |
|
| 537 |
void sendStopMessage() { |
685 |
void sendStopMessage() { |
| 538 |
sendStopMessage(getOtherID()); |
686 |
sendStopMessage(getOtherID()); |
| 539 |
} |
687 |
} |