Browse Source

Add tooltips controls

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
9f1028cbf3
  1. 109
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 54
      Debugger/ILSpy.Debugger/AvalonEdit/TextEditorWeakEventManager.cs
  3. 4
      Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj
  4. 121
      Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
  5. 24
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  6. 71
      Debugger/ILSpy.Debugger/ToolTips/Models/ToolTipRequestEventArgs.cs
  7. 197
      Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs
  8. 6
      ILSpy/TextView/DecompilerTextView.cs

109
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -28,6 +28,7 @@ using ICSharpCode.AvalonEdit.Utils; @@ -28,6 +28,7 @@ using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler.Disassembler;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Services;
using ILSpy.Debugger.ToolTips;
using Mono.Cecil;
namespace ILSpy.Debugger.AvalonEdit
@ -87,45 +88,10 @@ namespace ILSpy.Debugger.AvalonEdit @@ -87,45 +88,10 @@ namespace ILSpy.Debugger.AvalonEdit
BookmarkBase bm;
if (bookmarkDict.TryGetValue(lineNumber, out bm)) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(line.VisualTop - textView.VerticalOffset, pixelSize.Height), 16, 16);
if (dragDropBookmark == bm && dragStarted)
drawingContext.PushOpacity(0.5);
drawingContext.DrawImage(bm.Image, rect);
if (dragDropBookmark == bm && dragStarted)
drawingContext.Pop();
drawingContext.DrawImage(bm.Image, rect);
}
}
if (dragDropBookmark != null && dragStarted) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(dragDropCurrentPoint - 8, pixelSize.Height), 16, 16);
drawingContext.DrawImage(dragDropBookmark.Image, rect);
}
}
}
IBookmark dragDropBookmark; // bookmark being dragged (!=null if drag'n'drop is active)
double dragDropStartPoint;
double dragDropCurrentPoint;
bool dragStarted; // whether drag'n'drop operation has started (mouse was moved minimum distance)
protected override void OnMouseDown(MouseButtonEventArgs e)
{
CancelDragDrop();
base.OnMouseDown(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && line > 0) {
IBookmark bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseDown(e);
if (!e.Handled) {
if (e.ChangedButton == MouseButton.Left && bm.CanDragDrop && CaptureMouse()) {
StartDragDrop(bm, e);
e.Handled = true;
}
}
}
}
}
// don't allow selecting text through the IconBarMargin
if (e.ChangedButton == MouseButton.Left)
e.Handled = true;
}
BookmarkBase GetBookmarkFromLine(int line)
@ -142,46 +108,6 @@ namespace ILSpy.Debugger.AvalonEdit @@ -142,46 +108,6 @@ namespace ILSpy.Debugger.AvalonEdit
return result;
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
CancelDragDrop();
base.OnLostMouseCapture(e);
}
void StartDragDrop(IBookmark bm, MouseEventArgs e)
{
dragDropBookmark = bm;
dragDropStartPoint = dragDropCurrentPoint = e.GetPosition(this).Y;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown += TextArea_PreviewKeyDown;
}
}
void CancelDragDrop()
{
if (dragDropBookmark != null) {
dragDropBookmark = null;
dragStarted = false;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown -= TextArea_PreviewKeyDown;
}
ReleaseMouseCapture();
InvalidateVisual();
}
}
void TextArea_PreviewKeyDown(object sender, KeyEventArgs e)
{
// any key press cancels drag'n'drop
CancelDragDrop();
if (e.Key == Key.Escape)
e.Handled = true;
}
int GetLineFromMousePosition(MouseEventArgs e)
{
TextView textView = this.TextView;
@ -193,44 +119,25 @@ namespace ILSpy.Debugger.AvalonEdit @@ -193,44 +119,25 @@ namespace ILSpy.Debugger.AvalonEdit
return vl.FirstDocumentLine.LineNumber;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (dragDropBookmark != null) {
dragDropCurrentPoint = e.GetPosition(this).Y;
if (Math.Abs(dragDropCurrentPoint - dragDropStartPoint) > SystemParameters.MinimumVerticalDragDistance)
dragStarted = true;
InvalidateVisual();
}
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && dragDropBookmark != null) {
if (dragStarted) {
if (line != 0)
dragDropBookmark.Drop(line);
e.Handled = true;
}
CancelDragDrop();
}
if (!e.Handled && line != 0) {
IBookmark bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseUp(e);
if (IconBarMargin.CurrentType != null) {
DebuggerService.ToggleBreakpointAt(IconBarMargin.CurrentType.FullName, line);
if (CurrentType != null) {
DebuggerService.ToggleBreakpointAt(CurrentType.FullName, line);
}
InvalidateVisual();
if (e.Handled)
return;
}
if (e.ChangedButton == MouseButton.Left && TextView != null) {
if (IconBarMargin.CurrentType != null) {
if (e.ChangedButton == MouseButton.Left) {
if (CurrentType != null) {
// no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt(IconBarMargin.CurrentType.FullName, line);
DebuggerService.ToggleBreakpointAt(CurrentType.FullName, line);
}
}
InvalidateVisual();

54
Debugger/ILSpy.Debugger/AvalonEdit/TextEditorWeakEventManager.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// 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 System.Windows;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Utils;
namespace ILSpy.Debugger.AvalonEdit
{
public static class TextEditorWeakEventManager
{
public sealed class MouseHover : WeakEventManagerBase<MouseHover, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHover -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHover += DeliverEvent;
}
}
public sealed class MouseHoverStopped : WeakEventManagerBase<MouseHoverStopped, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHoverStopped -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHoverStopped += DeliverEvent;
}
}
}
}

