View | Details | Raw Unified | Return to bug 237923 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/ecf/internal/provisional/docshare/DocShare.java (-2 / +159 lines)
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
	}
(-)plugin.xml (+48 lines)
Lines 29-33 Link Here
29
      </menuContribution>
29
      </menuContribution>
30
   </extension>
30
   </extension>
31
31
32
   <extension
33
         point="org.eclipse.ui.editors.annotationTypes">
34
      <type
35
            name="org.eclipse.ecf.docshare.annotations.RemoteSelection">
36
      </type>
37
      <type
38
            name="org.eclipse.ecf.docshare.annotations.RemoteCursor"
39
            super="org.eclipse.ecf.docshare.annotations.RemoteSelection">
40
      </type>
41
   </extension>
42
   <extension
43
         point="org.eclipse.ui.editors.markerAnnotationSpecification">
44
      <specification
45
            annotationType="org.eclipse.ecf.docshare.annotations.RemoteSelection"
46
            colorPreferenceKey="remoteSelectionColor"
47
            colorPreferenceValue="231,223,143"
48
            contributesToHeader="false"
49
            highlightPreferenceKey="remoteSelectionHighlighting"
50
            highlightPreferenceValue="true"
51
            includeOnPreferencePage="true"
52
            label="Remote Selection"
53
            overviewRulerPreferenceKey="remoteSelectionIndicationInOverviewRuler"
54
            overviewRulerPreferenceValue="true"
55
            presentationLayer="5"
56
            textPreferenceKey="remoteSelectionTextIndication"
57
            textPreferenceValue="false"
58
            textStylePreferenceKey="remoteSelectionTextIndicationStyle"
59
            textStylePreferenceValue="NONE">
60
      </specification>
61
      <specification
62
            annotationType="org.eclipse.ecf.docshare.annotations.RemoteCursor"
63
            colorPreferenceKey="remoteCursorColor"
64
            colorPreferenceValue="166,138,60"
65
            contributesToHeader="false"
66
            highlightPreferenceKey="remoteCursorHighlighting"
67
            highlightPreferenceValue="false"
68
            includeOnPreferencePage="true"
69
            label="Remote Cursor"
70
            overviewRulerPreferenceKey="remoteCursorIndicationInOverviewRuler"
71
            overviewRulerPreferenceValue="true"
72
            presentationLayer="5"
73
            textPreferenceKey="remoteCursorTextIndication"
74
            textPreferenceValue="true"
75
            textStylePreferenceKey="remoteCursorTextIndicationStyle"
76
            textStylePreferenceValue="IBEAM">
77
      </specification>
78
   </extension>
79
32
   
80
   
33
</plugin>
81
</plugin>

Return to bug 237923