Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit e0c2177

Browse files
authored
Merge pull request #8461 from mono/jstedfast-mac-objectvaluetreeview
[Debugger] Cocoa port of ObjectValueTreeView
2 parents 62e5edc + 4a7d4f0 commit e0c2177

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+4274
-338
lines changed

main/src/addins/MonoDevelop.Debugger/Gui/MonoDevelop.Debugger.ExpressionEvaluatorDialog.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ protected virtual void Build ()
7272
this.valueTree.AllowPinning = false;
7373
this.valueTree.RootPinAlwaysVisible = false;
7474
this.valueTree.AllowExpanding = false;
75-
this.valueTree.PinnedWatchLine = 0;
7675
this.valueTree.CompactView = false;
7776
this.GtkScrolledWindow.Add (this.valueTree);
7877
this.vbox2.Add (this.GtkScrolledWindow);

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.PreviewVisualizers/PreviewWindowManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,16 @@ public static void Show (ObjectValue val, Control widget, Gdk.Rectangle previewB
4747
wnd = new PreviewVisualizerWindow (val, widget);
4848
IdeApp.CommandService.RegisterTopWindow (wnd);
4949
wnd.ShowPopup (widget, previewButtonArea, PopupPosition.Left);
50+
wnd.FocusOutEvent += HandleFocusOutEvent;
5051
wnd.Destroyed += HandleDestroyed;
5152
OnWindowShown (EventArgs.Empty);
5253
}
5354