4
Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj

@ -52,6 +52,7 @@ @@ -52,6 +52,7 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="AvalonEdit\TextEditorWeakEventManager.cs" />
<Compile Include="AvalonEdit\Editor\AvalonEditTextSourceAdapter.cs" />
<Compile Include="AvalonEdit\Editor\IDocument.cs" />
<Compile Include="AvalonEdit\Editor\IDocumentLine.cs" />
@ -97,6 +98,8 @@ @@ -97,6 +98,8 @@
<DependentUpon>DebuggerTooltipControl.xaml</DependentUpon>
</Compile>
<Compile Include="ToolTips\LazyItemsControl.cs" />
<Compile Include="ToolTips\Models\ToolTipRequestEventArgs.cs" />
<Compile Include="ToolTips\TextEditorListener.cs" />
<Compile Include="ToolTips\VirtualizingIEnumerable.cs" />
<Compile Include="UI\AttachToProcessWindow.xaml.cs">
<DependentUpon>AttachToProcessWindow.xaml</DependentUpon>
@ -106,6 +109,7 @@ @@ -106,6 +109,7 @@
<ItemGroup>
<Folder Include="Models\TreeModel" />
<Folder Include="ToolTips" />
<Folder Include="ToolTips\Models" />
</ItemGroup>
<ItemGroup>
<Page Include="ToolTips\DebuggerTooltipControl.xaml" />

121
Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs

@ -3,10 +3,15 @@ @@ -3,10 +3,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.ToolTips;
namespace ILSpy.Debugger.Services
{
@ -194,52 +199,72 @@ namespace ILSpy.Debugger.Services @@ -194,52 +199,72 @@ namespace ILSpy.Debugger.Services
/// showing its current value (when in debugging mode) can be returned
/// through the ToolTipRequestEventArgs.SetTooltip() method.
/// </summary>
// internal static void HandleToolTipRequest(ToolTipRequestEventArgs e)
// {
internal static void HandleToolTipRequest(ToolTipRequestEventArgs e)
{
if (currentDebugger == null || !currentDebugger.IsDebugging) {
e.ContentToShow = "test";
}
else {
e.ContentToShow = currentDebugger.GetTooltipControl(e.LogicalPosition, "test");
}
// FIXME
// if (!e.InDocument)
// return;
// Location logicPos = e.LogicalPosition;
// var doc = e.Editor.Document;
// IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(e.Editor.FileName);
// if (expressionFinder == null)
// return;
// var currentLine = doc.GetLine(logicPos.Y);
// if (logicPos.X > currentLine.Length)
// return;
// string textContent = doc.Text;
// ExpressionResult expressionResult = expressionFinder.FindFullExpression(textContent, doc.PositionToOffset(logicPos.Line, logicPos.Column));
// string expression = (expressionResult.Expression ?? "").Trim();
// if (expression.Length > 0) {
// // Look if it is variable
// ResolveResult result = ParserService.Resolve(expressionResult, logicPos.Y, logicPos.X, e.Editor.FileName, textContent);
// bool debuggerCanShowValue;
// string toolTipText = GetText(result, expression, out debuggerCanShowValue);
// if (Control.ModifierKeys == Keys.Control) {
// toolTipText = "expr: " + expressionResult.ToString() + "\n" + toolTipText;
// debuggerCanShowValue = false;
// }
// if (toolTipText != null) {
// if (debuggerCanShowValue && currentDebugger != null) {
// object toolTip = currentDebugger.GetTooltipControl(e.LogicalPosition, expressionResult.Expression);
// if (toolTip != null)
// e.SetToolTip(toolTip);
// else
// var logicPos = e.LogicalPosition;
// var doc = (TextDocument)e.Editor.Document;
//
// using (var sr = new StringReader(doc.Text))
// {
// var parser = new CSharpParser();
// parser.Parse(sr);
//
// IExpressionFinder expressionFinder = ParserService.GetExpressionFinder();
// if (expressionFinder == null)
// return;
// var currentLine = doc.GetLine(logicPos.Y);
// if (logicPos.X > currentLine.Length)
// return;
// string textContent = doc.Text;
// ExpressionResult expressionResult = expressionFinder.FindFullExpression(textContent, doc.GetOffset(new TextLocation(logicPos.Line, logicPos.Column)));
// string expression = (expressionResult.Expression ?? "").Trim();
// if (expression.Length > 0) {
// // Look if it is variable
// ResolveResult result = ParserService.Resolve(expressionResult, logicPos.Y, logicPos.X, e.Editor.FileName, textContent);
// bool debuggerCanShowValue;
// string toolTipText = GetText(result, expression, out debuggerCanShowValue);
// if (Control.ModifierKeys == Keys.Control) {
// toolTipText = "expr: " + expressionResult.ToString() + "\n" + toolTipText;
// debuggerCanShowValue = false;
// }
// if (toolTipText != null) {
// if (debuggerCanShowValue && currentDebugger != null) {
// object toolTip = currentDebugger.GetTooltipControl(e.LogicalPosition, expressionResult.Expression);
// if (toolTip != null)
// e.SetToolTip(toolTip);
// else
// e.SetToolTip(toolTipText);
// } else {
// e.SetToolTip(toolTipText);
// } else {
// e.SetToolTip(toolTipText);
// }
// }
// }
// } else {
// #if DEBUG
// if (Control.ModifierKeys == Keys.Control) {
// e.SetToolTip("no expr: " + expressionResult.ToString());
// else {
// #if DEBUG
// if (Control.ModifierKeys == Keys.Control) {
// e.SetToolTip("no expr: " + expressionResult.ToString());
// }
// #endif
// }
// #endif
// }
// }
//
// static string GetText(ResolveResult result, string expression, out bool debuggerCanShowValue)
// {
}
static string GetText(ResolveResult result, string expression, out bool debuggerCanShowValue)
{
debuggerCanShowValue = false;
return "FIXME";
// FIXME
// debuggerCanShowValue = false;
// if (result == null) {
// // when pressing control, show the expression even when it could not be resolved
@ -303,8 +328,8 @@ namespace ILSpy.Debugger.Services @@ -303,8 +328,8 @@ namespace ILSpy.Debugger.Services
// return null;
// }
// }
// }
//
}
// static string GetMemberText(IAmbience ambience, IEntity member, string expression, out bool debuggerCanShowValue)
// {
// bool tryDisplayValue = false;
@ -344,18 +369,4 @@ namespace ILSpy.Debugger.Services @@ -344,18 +369,4 @@ namespace ILSpy.Debugger.Services
// }
#endregion
}
/// <summary>
/// Provides the default debugger tooltips on the text area.
/// </summary>
/// <remarks>
/// This class must be public because it is accessed via the AddInTree.
/// </remarks>
// public class DebuggerTextAreaToolTipProvider : ITextAreaToolTipProvider
// {
// public void HandleToolTipRequest(ToolTipRequestEventArgs e)
// {
// DebuggerService.HandleToolTipRequest(e);
// }
// }
}

