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

Commit dddd6d4

Browse files
authored
Merge pull request #9398 from mono/exception-caught-dialog-accessibility
[Debugger] Exception caught dialog accessibility
2 parents f3f6dd3 + e1fc91d commit dddd6d4

File tree

4 files changed

+133
-69
lines changed

4 files changed

+133
-69
lines changed

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs

Lines changed: 83 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@
3030
using System.Linq;
3131
using System.Collections.Generic;
3232

33+
using Foundation;
34+
using GLib;
3335
using Gtk;
3436

3537
using Mono.Debugging.Client;
3638

3739
using MonoDevelop.Ide;
3840
using MonoDevelop.Core;
3941
using MonoDevelop.Components;
42+
using MonoDevelop.Components.AtkCocoaHelper;
4043
using MonoDevelop.Ide.TextEditing;
4144
using MonoDevelop.Ide.Editor.Extension;
4245

@@ -56,7 +59,7 @@ class ExceptionCaughtDialog : Gtk.Window
5659
VBox vboxAroundInnerExceptionMessage, rightVBox, container;
5760
Button close, helpLinkButton, innerExceptionHelpLinkButton;
5861
TreeView exceptionValueTreeView, stackTraceTreeView;
59-
Expander expanderProperties, expanderStacktrace;
62+
MacObjectValueTreeView macExceptionValueTreeView;
6063
InnerExceptionsTree innerExceptionsTreeView;
6164
ObjectValueTreeViewController controller;
6265
CheckButton onlyShowMyCodeCheckbox;
@@ -96,6 +99,8 @@ Widget CreateExceptionHeader ()
9699
icon.Yalign = 0;
97100

98101
exceptionTypeLabel = new Label { Xalign = 0.0f, Selectable = true, CanFocus = false };
102+
icon.SetCommonAccessibilityAttributes ("ExceptionCaughtDialog.WarningIcon", exceptionTypeLabel, null);
103+
99104
exceptionMessageLabel = new Label { Wrap = true, Xalign = 0.0f, Selectable = true, CanFocus = false };
100105
helpLinkButton = new Button { HasFocus = true, Xalign = 0, Relief = ReliefStyle.None, BorderWidth = 0 };
101106
helpLinkButton.Name = "exception_help_link_label";
@@ -181,12 +186,17 @@ protected override void OnSizeAllocated (Gdk.Rectangle allocation)
181186