55+
private static void HandleFocusOutEvent (object o, Gtk.FocusOutEventArgs args)
56+
{
57+
DestroyWindow ();
58+
}
59+
5460
static void HandleDestroyed (object sender, EventArgs e)
5561
{
5662
wnd = null;
@@ -85,6 +91,8 @@ static void HandleKeyPressed (object sender, KeyPressArgs e)
8591
public static void DestroyWindow ()
8692
{
8793
if (wnd != null) {
94+
wnd.FocusOutEvent -= HandleFocusOutEvent;
95+
wnd.Destroyed -= HandleDestroyed;
8896
wnd.Destroy ();
8997
wnd = null;
9098
}

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<Compile Include="TextFile.cs" />
2424
<Compile Include="VsCodeStackFrameTests.cs" />
2525
<Compile Include="BreakpointsAndSteppingTests.cs" />
26+
<Compile Include="ObjectValueTreeViewControllerTests.cs" />
2627
</ItemGroup>
2728
<ItemGroup>
2829
<ProjectReference Include="..\MonoDevelop.Debugger.csproj">
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
//
2+
// ObjectValueTreeViewControllerTests.cs
3+
//
4+
// Author:
5+
// Jeffrey Stedfast <[email protected]>
6+
//
7+
// Copyright (c) 2019 Microsoft Corp.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
using System;
28+
using System.Threading;
29+
using System.Threading.Tasks;
30+
using System.Collections.Generic;
31+
32+
using NUnit.Framework;
33+
34+
using Mono.Debugging.Client;
35+
36+
namespace MonoDevelop.Debugger.Tests
37+
{
38+
class DummyDebuggerService : IDebuggerService
39+
{
40+
public bool IsConnected => true;
41+
42+
public bool IsPaused => true;
43+
44+
public bool HasInlineVisualizer (ObjectValueNode node)
45+
{
46+
return false;
47+
}
48+
49+
public bool HasValueVisualizers (ObjectValueNode node)
50+
{
51+
return false;
52+
}
53+
54+
public void NotifyVariableChanged ()
55+
{
56+
}
57+
58+
public bool ShowValueVisualizer (ObjectValueNode node)
59+
{
60+
return false;
61+
}
62+
}
63+
64+
class DummyStackFrame : IStackFrame
65+
{
66+
public EvaluationOptions CloneSessionEvaluationOpions ()
67+
{
68+
return new EvaluationOptions ();
69+
}
70+
71+
public ObjectValueNode EvaluateExpression (string expression)
72+
{
73+
return new FakeObjectValueNode (expression);
74+
}
75+
76+
public ObjectValueNode [] EvaluateExpressions (IList<string> expressions)
77+
{
78+
var values = new ObjectValueNode [expressions.Count];
79+
80+
for (int i = 0; i < expressions.Count; i++)
81+
values [i] = new FakeObjectValueNode (expressions [i]);
82+
83+
return values;
84+
}
85+
}
86+
87+
class DummyObjectValueTreeViewController : ObjectValueTreeViewController
88+
{
89+
protected override IDebuggerService OnGetDebuggerService ()
90+
{
91+
return new DummyDebuggerService ();
92+
}
93+
94+
public void SetViewControl (IObjectValueTreeView control)
95+
{
96+
ConfigureView (control);
97+
}
98+
}
99+
100+
class ObjectValueNodeReplacedEventArgs : EventArgs
101+
{
102+
public ObjectValueNodeReplacedEventArgs (ObjectValueNode node, ObjectValueNode[] replacementNodes)
103+
{
104+
Node = node;
105+
ReplacementNodes = replacementNodes;
106+
}
107+
108+
public ObjectValueNode Node {
109+
get; private set;
110+
}
111+
112+
public ObjectValueNode[] ReplacementNodes {
113+
get; private set;
114+
}
115+
}
116+
117+
class DummyObjectValueTreeView : IObjectValueTreeView
118+
{
119+
public bool AllowEditing { get; set; }
120+
public bool AllowExpanding { get; set; }
121+
public PinnedWatch PinnedWatch { get; set; }
122+
123+
public int PinnedWatchOffset { get; set; }
124+
125+
public event EventHandler<ObjectValueNodeEventArgs> NodeExpand;
126+
127+
public object EmitNodeExpand (ObjectValueNode node)
128+
{
129+
var args = new ObjectValueNodeEventArgs (node);
130+
NodeExpand (this, args);
131+
return args.Response;
132+
}
133+
134+
public event EventHandler<ObjectValueNodeEventArgs> NodeCollapse;
135+
136+
public object EmitNodeCollapse (ObjectValueNode node)
137+
{
138+
var args = new ObjectValueNodeEventArgs (node);
139+
NodeCollapse (this, args);
140+
return args.Response;
141+
}
142+
143+
public event EventHandler<ObjectValueNodeEventArgs> NodeLoadMoreChildren;
144+
145+
public object EmitNodeLoadMoreChildren (ObjectValueNode node)
146+
{
147+
var args = new ObjectValueNodeEventArgs (node);
148+
NodeLoadMoreChildren (this, args);
149+
return args.Response;
150+
}
151+
152+
public event EventHandler<ObjectValueNodeEventArgs> NodeRefresh;
153+
154+
public object EmitNodeRefresh (ObjectValueNode node)
155+
{
156+
var args = new ObjectValueNodeEventArgs (node);
157+
NodeRefresh (this, args);
158+
return args.Response;
159+
}
160+
161+
public event EventHandler<ObjectValueNodeEventArgs> NodeGetCanEdit;
162+
163+
public object EmitNodeGetCanEdit (ObjectValueNode node)
164+
{
165+
var args = new ObjectValueNodeEventArgs (node);
166+
NodeGetCanEdit (this, args);
167+
return args.Response;
168+
}
169+
170+
public event EventHandler<ObjectValueEditEventArgs> NodeEditValue;
171+
172+
public object EmitNodeEditValue (ObjectValueNode node, string newValue)
173+
{
174+
var args = new ObjectValueEditEventArgs (node, newValue);
175+
NodeEditValue (this, args);
176+
return args.Response;
177+
}
178+
179+
public event EventHandler<ObjectValueNodeEventArgs> NodeRemoved;
180+
181+
public object EmitNodeRemoved (ObjectValueNode node)
182+
{
183+
var args = new ObjectValueNodeEventArgs (node);
184+
NodeRemoved (this, args);
185+
return args.Response;
186+
}
187+
188+
public event EventHandler<ObjectValueNodeEventArgs> NodePinned;
189+
190+
public object EmitNodePinned (ObjectValueNode node)
191+
{
192+
var args = new ObjectValueNodeEventArgs (node);
193+
NodePinned (this, args);
194+
return args.Response;
195+
}
196+
197+
public event EventHandler<EventArgs> NodeUnpinned;
198+
199+
public object EmitNodeUnpinned (ObjectValueNode node)
200+
{
201+
var args = new ObjectValueNodeEventArgs (node);
202+
NodeUnpinned (this, args);
203+
return args.Response;
204+
}
205+
206+
public event EventHandler<ObjectValueNodeEventArgs> NodeShowVisualiser;
207+
208+
public object EmitNodeShowVisualizer (ObjectValueNode node)
209+
{
210+
var args = new ObjectValueNodeEventArgs (node);
211+
NodeShowVisualiser (this, args);
212+
return args.Response;
213+
}
214+
215+
public event EventHandler<ObjectValueExpressionEventArgs> ExpressionAdded;
216+
217+
public object EmitExpressionAdded (ObjectValueNode node, string expression)
218+
{
219+
var args = new ObjectValueExpressionEventArgs (node, expression);
220+
ExpressionAdded (this, args);
221+
return args.Response;
222+
}
223+
224+
public event EventHandler<ObjectValueExpressionEventArgs> ExpressionEdited;
225+
226+
public object EmitExpressionEdited (ObjectValueNode node, string expression)
227+
{
228+
var args = new ObjectValueExpressionEventArgs (node, expression);
229+
ExpressionEdited (this, args);
230+
return args.Response;
231+
}
232+
233+
public event EventHandler StartEditing;
234+
public event EventHandler EndEditing;
235+
236+
public event EventHandler<ObjectValueNodeEventArgs> ViewAppendedNode;
237+
238+
public void Appended (ObjectValueNode node)
239+
{
240+
ViewAppendedNode.Invoke (this, new ObjectValueNodeEventArgs (node));
241+
}
242+
243+
public void Appended (IList<ObjectValueNode> nodes)
244+
{
245+
foreach (var node in nodes)
246+
ViewAppendedNode?.Invoke (this, new ObjectValueNodeEventArgs (node));
247+
}
248+
249+
public event EventHandler ViewCleared;
250+
251+
public void Cleared ()
252+
{
253+
ViewCleared?.Invoke (this, EventArgs.Empty);
254+
}
255+
256+
public event EventHandler<ObjectValueNodeReplacedEventArgs> ViewReplacedNode;
257+
258+
public void LoadEvaluatedNode (ObjectValueNode node, ObjectValueNode[] replacementNodes)
259+
{
260+
ViewReplacedNode?.Invoke (this, new ObjectValueNodeReplacedEventArgs (node, replacementNodes));
261+
}
262+
263+
public event EventHandler<ObjectValueNodeEventArgs> ViewLoadedChildren;
264+
265+
public void LoadNodeChildren (ObjectValueNode node, int startIndex, int count)
266+
{
267+
ViewLoadedChildren?.Invoke (this, new ObjectValueNodeEventArgs (node));
268+
}
269+
270+
public event EventHandler<ObjectValueNodeEventArgs> ViewExpandedNode;
271+
272+
public void OnNodeExpanded (ObjectValueNode node)
273+
{
274+
ViewExpandedNode?.Invoke (this, new ObjectValueNodeEventArgs (node));
275+
}
276+
}
277+
278+
[TestFixture]
279+
public class ObjectValueTreeViewControllerTests
280+
{
281+
[Test]
282+
public async Task TestBasicFunctionalityAsync ()
283+
{
284+
var controller = new DummyObjectValueTreeViewController ();
285+
var view = new DummyObjectValueTreeView ();
286+
ObjectValueNode[] replacements = null;
287+
int appended = 0;
288+
int replaced = 0;
289+
int expanded = 0;
290+
int cleared = 0;
291+
int loaded = 0;
292+
293+
view.ViewAppendedNode += (o, e) => {
294+
appended++;
295+
};
296+
297+
view.ViewReplacedNode += (o, e) => {
298+
replaced++;
299+
replacements = e.ReplacementNodes;
300+
};
301+
302+
view.ViewLoadedChildren += (o, e) => {
303+
loaded++;
304+
};
305+
306+
view.ViewExpandedNode += (o, e) => {
307+
expanded++;
308+
};
309+
310+
view.ViewCleared += (o, e) => {
311+
cleared++;
312+
};
313+
314+
controller.SetViewControl (view);
315+
controller.Frame = new DummyStackFrame ();
316+
317+
var xx = new List<ObjectValueNode> ();
318+
319+
xx.Add (new FakeObjectValueNode ("f1"));
320+
xx.Add (new FakeIsImplicitNotSupportedObjectValueNode ());
321+
322+
xx.Add (new FakeEvaluatingGroupObjectValueNode (1));
323+
xx.Add (new FakeEvaluatingGroupObjectValueNode (0));
324+
xx.Add (new FakeEvaluatingGroupObjectValueNode (5));
325+
326+
xx.Add (new FakeEvaluatingObjectValueNode ());
327+
xx.Add (new FakeEnumerableObjectValueNode (10));
328+
xx.Add (new FakeEnumerableObjectValueNode (20));
329+
xx.Add (new FakeEnumerableObjectValueNode (23));
330+
331+
controller.AddValues (xx);
332+
333+
Assert.AreEqual (xx.Count, appended, "Number of appended object value nodes do not match.");
334+
335+
// the fake evaluating nodes are using a 5000 timer, so 5100 should be enough...
336+
await Task.Delay (5100);
337+
338+
Assert.AreEqual (4, replaced, "Number of replaced nodes does not match.");
339+
340+
// expand the "f1" node
341+
view.EmitNodeExpand (xx[0]);
342+
343+
// expanding a fake node uses a 1000 timer, so 1100 should be enough
344+
await Task.Delay (1100);
345+
346+
Assert.AreEqual (1, expanded, "Expected the f1 node to be expanded.");
347+
348+
controller.ClearAll ();
349+
350+
Assert.AreEqual (1, cleared, "Expected ClearAll to clear the values.");
351+
}
352+
}
353+
}

0 commit comments

Comments
 (0)