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 = new TreeMap(); |
117 |
newAnnotations.put(newAnnotation, newPosition); |
118 |
((IAnnotationModelExtension) this.annotationModel).replaceAnnotations(oldAnnotations, newAnnotations); |
119 |
} else { |
120 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
121 |
this.annotationModel.addAnnotation(newAnnotation, newPosition); |
122 |
} |
123 |
} |
124 |
} |
125 |
} |
126 |
|
127 |
void dispose() { |
128 |
if (this.annotationModelLock == null) { |
129 |
return; |
130 |
} |
131 |
synchronized (this.annotationModelLock) { |
132 |
if (this.annotationModel != null) { |
133 |
if (this.currentAnnotation != null) { |
134 |
this.annotationModel.removeAnnotation(this.currentAnnotation); |
135 |
this.currentAnnotation = null; |
136 |
} |
137 |
this.annotationModel = null; |
138 |
} |
139 |
} |
140 |
} |
141 |
|
142 |
} |
143 |
|
51 |
/** |
144 |
/** |
52 |
* The ID of the initiator |
145 |
* The ID of the initiator |
53 |
*/ |
146 |
*/ |
Lines 83-88
Link Here
|
83 |
// TODO provide for a user-interactive selection mechanism |
176 |
// TODO provide for a user-interactive selection mechanism |
84 |
SynchronizationStrategy sync; |
177 |
SynchronizationStrategy sync; |
85 |
|
178 |
|
|
|
179 |
SelectionReceiver selectionReceiver; |
180 |
|
86 |
/** |
181 |
/** |
87 |
* The document listener is the listener for changes to the *local* copy of |
182 |
* The document listener is the listener for changes to the *local* copy of |
88 |
* the IDocument. This listener is responsible for sending document update |
183 |
* the IDocument. This listener is responsible for sending document update |
Lines 131-136
Link Here
|
131 |
} |
226 |
} |
132 |
}; |
227 |
}; |
133 |
|
228 |
|
|
|
229 |
ISelectionChangedListener selectionListener = new ISelectionChangedListener() { |
230 |
|
231 |
public void selectionChanged(final SelectionChangedEvent event) { |
232 |
// If the channel is gone, then no reason to handle this. |
233 |
if (getChannel() == null || !Activator.getDefault().isListenerActive()) { |
234 |
return; |
235 |
} |
236 |
// If the listener is not active, ignore input |
237 |
if (!Activator.getDefault().isListenerActive()) { |
238 |
// The local editor is being updated by a remote peer, so we do |
239 |
// not |
240 |
// wish to echo this change. |
241 |
return; |
242 |
} |
243 |
Trace.trace(Activator.PLUGIN_ID, NLS.bind("{0}.selectionChanged[{1}]", DocShare.this, event)); //$NON-NLS-1$ |
244 |
|
245 |
if (!(event.getSelection() instanceof ITextSelection)) { |
246 |
return; |
247 |
} |
248 |
final ITextSelection textSelection = (ITextSelection) event.getSelection(); |
249 |
final SelectionMessage msg = new SelectionMessage(textSelection.getOffset(), textSelection.getLength()); |
250 |
|
251 |
sendSelectionMsg(msg); |
252 |
} |
253 |
|
254 |
}; |
255 |
|
134 |
/** |
256 |
/** |
135 |
* Create a document sharing session instance. |
257 |
* Create a document sharing session instance. |
136 |
* |
258 |
* |
Lines 255-260
Link Here
|
255 |
handleStartMessage((StartMessage) message); |
377 |
handleStartMessage((StartMessage) message); |
256 |
} else if (message instanceof UpdateMessage) { |
378 |
} else if (message instanceof UpdateMessage) { |
257 |
handleUpdateMessage((UpdateMessage) message); |
379 |
handleUpdateMessage((UpdateMessage) message); |
|
|
380 |
} else if (message instanceof SelectionMessage) { |
381 |
SelectionReceiver receiver = selectionReceiver; |
382 |
if (receiver != null) { |
383 |
receiver.handleMessage((SelectionMessage) message); |
384 |
} |
258 |
} else if (message instanceof StopMessage) { |
385 |
} else if (message instanceof StopMessage) { |
259 |
handleStopMessage((StopMessage) message); |
386 |
handleStopMessage((StopMessage) message); |
260 |
} else { |
387 |
} else { |
Lines 499-504
Link Here
|
499 |
final IDocument doc = getDocumentFromEditor(); |
626 |
final IDocument doc = getDocumentFromEditor(); |
500 |
if (doc != null) |
627 |
if (doc != null) |
501 |
doc.addDocumentListener(documentListener); |
628 |
doc.addDocumentListener(documentListener); |
|
|
629 |
if (this.editor != null) { |
630 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
631 |
if (selectionProvider instanceof IPostSelectionProvider) { |
632 |
((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(selectionListener); |
633 |
} |
634 |
selectionReceiver = new SelectionReceiver(this.editor); |
635 |
} |
502 |
} |
636 |
} |
503 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
637 |
// used to have the ColaSynchronizer.getInstanceFor(...) call here ... |
504 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
638 |
// TODO needs to be moved to a more appropriate spot, where ColaSynch'er |
Lines 508-513
Link Here
|
508 |
} |
642 |
} |
509 |
|
643 |
|
510 |
void localStopShare() { |
644 |
void localStopShare() { |
|
|
645 |
SelectionReceiver oldSelectionReceiver; |
511 |
synchronized (stateLock) { |
646 |
synchronized (stateLock) { |
512 |
this.ourID = null; |
647 |
this.ourID = null; |
513 |
this.initiatorID = null; |
648 |
this.initiatorID = null; |
Lines 516-523
Link Here
|
516 |
final IDocument doc = getDocumentFromEditor(); |
651 |
final IDocument doc = getDocumentFromEditor(); |
517 |
if (doc != null) |
652 |
if (doc != null) |
518 |
doc.removeDocumentListener(documentListener); |
653 |
doc.removeDocumentListener(documentListener); |
|
|
654 |
if (this.editor != null) { |
655 |
ISelectionProvider selectionProvider = this.editor.getSelectionProvider(); |
656 |
if (selectionProvider instanceof IPostSelectionProvider) { |
657 |
((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(selectionListener); |
658 |
} |
659 |
} |
660 |
oldSelectionReceiver = this.selectionReceiver; |
661 |
this.selectionReceiver = null; |
519 |
this.editor = null; |
662 |
this.editor = null; |
520 |
} |
663 |
} |
|
|
664 |
|
665 |
if (oldSelectionReceiver != null) { |
666 |
oldSelectionReceiver.dispose(); |
667 |
} |
521 |
// clean up if necessary |
668 |
// clean up if necessary |
522 |
// TODO abstract this to work for SynchronizationStrategy |
669 |
// TODO abstract this to work for SynchronizationStrategy |
523 |
ColaSynchronizer.cleanUpFor(this); |
670 |
ColaSynchronizer.cleanUpFor(this); |
Lines 534-539
Link Here
|
534 |
} |
681 |
} |
535 |
} |
682 |
} |
536 |
|
683 |
|
|
|
684 |
void sendSelectionMsg(SelectionMessage msg) { |
685 |
if (isSharing()) { |
686 |
try { |
687 |
send(getOtherID(), msg); |
688 |
} catch (final Exception e) { |
689 |
logError(Messages.DocShare_EXCEPTION_SEND_MESSAGE, e); |
690 |
} |
691 |
} |
692 |
} |
693 |
|
537 |
void sendStopMessage() { |
694 |
void sendStopMessage() { |
538 |
sendStopMessage(getOtherID()); |
695 |
sendStopMessage(getOtherID()); |
539 |
} |
696 |
} |