Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs246
1 files changed, 246 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs
new file mode 100644
index 0000000000..ec5fd72ee1
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/AbstractUsagesExtension.cs
@@ -0,0 +1,246 @@
+//
+// AbstractUsagesExtension.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Ide.Gui.Content;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Ide.FindInFiles;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using System.Diagnostics.CodeAnalysis;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public abstract class UsageProviderEditorExtension : TextEditorExtension
+ {
+ public abstract IEnumerable<Usage> Usages {
+ get;
+ }
+
+ public event EventHandler UsagesUpdated;
+
+ protected void OnUsagesUpdated (EventArgs e)
+ {
+ var handler = UsagesUpdated;
+ if (handler != null)
+ handler (this, e);
+ }
+ }
+
+ /// <summary>
+ /// Provides a base class for implementing highlighting of usages inside the text editor.
+ /// </summary>
+ public abstract class AbstractUsagesExtension<T> : UsageProviderEditorExtension
+ {
+ [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+ protected static readonly List<MemberReference> EmptyList = new List<MemberReference> ();
+
+ CancellationTokenSource tooltipCancelSrc = new CancellationTokenSource ();
+ List<ITextSegmentMarker> markers = new List<ITextSegmentMarker> ();
+
+ public IList<ITextSegmentMarker> Markers {
+ get {
+ return markers;
+ }
+ }
+
+ uint popupTimer;
+
+ protected override void Initialize ()
+ {
+ Editor.CaretPositionChanged += HandleTextEditorDataCaretPositionChanged;
+ Editor.TextChanged += HandleTextEditorDataDocumentTextReplaced;
+ Editor.SelectionChanged += HandleTextEditorDataSelectionChanged;
+ }
+
+ void HandleTextEditorDataSelectionChanged (object sender, EventArgs e)
+ {
+ if (Editor.IsSomethingSelected)
+ RemoveMarkers ();
+ }
+
+ void HandleTextEditorDataDocumentTextReplaced (object sender, TextChangeEventArgs e)
+ {
+ RemoveMarkers ();
+ }
+
+ public override void Dispose ()
+ {
+ CancelTooltip ();
+
+ Editor.SelectionChanged -= HandleTextEditorDataSelectionChanged;
+ Editor.CaretPositionChanged -= HandleTextEditorDataCaretPositionChanged;
+ Editor.TextChanged -= HandleTextEditorDataDocumentTextReplaced;
+ base.Dispose ();
+ RemoveTimer ();
+ }
+
+ public bool IsTimerOnQueue {
+ get {
+ return popupTimer != 0;
+ }
+ }
+
+ public void ForceUpdate ()
+ {
+ RemoveTimer ();
+ DelayedTooltipShow ();
+ }
+
+ /// <summary>
+ /// Tries to resolve inside the current location inside tho document.
+ /// </summary>
+ /// <returns><c>true</c>, if resolve was successful, <c>false</c> otherwise.</returns>
+ /// <param name="token">A cancellation token to cancel the operation.</param>
+ protected abstract Task<T> ResolveAsync (CancellationToken token);
+
+
+ /// <summary>
+ /// Gets all references from a given resolve result. Note that this method is called on a background thread.
+ /// </summary>
+ /// <returns>The references.</returns>
+ /// <param name="resolveResult">The resolve result given in 'TryResolve'.</param>
+ /// <param name="token">A cancellation token to cancel the operation.</param>
+ protected abstract IEnumerable<MemberReference> GetReferences (T resolveResult, CancellationToken token);
+
+ async void DelayedTooltipShow ()
+ {
+ try {
+ CancelTooltip ();
+
+ var token = tooltipCancelSrc.Token;
+
+ T result = await ResolveAsync (token);
+ if (token.IsCancellationRequested) {
+ ClearQuickTasks ();
+ return;
+ }
+
+ Task.Run (delegate {
+ var list = GetReferences (result, token).ToList ();
+ if (!token.IsCancellationRequested) {
+ Gtk.Application.Invoke (delegate {
+ if (!token.IsCancellationRequested)
+ ShowReferences (list);
+ });
+ }
+ });
+
+ } catch (Exception e) {
+ LoggingService.LogError ("Unhandled Exception in HighlightingUsagesExtension", e);
+ } finally {
+ popupTimer = 0;
+ }
+ }
+
+ void RemoveTimer ()
+ {
+ if (popupTimer != 0) {
+ GLib.Source.Remove (popupTimer);
+ popupTimer = 0;
+ }
+ }
+
+ void HandleTextEditorDataCaretPositionChanged (object sender, EventArgs e)
+ {
+ if (!DefaultSourceEditorOptions.Instance.EnableHighlightUsages)
+ return;
+ if (!Editor.IsSomethingSelected && markers.Any (m => m.Contains (Editor.CaretOffset)))
+ return;
+ RemoveMarkers ();
+ RemoveTimer ();
+ if (!Editor.IsSomethingSelected)
+ popupTimer = GLib.Timeout.Add (1000, () => { DelayedTooltipShow (); return false; } );
+ }
+
+ void ClearQuickTasks ()
+ {
+ //UsagesSegments.Clear ();
+ if (usages.Count > 0) {
+ usages.Clear ();
+ OnUsagesUpdated (EventArgs.Empty);
+ }
+ }
+
+ void CancelTooltip ()
+ {
+ tooltipCancelSrc.Cancel ();
+ tooltipCancelSrc = new CancellationTokenSource ();
+ }
+
+ void RemoveMarkers ()
+ {
+ if (markers.Count == 0)
+ return;
+ // TextEditorData.Parent.TextViewMargin.AlphaBlendSearchResults = false;
+ foreach (var marker in markers) {
+ Editor.RemoveMarker (marker);
+ }
+ markers.Clear ();
+ }
+
+ void ShowReferences (IEnumerable<MemberReference> references)
+ {
+ RemoveMarkers ();
+ var lineNumbers = new HashSet<int> ();
+ usages.Clear ();
+ var editor = Editor;
+ if (editor != null /*&& editor.TextViewMargin != null*/) {
+ if (references != null) {
+ foreach (var r in references) {
+ if (r == null)
+ continue;
+ var start = r.Offset;
+ var end = r.Offset + r.Length;
+ if (end > editor.Length)
+ continue;
+ var usage = new Usage (TextSegment.FromBounds (start, end), r.ReferenceUsageType);
+ usages.Add (usage);
+ var marker = TextMarkerFactory.CreateUsageMarker (editor, usage);
+ markers.Add (marker);
+ lineNumbers.Add (editor.OffsetToLineNumber (start));
+ editor.AddMarker (marker);
+ }
+ }
+ }
+ OnUsagesUpdated (EventArgs.Empty);
+ }
+
+ #region IUsageProvider implementation
+
+ readonly List<Usage> usages = new List<Usage> ();
+ public override IEnumerable<Usage> Usages {
+ get {
+ return usages;
+ }
+ }
+ #endregion
+ }
+}
+