182187
Widget CreateExceptionValueTreeView ()
183188
{
189+
Widget scrolledWidget = null;
184190
if (useNewTreeView) {
185191
controller = new ObjectValueTreeViewController ();
186192
controller.SetStackFrame (DebuggingService.CurrentFrame);
187193
controller.AllowExpanding = true;
188194

189-
exceptionValueTreeView = controller.GetGtkControl (ObjectValueTreeViewFlags.ExceptionCaughtFlags);
195+
if (Platform.IsMac) {
196+
macExceptionValueTreeView = controller.GetMacControl (ObjectValueTreeViewFlags.ObjectValuePadFlags);
197+
} else {
198+
exceptionValueTreeView = controller.GetGtkControl (ObjectValueTreeViewFlags.ExceptionCaughtFlags);
199+
}
190200
} else {
191201
var objValueTreeView = new ObjectValueTreeView ();
192202
objValueTreeView.Frame = DebuggingService.CurrentFrame;
@@ -199,77 +209,70 @@ Widget CreateExceptionValueTreeView ()
199209
exceptionValueTreeView = objValueTreeView;
200210
}
201211

202-
exceptionValueTreeView.ModifyBase (StateType.Normal, Styles.ExceptionCaughtDialog.ValueTreeBackgroundColor.ToGdkColor ());
203-
exceptionValueTreeView.ModifyBase (StateType.Active, Styles.ObjectValueTreeActiveBackgroundColor.ToGdkColor ());
204-
exceptionValueTreeView.ModifyFont (Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11"));
205-
exceptionValueTreeView.RulesHint = false;
206-
exceptionValueTreeView.CanFocus = true;
207-
exceptionValueTreeView.Show ();
212+
if (useNewTreeView && Platform.IsMac) {
213+
var scrolled = new AppKit.NSScrollView {
214+
DocumentView = macExceptionValueTreeView,
215+
AutohidesScrollers = true,
216+
HasVerticalScroller = true,
217+
HasHorizontalScroller = true,
218+
};
219+
220+
// disable implicit animations
221+
scrolled.WantsLayer = true;
222+
scrolled.Layer.Actions = new NSDictionary (
223+
"actions", NSNull.Null,
224+
"contents", NSNull.Null,
225+
"hidden", NSNull.Null,
226+
"onLayout", NSNull.Null,
227+
"onOrderIn", NSNull.Null,
228+
"onOrderOut", NSNull.Null,
229+
"position", NSNull.Null,
230+
"sublayers", NSNull.Null,
231+
"transform", NSNull.Null,
232+
"bounds", NSNull.Null);
233+
234+
var host = new GtkNSViewHost (scrolled);
235+
host.ShowAll ();
236+
scrolledWidget = host;
237+
} else {
238+
exceptionValueTreeView.ModifyBase (StateType.Normal, Styles.ExceptionCaughtDialog.ValueTreeBackgroundColor.ToGdkColor ());
239+
exceptionValueTreeView.ModifyBase (StateType.Active, Styles.ObjectValueTreeActiveBackgroundColor.ToGdkColor ());
240+
exceptionValueTreeView.ModifyFont (Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11"));
241+
exceptionValueTreeView.RulesHint = false;
242+
exceptionValueTreeView.CanFocus = true;
243+
exceptionValueTreeView.Show ();
244+
245+
var scrolled = new ScrolledWindow {
246+
CanFocus = true,
247+
HscrollbarPolicy = PolicyType.Automatic,
248+
VscrollbarPolicy = PolicyType.Automatic
249+
};
250+
251+
scrolled.ShadowType = ShadowType.None;
252+
scrolled.Add (exceptionValueTreeView);
253+
scrolled.Show ();
254+
scrolledWidget = scrolled;
255+
}
208256

209-
var scrolled = new ScrolledWindow {
210-
HeightRequest = 180,
211-
CanFocus = true,
212-
HscrollbarPolicy = PolicyType.Automatic,
213-
VscrollbarPolicy = PolicyType.Automatic
214-
};
257+
var label = new Label ();
258+
label.Markup = "<b>" + GettextCatalog.GetString ("Properties") + "</b>";
259+
label.Xalign = 0;
260+
label.Xpad = 10;
215261

216-
scrolled.ShadowType = ShadowType.None;
217-
scrolled.Add (exceptionValueTreeView);
218-
scrolled.Show ();
262+
if (exceptionValueTreeView != null) {
263+
exceptionValueTreeView.SetCommonAccessibilityAttributes ("ExceptionCaughtDialog.ExceptionValueTreeView", label, null);
264+
} else {
265+
macExceptionValueTreeView.AccessibilityTitle = new NSString (label.Text);
266+
}
219267

220268
var vbox = new VBox ();
221-
expanderProperties = WrapInExpander (GettextCatalog.GetString ("Properties"), scrolled);
222-
vbox.PackStart (new VBox (), false, false, 5);
223-
vbox.PackStart (expanderProperties, true, true, 0);
269+
vbox.PackStart (label, false, false, 12);
270+
vbox.PackStart (scrolledWidget, true, true, 0);
224271
vbox.ShowAll ();
225272

226273
return vbox;
227274
}
228275

229-
class ExpanderWithMinSize : Expander
230-
{
231-
public ExpanderWithMinSize (string label) : base (label)
232-
{
233-
}
234-
235-
protected override void OnSizeRequested (ref Requisition requisition)
236-
{
237-
base.OnSizeRequested (ref requisition);
238-
requisition.Height = 28;
239-
}
240-
}
241-
242-
Expander WrapInExpander (string title, Widget widget)
243-
{
244-
var expander = new ExpanderWithMinSize ($"<b>{GLib.Markup.EscapeText (title)}</b>");
245-
expander.Name = "exception_dialog_expander";
246-
Gtk.Rc.ParseString (@"style ""exception-dialog-expander""
247-
{
248-
GtkExpander::expander-spacing = 10
249-
}
250-
widget ""*.exception_dialog_expander"" style ""exception-dialog-expander""
251-
");
252-
expander.Child = widget;
253-
expander.Spacing = 0;
254-
expander.Show ();
255-
expander.CanFocus = true;
256-
expander.UseMarkup = true;
257-
expander.Expanded = true;
258-
expander.Activated += Expander_Activated;
259-
expander.ModifyBg (StateType.Prelight, Ide.Gui.Styles.PrimaryBackgroundColor.ToGdkColor ());
260-
return expander;
261-
}
262-
263-
void Expander_Activated (object sender, EventArgs e)
264-
{
265-
if (expanderProperties.Expanded && expanderStacktrace.Expanded)
266-
paned.PositionSet = false;
267-
else if (expanderStacktrace.Expanded)
268-
paned.Position = paned.MaxPosition;
269-
else
270-
paned.Position = paned.MinPosition;
271-
}
272-
273276
static void StackFrameLayout (CellLayout layout, CellRenderer cr, TreeModel model, TreeIter iter)
274277
{
275278
var frame = (ExceptionStackFrame)model.GetValue (iter, (int)ModelColumn.StackFrame);
@@ -304,7 +307,6 @@ Widget CreateStackTraceTreeView ()
304307
stackTraceTreeView.RowActivated += StackFrameActivated;
305308

306309
var scrolled = new ScrolledWindow {
307-
HeightRequest = 180,
308310
HscrollbarPolicy = PolicyType.Never,
309311
VscrollbarPolicy = PolicyType.Automatic
310312
};
@@ -316,10 +318,16 @@ Widget CreateStackTraceTreeView ()
316318
vbox.PackStart (scrolled, true, true, 0);
317319
vbox.Show ();
318320

321+
var label = new Label ();
322+
label.Markup = "<b>" + GettextCatalog.GetString ("Stacktrace") + "</b>";
323+
label.Xalign = 0;
324+
label.Xpad = 10;
325+
326+
stackTraceTreeView.SetCommonAccessibilityAttributes ("ExceptionCaughtDialog.StackTraceTreeView", label, null);
327+
319328
var vbox2 = new VBox ();
320-
expanderStacktrace = WrapInExpander (GettextCatalog.GetString ("Stacktrace"), vbox);
321-
vbox2.PackStart (new VBox (), false, false, 5);
322-
vbox2.PackStart (expanderStacktrace, true, true, 0);
329+
vbox2.PackStart (label, false, false, 12);
330+
vbox2.PackStart (vbox, true, true, 0);
323331
vbox2.ShowAll ();
324332
return vbox2;
325333
}
@@ -371,6 +379,7 @@ void Build ()
371379
paned.GrabAreaSize = 10;
372380
paned.Pack1 (CreateStackTraceTreeView (), true, false);
373381
paned.Pack2 (CreateExceptionValueTreeView (), true, false);
382+
paned.Position = 160;
374383
paned.Show ();
375384
var vbox = new VBox (false, 0);
376385
var whiteBackground = new EventBox ();
@@ -432,6 +441,7 @@ Widget CreateInnerExceptionMessage ()
432441
innerExceptionTypeLabel.Xalign = 0;
433442
innerExceptionTypeLabel.Selectable = true;
434443
innerExceptionTypeLabel.CanFocus = false;
444+
icon.SetCommonAccessibilityAttributes ("ExceptionCaughtDialog.InnerExceptionWarningIcon", innerExceptionTypeLabel, null);
435445
hbox.PackStart (innerExceptionTypeLabel, false, true, 4);
436446

437447
innerExceptionMessageLabel = new Label ();
@@ -515,6 +525,10 @@ Widget CreateInnerExceptionsTree ()
515525
UpdateSelectedException ((ExceptionInfo)innerExceptionsTreeView.Model.GetValue (selectedIter, 0));
516526
}
517527
};
528+
innerExceptionsTreeView.SetCommonAccessibilityAttributes (
529+
"ExceptionCaughtDialog.InnerExceptionsTreeView",
530+
GettextCatalog.GetString ("Inner Exceptions"),
531+
null);
518532
var eventBox = new EventBox ();
519533
eventBox.ModifyBg (StateType.Normal, Styles.ExceptionCaughtDialog.TreeBackgroundColor.ToGdkColor ()); // top and bottom padders
520534
var vbox = new VBox ();
@@ -717,6 +731,7 @@ protected override void OnDestroyed ()
717731

718732
class CellRendererInnerException : CellRenderer
719733
{
734+
[Property ("text")] // Enables Voice Over support.
720735
public string Text { get; set; }
721736

722737
Pango.FontDescription font = Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11");

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public MacDebuggerObjectNameView (MacObjectValueTreeView treeView) : base (treeV
9292

9393
PreviewButton = new NSButton {
9494
TranslatesAutoresizingMaskIntoConstraints = false,
95+
AccessibilityTitle = GettextCatalog.GetString ("Open Preview Visualizer"),
9596
Image = GetImage ("md-empty", Gtk.IconSize.Menu),
9697
BezelStyle = NSBezelStyle.Inline,
9798
Bordered = false
@@ -264,6 +265,9 @@ protected override void UpdateContents ()
264265
TextField.Editable = editable;
265266
UpdateFont (TextField);
266267
TextField.SizeToFit ();
268+
ImageView.AccessibilityTitle = ObjectValueTreeViewController.GetAccessibilityTitleForIcon (
269+
Node.Flags,
270+
GettextCatalog.GetString ("Object Name"));
267271

268272
var value = editable && string.IsNullOrEmpty (name) ? placeholder : name;
269273
var textWidth = GetWidthForString (TextField.Font, value);

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectValueView.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public MacDebuggerObjectValueView (MacObjectValueTreeView treeView) : base (tree
8282

8383
int imageSize = treeView.CompactView ? CompactImageSize : ImageSize;
8484
viewerButton = new NSButton {
85+
AccessibilityTitle = GettextCatalog.GetString ("Open Value Visualizer"),
8586
Image = GetImage (Gtk.Stock.Edit, imageSize, imageSize),
8687
TranslatesAutoresizingMaskIntoConstraints = false
8788
};
@@ -188,7 +189,9 @@ protected override void UpdateContents ()
188189
// First item: Status Icon -or- Spinner
189190
if (evaluateStatusIcon != null) {
190191
statusIcon.Image = GetImage (evaluateStatusIcon, Gtk.IconSize.Menu, selected);
191-
192+
statusIcon.AccessibilityTitle = ObjectValueTreeViewController.GetAccessibilityTitleForIcon (
193+
evaluateStatusIcon,
194+
GettextCatalog.GetString ("Object Value"));
192195
if (!statusIconVisible) {
193196
AddSubview (statusIcon);
194197
statusIconVisible = true;

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueTreeViewController.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,48 @@ public static string GetIcon (ObjectValueFlags flags)
964964
return "md-" + access + global + source;
965965
}
966966

967+
internal static string GetAccessibilityTitleForIcon (ObjectValueFlags flags, string defaultTitle = null)
968+
{
969+
if ((flags & ObjectValueFlags.Field) != 0 && (flags & ObjectValueFlags.ReadOnly) != 0)
970+
return GettextCatalog.GetString ("Literal");
971+
972+
string global = (flags & ObjectValueFlags.Global) != 0 ? GettextCatalog.GetString ("Static") : string.Empty;
973+
string source;
974+
975+
switch (flags & ObjectValueFlags.OriginMask) {
976+
case ObjectValueFlags.Property: source = GettextCatalog.GetString ("Property"); break;
977+
case ObjectValueFlags.Type: source = GettextCatalog.GetString ("Class"); global = string.Empty; break;
978+
case ObjectValueFlags.Method: source = GettextCatalog.GetString ("Method"); break;
979+
case ObjectValueFlags.Literal: return GettextCatalog.GetString ("Literal");
980+
case ObjectValueFlags.Namespace: return GettextCatalog.GetString ("Namespace");
981+
case ObjectValueFlags.Group: return GettextCatalog.GetString ("Open Resource Folder");
982+
case ObjectValueFlags.Field: source = GettextCatalog.GetString ("Field"); break;
983+
case ObjectValueFlags.Variable: return GettextCatalog.GetString ("Variable");
984+
default: return defaultTitle;
985+
}
986+
987+
string access;
988+
switch (flags & ObjectValueFlags.AccessMask) {
989+
case ObjectValueFlags.Private: access = GettextCatalog.GetString ("Private"); break;
990+
case ObjectValueFlags.Internal: access = GettextCatalog.GetString ("Internal"); break;
991+
case ObjectValueFlags.InternalProtected:
992+
case ObjectValueFlags.Protected: access = GettextCatalog.GetString ("Protected"); break;
993+
default: access = string.Empty; break;
994+
}
995+
996+
return access + " " + global + " " + source;
997+
}
998+
999+
internal static string GetAccessibilityTitleForIcon (string iconName, string defaultTitle)
1000+
{
1001+
switch (iconName) {
1002+
case "md-warning":
1003+
return GettextCatalog.GetString ("Warning");
1004+
default:
1005+
return defaultTitle;
1006+
}
1007+
}
1008+
9671009
static int GetKnownImageId (ObjectValueFlags flags)
9681010
{
9691011
var name = GetIcon (flags);

0 commit comments

Comments
 (0)