24
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -16,6 +16,7 @@ using ICSharpCode.NRefactory.Visitors; @@ -16,6 +16,7 @@ using ICSharpCode.NRefactory.Visitors;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Models.TreeModel;
using ILSpy.Debugger.Services.Debugger;
using ILSpy.Debugger.Tooltips;
using CorDbg = Debugger;
using Process = Debugger.Process;
@ -384,17 +385,18 @@ namespace ILSpy.Debugger.Services @@ -384,17 +385,18 @@ namespace ILSpy.Debugger.Services
/// </summary>
public object GetTooltipControl(AstLocation logicalPosition, string variableName)
{
try {
var tooltipExpression = GetExpression(variableName);
string imageName;
var image = ExpressionNode.GetImageForLocalVariable(out imageName);
ExpressionNode expressionNode = new ExpressionNode(image, variableName, tooltipExpression);
expressionNode.ImageName = imageName;
return null;
// return new DebuggerTooltipControl(logicalPosition, expressionNode);
} catch (GetValueException) {
return null;
}
return new DebuggerTooltipControl(logicalPosition, new ExpressionNode(ImageService.Breakpoint, variableName, null));
//FIXME
// try {
// var tooltipExpression = GetExpression(variableName);
// string imageName;
// var image = ExpressionNode.GetImageForLocalVariable(out imageName);
// ExpressionNode expressionNode = new ExpressionNode(image, variableName, tooltipExpression);
// expressionNode.ImageName = imageName;
// return new DebuggerTooltipControl(logicalPosition, expressionNode);
// } catch (GetValueException) {
// return null;
// }
}
public ITreeNode GetNode(string variable, string currentImageName = null)

71
Debugger/ILSpy.Debugger/ToolTips/Models/ToolTipRequestEventArgs.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// 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 ICSharpCode.AvalonEdit;
using ICSharpCode.NRefactory.CSharp;
namespace ILSpy.Debugger.ToolTips
{
public class ToolTipRequestEventArgs : EventArgs
{
/// <summary>
/// Gets whether the tool tip request was handled.
/// </summary>
public bool Handled { get; set; }
/// <summary>
/// Gets the editor causing the request.
/// </summary>
public TextEditor Editor { get; private set; }
/// <summary>
/// Gets whether the mouse was inside the document bounds.
/// </summary>
public bool InDocument { get; set; }
/// <summary>
/// The mouse position, in document coordinates.
/// </summary>
public AstLocation LogicalPosition { get; set; }
/// <summary>
/// Gets/Sets the content to show as a tooltip.
/// </summary>
public object ContentToShow { get; set; }
/// <summary>
/// Sets the tooltip to be shown.
/// </summary>
public void SetToolTip(object content)
{
if (content == null)
throw new ArgumentNullException("content");
this.Handled = true;
this.ContentToShow = content;
}
public ToolTipRequestEventArgs(TextEditor editor)
{
if (editor == null)
throw new ArgumentNullException("editor");
this.Editor = editor;
this.InDocument = true;
}
}
}

197
Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs

@ -0,0 +1,197 @@ @@ -0,0 +1,197 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// 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 System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Services;
namespace ILSpy.Debugger.ToolTips
{
/// <summary>
/// Description of TextEditorListener.
/// </summary>
public class TextEditorListener : IWeakEventListener
{
private static readonly TextEditorListener instance;
static TextEditorListener()
{
instance = new TextEditorListener();
}
private TextEditorListener() { }
Popup popup;
ToolTip toolTip;
TextEditor editor;
public static TextEditorListener Instance {
get { return instance; }
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager.MouseHover)) {
editor = (TextEditor)sender;
OnMouseHover((MouseEventArgs)e);
}
if (managerType == typeof(ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager.MouseHoverStopped)) {
OnMouseHoverStopped((MouseEventArgs)e);
}
return true;
}
void OnMouseHoverStopped(MouseEventArgs e)
{
if (popup != null)
popup.IsOpen = false;
if (toolTip != null)
toolTip.IsOpen = false;
}
void OnMouseHover(MouseEventArgs e)
{
ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor);
var pos = editor.GetPositionFromPoint(e.GetPosition(editor));
args.InDocument = pos.HasValue;
if (pos.HasValue) {
args.LogicalPosition = new AstLocation(pos.Value.Column, pos.Value.Line);
}
DebuggerService.HandleToolTipRequest(args);
if (args.ContentToShow != null) {
var contentToShowITooltip = args.ContentToShow as ITooltip;
if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) {
if (!(args.ContentToShow is UIElement)) {
throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
}
if (popup == null) {
popup = CreatePopup();
}
if (TryCloseExistingPopup(false)) {
// when popup content decides to close, close the popup
contentToShowITooltip.Closed += delegate { popup.IsOpen = false; };
popup.Child = (UIElement)args.ContentToShow;
//ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged
SetPopupPosition(popup, e);
popup.IsOpen = true;
}
e.Handled = true;
} else {
if (toolTip == null) {
toolTip = new ToolTip();
toolTip.Closed += delegate { toolTip = null; };
}
toolTip.PlacementTarget = editor; // required for property inheritance
if(args.ContentToShow is string) {
toolTip.Content = new TextBlock
{
Text = args.ContentToShow as string,
TextWrapping = TextWrapping.Wrap
};
}
else
toolTip.Content = args.ContentToShow;
toolTip.IsOpen = true;
e.Handled = true;
}
} else {
// close popup if mouse hovered over empty area
if (popup != null) {
e.Handled = true;
}
TryCloseExistingPopup(false);
}
}
bool TryCloseExistingPopup(bool mouseClick)
{
bool canClose = true;
if (popup != null) {
var popupContentITooltip = popup.Child as ITooltip;
if (popupContentITooltip != null) {
canClose = popupContentITooltip.Close(mouseClick);
}
if (canClose) {
popup.IsOpen = false;
}
}
return canClose;
}
void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs)
{
var popupPosition = GetPopupPosition(mouseArgs);
popup.HorizontalOffset = popupPosition.X;
popup.VerticalOffset = popupPosition.Y;
}
/// <summary> Returns Popup position based on mouse position, in device independent units </summary>
Point GetPopupPosition(MouseEventArgs mouseArgs)
{
Point mousePos = mouseArgs.GetPosition(editor);
Point positionInPixels;
// align Popup with line bottom
TextViewPosition? logicalPos = editor.GetPositionFromPoint(mousePos);
if (logicalPos.HasValue) {
var textView = editor.TextArea.TextView;
positionInPixels =
textView.PointToScreen(
textView.GetVisualPosition(logicalPos.Value, VisualYPosition.LineBottom) - textView.ScrollOffset);
positionInPixels.X -= 4;
} else {
positionInPixels = editor.PointToScreen(mousePos + new Vector(-4, 6));
}
// use device independent units, because Popup Left/Top are in independent units
return positionInPixels.TransformFromDevice(editor);
}
Popup CreatePopup()
{
popup = new Popup();
popup.Closed += delegate { popup = null; };
popup.AllowsTransparency = true;
popup.PlacementTarget = editor; // required for property inheritance
popup.Placement = PlacementMode.Absolute;
popup.StaysOpen = true;
return popup;
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
return ReceiveWeakEvent(managerType, sender, e);
}
}
}

6
ILSpy/TextView/DecompilerTextView.cs

@ -29,6 +29,7 @@ using System.Windows.Media.Animation; @@ -29,6 +29,7 @@ using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Xml;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
@ -36,6 +37,7 @@ using ICSharpCode.Decompiler; @@ -36,6 +37,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.TreeNodes;
using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.ToolTips;
using Microsoft.Win32;
using Mono.Cecil;
@ -80,6 +82,10 @@ namespace ICSharpCode.ILSpy.TextView @@ -80,6 +82,10 @@ namespace ICSharpCode.ILSpy.TextView
// add margin
iconMargin = new IconBarMargin();
textEditor.TextArea.LeftMargins.Add(iconMargin);
// wire the mouse events
TextEditorWeakEventManager.MouseHover.AddListener(textEditor, TextEditorListener.Instance);
TextEditorWeakEventManager.MouseHoverStopped.AddListener(textEditor, TextEditorListener.Instance);
textEditor.TextArea.TextView.VisualLinesChanged += (s, e) => iconMargin.InvalidateVisual();
BookmarkManager.Added += BookmarkManager_Added;
BookmarkManager.Removed += (s, e) => iconMargin.InvalidateVisual();

Loading…
Cancel
Save