diff options
-rw-r--r-- | main/.nuget/packages.config | 1 | ||||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj | 18 | ||||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs | 565 | ||||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16.png | bin | 0 -> 478 bytes | |||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16@2x.png | bin | 0 -> 1054 bytes | |||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon.png | bin | 0 -> 609 bytes | |||
-rw-r--r-- | main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon@2x.png | bin | 0 -> 1316 bytes |
7 files changed, 365 insertions, 219 deletions
diff --git a/main/.nuget/packages.config b/main/.nuget/packages.config index 0901fded19..ebd34ccb09 100644 --- a/main/.nuget/packages.config +++ b/main/.nuget/packages.config @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="NuGet.CommandLine" version="2.8.2" /> + <package id="NUnit.Runners" version="2.6.4" /> </packages>
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj index 127da92151..3bece5c534 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj @@ -401,12 +401,6 @@ <EmbeddedResource Include="icons\lightning-16~dark~disabled%402x.png"> <LogicalName>lightning-16~dark~disabled@2x.png</LogicalName> </EmbeddedResource> - <EmbeddedResource Include="icons\exception-48.png"> - <LogicalName>exception-48.png</LogicalName> - </EmbeddedResource> - <EmbeddedResource Include="icons\exception-48%402x.png"> - <LogicalName>exception-48@2x.png</LogicalName> - </EmbeddedResource> <EmbeddedResource Include="icons\exception-48~dark.png"> <LogicalName>exception-48~dark.png</LogicalName> </EmbeddedResource> @@ -515,6 +509,18 @@ <EmbeddedResource Include="icons\stack-pointer-16%402x.png"> <LogicalName>stack-pointer-16@2x.png</LogicalName> </EmbeddedResource> + <EmbeddedResource Include="icons\toolbar-icon.png"> + <LogicalName>toolbar-icon.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\toolbar-icon%402x.png"> + <LogicalName>toolbar-icon@2x.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\exception-outline-16.png"> + <LogicalName>exception-outline-16.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\exception-outline-16%402x.png"> + <LogicalName>exception-outline-16@2x.png</LogicalName> + </EmbeddedResource> <EmbeddedResource Include="icons\stack-pointer-16~dark.png"> <LogicalName>stack-pointer-16~dark.png</LogicalName> </EmbeddedResource> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs index 602cc05c42..da38a4f745 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs @@ -45,18 +45,27 @@ namespace MonoDevelop.Debugger { class ExceptionCaughtDialog : Gtk.Dialog { - static readonly Xwt.Drawing.Image WarningIconPixbuf = Xwt.Drawing.Image.FromResource ("exception-48.png"); + static readonly Xwt.Drawing.Image WarningIconPixbuf = Xwt.Drawing.Image.FromResource ("toolbar-icon.png"); + static readonly Xwt.Drawing.Image WarningIconPixbufInner = Xwt.Drawing.Image.FromResource ("exception-outline-16.png"); + protected ObjectValueTreeView ExceptionValueTreeView { get; private set; } + protected TreeView StackTraceTreeView { get; private set; } + protected CheckButton OnlyShowMyCodeCheckbox { get; private set; } + protected Label ExceptionMessageLabel { get; private set; } + protected Label ExceptionTypeLabel { get; private set; } + readonly ExceptionCaughtMessage message; readonly ExceptionInfo exception; ExceptionInfo selected; bool destroyed; + VPaned paned; - protected enum ModelColumn { + protected enum ModelColumn + { StackFrame, Markup, IsUserCode @@ -64,6 +73,7 @@ namespace MonoDevelop.Debugger public ExceptionCaughtDialog (ExceptionInfo ex, ExceptionCaughtMessage msg) { + this.Name = "wizard_dialog"; this.ApplyTheme (); selected = exception = ex; message = msg; @@ -74,41 +84,49 @@ namespace MonoDevelop.Debugger exception.Changed += ExceptionChanged; } - Widget CreateExceptionInfoHeader () + Widget CreateExceptionHeader () { - ExceptionMessageLabel = new Label { UseMarkup = true, Selectable = true, Wrap = true, WidthRequest = 500, Xalign = 0.0f, Yalign = 0.0f }; - ExceptionTypeLabel = new Label { UseMarkup = true, Xalign = 0.0f }; + var icon = new ImageView (WarningIconPixbuf); + icon.Yalign = 0; - ExceptionMessageLabel.Show (); - ExceptionTypeLabel.Show (); + ExceptionTypeLabel = new Label { Xalign = 0.0f }; + ExceptionMessageLabel = new Label { Wrap = true, Xalign = 0.0f }; + ExceptionTypeLabel.ModifyFg (StateType.Normal, new Gdk.Color (255, 255, 255)); + ExceptionMessageLabel.ModifyFg (StateType.Normal, new Gdk.Color (255, 255, 255)); - var alignment = new Alignment (0.0f, 0.0f, 0.0f, 0.0f); - alignment.Child = ExceptionMessageLabel; - alignment.BorderWidth = 6; - alignment.Show (); + if (Platform.IsWindows) { + ExceptionTypeLabel.ModifyFont (Pango.FontDescription.FromString ("bold 19")); + ExceptionMessageLabel.ModifyFont (Pango.FontDescription.FromString ("10")); + } else { + ExceptionTypeLabel.ModifyFont (Pango.FontDescription.FromString ("21")); + ExceptionMessageLabel.ModifyFont (Pango.FontDescription.FromString ("12")); + } - var frame = new InfoFrame (alignment); - frame.Show (); + //Force rendering of background with EventBox + var eventBox = new EventBox (); + var hBox = new HBox (); + var leftVBox = new VBox (); + var rightVBox = new VBox (); - var vbox = new VBox (false, 12); - vbox.PackStart (ExceptionTypeLabel, false, true, 0); - vbox.PackStart (frame, true, true, 0); - vbox.Show (); + leftVBox.PackStart (icon, false, false, (uint)(Platform.IsWindows ? 5 : 0)); // as we change frame.BorderWidth below, we need to compensate - return vbox; - } + rightVBox.PackStart (ExceptionTypeLabel, false, false, (uint)(Platform.IsWindows ? 0 : 2)); + rightVBox.PackStart (ExceptionMessageLabel, true, true, (uint)(Platform.IsWindows ? 6 : 5)); - Widget CreateExceptionHeader () - { - var icon = new ImageView (WarningIconPixbuf); - icon.Show (); + hBox.PackStart (leftVBox, false, false, (uint)(Platform.IsWindows ? 5 : 0)); // as we change frame.BorderWidth below, we need to compensate + hBox.PackStart (rightVBox, true, true, (uint)(Platform.IsWindows ? 5 : 10)); + + var frame = new Frame (); + frame.Add (hBox); + frame.BorderWidth = (uint)(Platform.IsWindows ? 5 : 10); // on Windows we need to have smaller border due to ExceptionTypeLabel vertical misalignment + frame.Shadow = ShadowType.None; + frame.ShadowType = ShadowType.None; - var hbox = new HBox (false, 12) { BorderWidth = 12 }; - hbox.PackStart (icon, false, true, 0); - hbox.PackStart (CreateExceptionInfoHeader (), true, true, 0); - hbox.Show (); + eventBox.Add (frame); + eventBox.ShowAll (); + eventBox.ModifyBg (StateType.Normal, new Gdk.Color (119, 130, 140)); - return hbox; + return eventBox; } Widget CreateExceptionValueTreeView () @@ -121,26 +139,53 @@ namespace MonoDevelop.Debugger ExceptionValueTreeView.AllowPinning = false; ExceptionValueTreeView.AllowEditing = false; ExceptionValueTreeView.AllowAdding = false; + ExceptionValueTreeView.RulesHint = true; + ExceptionValueTreeView.ModifyFont (Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11")); ExceptionValueTreeView.RulesHint = false; - ExceptionValueTreeView.Selection.Changed += ExceptionValueSelectionChanged; ExceptionValueTreeView.Show (); - var scrolled = new ScrolledWindow { HeightRequest = 180, HscrollbarPolicy = PolicyType.Automatic, VscrollbarPolicy = PolicyType.Automatic }; + var scrolled = new ScrolledWindow { + HeightRequest = 180, + HscrollbarPolicy = PolicyType.Automatic, + VscrollbarPolicy = PolicyType.Automatic + }; scrolled.ShadowType = ShadowType.None; scrolled.Add (ExceptionValueTreeView); scrolled.Show (); + var vbox = new VBox (); + vbox.Show (); + vbox.PackStart (CreateSeparator (), false, true, 7); + vbox.PackStart (WrapInExpander (GettextCatalog.GetString ("Properties"), scrolled), true, true, 0); + return vbox; + } - return scrolled; + Expander WrapInExpander (string title, Widget widget) + { + var expander = new Expander (string.Format ("<b>{0}</b>", GLib.Markup.EscapeText (title))); + expander.Child = widget; + expander.Spacing = 0; + expander.Show (); + expander.CanFocus = false; + expander.UseMarkup = true; + expander.Expanded = true; + expander.Activated += Expander_Activated; + expander.ModifyBg (StateType.Prelight, new Gdk.Color (255, 255, 255)); + return expander; + } + + void Expander_Activated (object sender, EventArgs e) + { + paned.PositionSet = false; } static void StackFrameLayout (CellLayout layout, CellRenderer cr, TreeModel model, TreeIter iter) { - var frame = (ExceptionStackFrame) model.GetValue (iter, (int) ModelColumn.StackFrame); - var renderer = (StackFrameCellRenderer) cr; + var frame = (ExceptionStackFrame)model.GetValue (iter, (int)ModelColumn.StackFrame); + var renderer = (StackFrameCellRenderer)cr; - renderer.Markup = (string) model.GetValue (iter, (int) ModelColumn.Markup); + renderer.Markup = (string)model.GetValue (iter, (int)ModelColumn.Markup); renderer.Frame = frame; if (frame == null) { @@ -148,38 +193,44 @@ namespace MonoDevelop.Debugger return; } - renderer.IsUserCode = (bool) model.GetValue (iter, (int) ModelColumn.IsUserCode); + renderer.IsUserCode = (bool)model.GetValue (iter, (int)ModelColumn.IsUserCode); } Widget CreateStackTraceTreeView () { - var store = new ListStore (typeof (ExceptionStackFrame), typeof (string), typeof (bool)); + var store = new ListStore (typeof(ExceptionStackFrame), typeof(string), typeof(bool)); StackTraceTreeView = new TreeView (store); StackTraceTreeView.FixedHeightMode = false; StackTraceTreeView.HeadersVisible = false; StackTraceTreeView.ShowExpanders = false; - StackTraceTreeView.RulesHint = true; + StackTraceTreeView.RulesHint = false; StackTraceTreeView.Show (); var renderer = new StackFrameCellRenderer (StackTraceTreeView.PangoContext); - renderer.Width = DefaultWidth; - StackTraceTreeView.AppendColumn ("", renderer, (CellLayoutDataFunc) StackFrameLayout); + StackTraceTreeView.AppendColumn ("", renderer, (CellLayoutDataFunc)StackFrameLayout); - StackTraceTreeView.SizeAllocated += (o, args) => renderer.Width = args.Allocation.Width; StackTraceTreeView.RowActivated += StackFrameActivated; - var scrolled = new ScrolledWindow { HeightRequest = 180, HscrollbarPolicy = PolicyType.Automatic, VscrollbarPolicy = PolicyType.Automatic }; + var scrolled = new ScrolledWindow { + HeightRequest = 180, + HscrollbarPolicy = PolicyType.Never, + VscrollbarPolicy = PolicyType.Automatic + }; scrolled.ShadowType = ShadowType.None; scrolled.Add (StackTraceTreeView); scrolled.Show (); + var vbox = new VBox (); + vbox.PackStart (CreateSeparator (), false, true, 0); + vbox.PackStart (scrolled, true, true, 0); + vbox.Show (); - return scrolled; + return WrapInExpander (GettextCatalog.GetString ("Stacktrace"), vbox); } Widget CreateButtonBox () { - var buttons = new HButtonBox { Layout = ButtonBoxStyle.End, Spacing = 12 }; + var buttons = new HButtonBox { Layout = ButtonBoxStyle.End, Spacing = 18 }; var copy = new Button (Stock.Copy); copy.Clicked += CopyClicked; @@ -206,29 +257,49 @@ namespace MonoDevelop.Debugger return separator; } + bool HasInnerException () + { + return exception.InnerException != null; + } + + bool hadInnerException; + void Build () { Title = GettextCatalog.GetString ("Exception Caught"); - DefaultHeight = 500; - DefaultWidth = 600; - VBox.Spacing = 0; - + HeightRequest = 500; + WidthRequest = 600; + VBox.Foreach (VBox.Remove); VBox.PackStart (CreateExceptionHeader (), false, true, 0); - - var paned = new VPaned (); - paned.Add1 (CreateExceptionValueTreeView ()); - paned.Add2 (CreateStackTraceTreeView ()); + paned = new VPaned (); + paned.Pack1 (CreateStackTraceTreeView (), true, true); + paned.Pack2 (CreateExceptionValueTreeView (), true, true); paned.Show (); - var vbox = new VBox (false, 0); - vbox.PackStart (CreateSeparator (), false, true, 0); + var whiteBackground = new EventBox (); + whiteBackground.Show (); + whiteBackground.ModifyBg (StateType.Normal, new Gdk.Color (255, 255, 255)); + whiteBackground.Add (vbox); + hadInnerException = HasInnerException (); + if (hadInnerException) { + vbox.PackStart (CreateInnerExceptionMessage (), false, true, 12); + } vbox.PackStart (paned, true, true, 0); - vbox.PackStart (CreateSeparator (), false, true, 0); vbox.Show (); - VBox.PackStart (vbox, true, true, 0); + if (hadInnerException) { + var box = new HBox (); + box.PackStart (CreateInnerExceptionsTree (), false, false, 0); + box.PackStart (whiteBackground, true, true, 0); + box.Show (); + VBox.PackStart (box, true, true, 0); + WidthRequest = 900; + HeightRequest = 700; + } else { + VBox.PackStart (whiteBackground, true, true, 0); + } - var actionArea = new HBox (false, 12) { BorderWidth = 6 }; + var actionArea = new HBox (false, 0) { BorderWidth = 14 }; OnlyShowMyCodeCheckbox = new CheckButton (GettextCatalog.GetString ("_Only show my code.")); OnlyShowMyCodeCheckbox.Toggled += OnlyShowMyCodeToggled; @@ -240,55 +311,107 @@ namespace MonoDevelop.Debugger actionArea.PackStart (alignment, true, true, 0); actionArea.PackStart (CreateButtonBox (), false, true, 0); - actionArea.Show (); + actionArea.PackStart (new VBox (), false, true, 3); // dummy just to take extra 6px at end to make it 20pixels + actionArea.ShowAll (); VBox.PackStart (actionArea, false, true, 0); ActionArea.Hide (); } - bool TryGetExceptionInfo (TreePath path, out ExceptionInfo ex) - { - var model = (TreeStore) ExceptionValueTreeView.Model; - TreeIter iter, parent; - - ex = exception; - - if (!model.GetIter (out iter, path)) - return false; - - var value = (ObjectValue) model.GetValue (iter, ObjectValueTreeView.ObjectColumn); - if (value.Name != "InnerException") - return false; - - int depth = 0; - while (model.IterParent (out parent, iter)) { - iter = parent; - depth++; - } - - while (ex != null) { - if (depth == 0) - return true; - - ex = ex.InnerException; - depth--; - } - - return false; + Label InnerExceptionTypeLabel; + Label InnerExceptionMessageLabel; + + Widget CreateInnerExceptionMessage () + { + var hboxMain = new HBox (); + var vbox = new VBox (); + var hbox = new HBox (); + + var icon = new ImageView (WarningIconPixbufInner); + icon.Yalign = 0; + hbox.PackStart (icon, false, false, 0); + + InnerExceptionTypeLabel = new Label (); + InnerExceptionTypeLabel.UseMarkup = true; + InnerExceptionTypeLabel.Xalign = 0; + hbox.PackStart (InnerExceptionTypeLabel, false, true, 4); + + InnerExceptionMessageLabel = new Label (); + InnerExceptionMessageLabel.Wrap = true; + InnerExceptionMessageLabel.Xalign = 0; + InnerExceptionMessageLabel.ModifyFont (Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11")); + vbox.PackStart (hbox, false, true, 0); + vbox.PackStart (InnerExceptionMessageLabel, true, true, 10); + hboxMain.PackStart (vbox, true, true, 10); + hboxMain.ShowAll (); + return hboxMain; + } + + TreeStore InnerExceptionsStore; + TreeView InnerExceptionsTreeView; + + Widget CreateInnerExceptionsTree () + { + InnerExceptionsTreeView = new TreeView (); + InnerExceptionsTreeView.ModifyBase (StateType.Normal, new Gdk.Color (225, 228, 232)); // background + InnerExceptionsTreeView.ModifyBase (StateType.Selected, new Gdk.Color (205, 208, 212)); // selected + InnerExceptionsTreeView.HeadersVisible = false; + InnerExceptionsStore = new TreeStore (typeof(ExceptionInfo)); + + FillInnerExceptionsStore (InnerExceptionsStore, exception); + InnerExceptionsTreeView.AppendColumn ("Exception", new CellRendererInnerException (), new TreeCellDataFunc ((tree_column, cell, tree_model, iter) => { + var c = (CellRendererInnerException)cell; + c.Text = ((ExceptionInfo)tree_model.GetValue (iter, 0)).Type; + })); + InnerExceptionsTreeView.ShowExpanders = false; + InnerExceptionsTreeView.LevelIndentation = 10; + InnerExceptionsTreeView.Model = InnerExceptionsStore; + InnerExceptionsTreeView.ExpandAll (); + InnerExceptionsTreeView.Selection.Changed += (sender, e) => { + TreeIter selectedIter; + if (InnerExceptionsTreeView.Selection.GetSelected (out selectedIter)) { + UpdateSelectedException ((ExceptionInfo)InnerExceptionsTreeView.Model.GetValue (selectedIter, 0)); + } + }; + var eventBox = new EventBox (); + eventBox.ModifyBg (StateType.Normal, new Gdk.Color (225, 228, 232)); // top and bottom padders + var vbox = new VBox (); + vbox.PackStart (InnerExceptionsTreeView, true, true, 9); + eventBox.Add (vbox); + eventBox.ShowAll (); + return eventBox; } - void ExceptionValueSelectionChanged (object sender, EventArgs e) + void FillInnerExceptionsStore (TreeStore store, ExceptionInfo exception, TreeIter parentIter = default (TreeIter)) { - var selectedRows = ExceptionValueTreeView.Selection.GetSelectedRows (); - ExceptionInfo ex; - - if (selectedRows.Length > 0 && TryGetExceptionInfo (selectedRows[0], out ex)) { - ShowStackTrace (ex); - selected = ex; - } else if (selected != exception) { - ShowStackTrace (exception); - selected = exception; + TreeIter iter; + if (parentIter.Equals (TreeIter.Zero)) { + iter = store.AppendValues (exception); + } else { + iter = store.AppendValues (parentIter, exception); } + var updateInnerExceptions = new System.Action (() => { + if (!InnerExceptionsStore.IterHasChild (iter)) { + var innerExceptions = exception.InnerExceptions; + if (innerExceptions != null && innerExceptions.Count > 0) { + foreach (var inner in innerExceptions) { + FillInnerExceptionsStore (store, inner, iter); + } + } else { + var inner = exception.InnerException; + if (inner != null) + FillInnerExceptionsStore (store, inner, iter); + } + } + }); + exception.Changed += delegate { + Application.Invoke (delegate { + InnerExceptionsStore.EmitRowChanged (InnerExceptionsStore.GetPath (iter), iter); + updateInnerExceptions (); + InnerExceptionsTreeView.ExpandRow (InnerExceptionsStore.GetPath (iter), true); + }); + }; + updateInnerExceptions (); } void StackFrameActivated (object o, RowActivatedArgs args) @@ -299,7 +422,7 @@ namespace MonoDevelop.Debugger if (!model.GetIter (out iter, args.Path)) return; - var frame = (ExceptionStackFrame) model.GetValue (iter, (int) ModelColumn.StackFrame); + var frame = (ExceptionStackFrame)model.GetValue (iter, (int)ModelColumn.StackFrame); if (frame != null && !string.IsNullOrEmpty (frame.File) && File.Exists (frame.File)) { try { @@ -317,9 +440,10 @@ namespace MonoDevelop.Debugger return IdeApp.Workspace.GetProjectsContainingFile (frame.File).Any (); } - void ShowStackTrace (ExceptionInfo ex) + void UpdateSelectedException (ExceptionInfo ex) { - var model = (ListStore) StackTraceTreeView.Model; + selected = ex; + var model = (ListStore)StackTraceTreeView.Model; bool external = false; model.Clear (); @@ -340,11 +464,22 @@ namespace MonoDevelop.Debugger model.AppendValues (frame, null, isUserCode); external = false; } + ExceptionValueTreeView.ClearAll (); + if (!ex.IsEvaluating && ex.Instance != null) { + var opts = DebuggingService.GetUserOptions ().EvaluationOptions.Clone (); + opts.FlattenHierarchy = true; + ExceptionValueTreeView.AddValues (ex.Instance.GetAllChildren (opts)); + } if (ex.StackIsEvaluating) { var str = GettextCatalog.GetString ("Loading..."); model.AppendValues (null, str, false); } + + if (InnerExceptionTypeLabel != null) { + InnerExceptionTypeLabel.Markup = "<b>" + GLib.Markup.EscapeText (ex.Type) + "</b>"; + InnerExceptionMessageLabel.Text = ex.Message; + } } void UpdateDisplay () @@ -352,29 +487,24 @@ namespace MonoDevelop.Debugger if (destroyed) return; - ExceptionValueTreeView.ClearValues (); - - ExceptionTypeLabel.Markup = GettextCatalog.GetString ("A <b>{0}</b> was thrown.", exception.Type); - ExceptionMessageLabel.Markup = "<small>" + (exception.Message ?? string.Empty) + "</small>"; + ExceptionTypeLabel.Text = exception.Type; + ExceptionMessageLabel.Text = exception.Message ?? string.Empty; - if (!exception.IsEvaluating && exception.Instance != null) { - ExceptionValueTreeView.AddValue (exception.Instance); - ExceptionValueTreeView.ExpandRow (new TreePath ("0"), false); - } - - ShowStackTrace (exception); + UpdateSelectedException (exception); } void ExceptionChanged (object sender, EventArgs e) { Application.Invoke (delegate { + if (hadInnerException != HasInnerException ()) + Build (); UpdateDisplay (); }); } void OnlyShowMyCodeToggled (object sender, EventArgs e) { - ShowStackTrace (selected); + UpdateSelectedException (selected); } void CloseClicked (object sender, EventArgs e) @@ -405,138 +535,138 @@ namespace MonoDevelop.Debugger exception.Changed -= ExceptionChanged; base.OnDestroyed (); } + + class CellRendererInnerException : CellRenderer + { + public string Text { get; set; } + + Pango.FontDescription font = Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11"); + + public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + { + using (var layout = new Pango.Layout (widget.PangoContext)) { + layout.FontDescription = font; + Pango.Rectangle ink, logical; + layout.SetMarkup ("<b>" + Text + "</b>"); + layout.GetPixelExtents (out ink, out logical); + width = logical.Width + 10; + height = logical.Height + 6; + + x_offset = 0; + y_offset = 0; + } + } + + protected override void Render (Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags) + { + using (var cr = Gdk.CairoHelper.Create (window)) { + cr.Rectangle (background_area.X, background_area.Y, background_area.Width, background_area.Height); + + using (var layout = new Pango.Layout (widget.PangoContext)) { + layout.FontDescription = font; + + if ((flags & CellRendererState.Selected) != 0) { + cr.SetSourceRGB (205 / 256.0, 208 / 256.0, 212 / 256.0); // selected + cr.Fill (); + cr.SetSourceColor (new Cairo.Color (0, 0, 0)); + layout.SetMarkup ("<b>" + Text + "</b>"); + } else { + cr.SetSourceRGB (225 / 256.0, 228 / 256.0, 232 / 256.0); // background + cr.Fill (); + cr.SetSourceColor (new Cairo.Color (0, 0, 0)); + layout.SetMarkup (Text); + } + + cr.Translate (cell_area.X + 10, cell_area.Y + 3); + cr.ShowLayout (layout); + } + } + } + } } class StackFrameCellRenderer : CellRenderer { - static readonly Pango.FontDescription LineNumberFont = FontService.MonospaceFont.CopyModified (Ide.Gui.Styles.FontScale11); - const int RoundedRectangleRadius = 2; - const int RoundedRectangleHeight = 14; - const int RoundedRectangleWidth = 28; const int Padding = 6; public readonly Pango.Context Context; public ExceptionStackFrame Frame; public bool IsUserCode; public string Markup; + Pango.FontDescription font = Pango.FontDescription.FromString (Platform.IsWindows ? "9" : "11"); public StackFrameCellRenderer (Pango.Context ctx) { Context = ctx; } - int MaxMarkupWidth { - get { - if (Width < 0) - return Width; - - return Width - (Padding + RoundedRectangleWidth + Padding + Padding + Padding); - } - } - - public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + string GetMethodMarkup (bool selected) { - using (var layout = new Pango.Layout (Context)) { - Pango.Rectangle ink, logical; - - layout.Width = (int) (MaxMarkupWidth * Pango.Scale.PangoScale); - layout.SetMarkup (GetMarkup (false, widget)); + if (Markup != null) + return Markup; + var methodText = Frame.DisplayText; + var endOfMethodName = methodText.IndexOf ('('); + var methodName = methodText.Remove (endOfMethodName).Trim (); + var endOfParameters = methodText.IndexOf (')') + 1; + var parameters = methodText.Substring (endOfMethodName, endOfParameters - endOfMethodName).Trim (); - layout.GetPixelExtents (out ink, out logical); + var markup = string.Format ("<b>{0}</b> {1}", GLib.Markup.EscapeText (methodName), GLib.Markup.EscapeText (parameters)); - width = Padding + RoundedRectangleWidth + Padding + Padding + logical.Width + Padding; - height = Padding + Math.Max (RoundedRectangleHeight, logical.Height) + Padding; + if (selected) + markup = "<span foreground='#FFFFFF'>" + markup + "</span>"; - x_offset = 0; - y_offset = 0; - } + return markup; } - void RenderLineNumberIcon (Widget widget, Cairo.Context cr, Gdk.Rectangle cell_area, int markupHeight, int yOffset) + string GetFileMarkup (bool selected) { - if (Frame == null) - return; - - cr.Save (); - - #if CENTER_ROUNDED_RECTANGLE - cr.Translate (cell_area.X + Padding, (cell_area.Y + (cell_area.Height - RoundedRectangleHeight) / 2.0)); - #else - cr.Translate (cell_area.X + Padding, cell_area.Y + Padding + yOffset); - #endif - - cr.Antialias = Cairo.Antialias.Subpixel; - - cr.RoundedRectangle (0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius); - cr.Clip (); - - if (IsUserCode) - cr.SetSourceColor (Styles.ExceptionCaughtDialog.LineNumberInUserCodeBackgroundColor.ToCairoColor ()); // 230, 152, 223 - else - cr.SetSourceColor (Styles.ExceptionCaughtDialog.LineNumberBackgroundColor.ToCairoColor ()); // 197, 197, 197 - - cr.RoundedRectangle (0.0, 0.0, RoundedRectangleWidth, RoundedRectangleHeight, RoundedRectangleRadius); - cr.Fill (); - - var lineNumber = !string.IsNullOrEmpty (Frame.File) ? Frame.Line : -1; - - using (var layout = PangoUtil.CreateLayout (widget, lineNumber != -1 ? lineNumber.ToString () : "???")) { - layout.Alignment = Pango.Alignment.Left; - layout.FontDescription = LineNumberFont; - - int width, height; - layout.GetPixelSize (out width, out height); - - double y_offset = (RoundedRectangleHeight - height) / 2.0; - double x_offset = (RoundedRectangleWidth - width) / 2.0; - - cr.SetSourceColor (Styles.ExceptionCaughtDialog.LineNumberTextColor.ToCairoColor ()); - cr.Translate (x_offset, y_offset); - cr.ShowLayout (layout); + if (Frame == null || string.IsNullOrEmpty (Frame.File)) { + return ""; } - cr.Restore (); + var markup = string.Format ("<span foreground='{0}'>{1}", selected ? "#FFFFFF" : "#BBBBBB", GLib.Markup.EscapeText (Path.GetFileName (Frame.File))); + if (Frame.Line > 0) { + markup += ":" + Frame.Line; + if (Frame.Column > 0) + markup += "," + Frame.Column; + } + markup += "</span>"; + return markup; } - string GetMarkup (bool selected, Gtk.Widget parent) + public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) { - string text_color = selected ? parent.Style.Text (StateType.Selected).GetHex () : parent.Style.Text (StateType.Normal).GetHex (); - - if (Markup != null) - return "<span foreground='" + text_color + "'>" + Markup + "</span>"; - - var markup = string.Format ("<span foreground='{0}'><b>{1}</b></span>", text_color, GLib.Markup.EscapeText (Frame.DisplayText)); + using (var layout = new Pango.Layout (Context)) { + Pango.Rectangle ink, logical; + layout.FontDescription = font; + layout.SetMarkup (GetMethodMarkup (false)); + layout.GetPixelExtents (out ink, out logical); - if (!string.IsNullOrEmpty (Frame.File)) { - markup += string.Format ("<span size='4096'>\n\n</span><span size='small' foreground='{0}'>{1}", text_color, GLib.Markup.EscapeText (Frame.File)); - if (Frame.Line > 0) { - markup += ":" + Frame.Line; - if (Frame.Column > 0) - markup += "," + Frame.Column; - } - markup += "</span>"; + height = logical.Height; + width = 0; + x_offset = 0; + y_offset = 0; } - - return markup; } protected override void Render (Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags) { using (var cr = Gdk.CairoHelper.Create (window)) { + Pango.Rectangle ink, logical; using (var layout = new Pango.Layout (Context)) { - Pango.Rectangle ink, logical; - - layout.Width = (int) (MaxMarkupWidth * Pango.Scale.PangoScale); - layout.SetMarkup (GetMarkup ((flags & CellRendererState.Selected) != 0, widget)); - + layout.FontDescription = font; + layout.SetMarkup (GetFileMarkup ((flags & CellRendererState.Selected) != 0)); layout.GetPixelExtents (out ink, out logical); + var width = widget.Allocation.Width; + cr.Translate (width - logical.Width - 10, cell_area.Y); + cr.ShowLayout (layout); - RenderLineNumberIcon (widget, cr, cell_area, logical.Height, ink.Y); - - cr.Rectangle (expose_area.X, expose_area.Y, expose_area.Width, expose_area.Height); - cr.Clip (); + cr.IdentityMatrix (); - cr.Translate (cell_area.X + Padding + RoundedRectangleWidth + Padding + Padding, cell_area.Y + Padding); + layout.SetMarkup (GetMethodMarkup ((flags & CellRendererState.Selected) != 0)); + layout.Width = (int)((width - logical.Width - 35) * Pango.Scale.PangoScale); + layout.Ellipsize = Pango.EllipsizeMode.Middle; + cr.Translate (cell_area.X + 10, cell_area.Y); cr.ShowLayout (layout); } } @@ -558,11 +688,13 @@ namespace MonoDevelop.Debugger } public FilePath File { - get; private set; + get; + private set; } public int Line { - get; set; + get; + set; } public bool IsMinimized { @@ -638,13 +770,14 @@ namespace MonoDevelop.Debugger public event EventHandler Closed; } - class ExceptionCaughtButton: TopLevelWidgetExtension + class ExceptionCaughtButton : TopLevelWidgetExtension { readonly Xwt.Drawing.Image closeSelOverImage; readonly Xwt.Drawing.Image closeSelImage; readonly ExceptionCaughtMessage dlg; readonly ExceptionInfo exception; Label messageLabel; + Label typeLabel; public ExceptionCaughtButton (ExceptionInfo val, ExceptionCaughtMessage dlg, FilePath file, int line) { @@ -673,10 +806,10 @@ namespace MonoDevelop.Debugger vb.PackStart (image, false, false, 0); box.PackStart (vb, false, false, 0); vb = new VBox (false, 6); - vb.PackStart (new Label { - Markup = GettextCatalog.GetString ("<b>{0}</b> has been thrown", exception.Type), + typeLabel = new Label { Xalign = 0 - }); + }; + vb.PackStart (typeLabel); messageLabel = new Label { Xalign = 0, NoShowAll = true @@ -685,7 +818,7 @@ namespace MonoDevelop.Debugger var detailsBtn = new Xwt.LinkLabel (GettextCatalog.GetString ("Show Details")); var hh = new HBox (); - detailsBtn.NavigateToUrl += (o,e) => dlg.ShowDialog (); + detailsBtn.NavigateToUrl += (o, e) => dlg.ShowDialog (); hh.PackStart (detailsBtn.ToGtkWidget (), false, false, 0); vb.PackStart (hh, false, false, 0); @@ -730,10 +863,16 @@ namespace MonoDevelop.Debugger } else { messageLabel.Hide (); } + if (!string.IsNullOrEmpty (exception.Type)) { + typeLabel.Show (); + typeLabel.Markup = GettextCatalog.GetString ("<b>{0}</b> has been thrown", GLib.Markup.EscapeText (exception.Type)); + } else { + typeLabel.Hide (); + } } } - class ExceptionCaughtMiniButton: TopLevelWidgetExtension + class ExceptionCaughtMiniButton : TopLevelWidgetExtension { readonly ExceptionCaughtMessage dlg; @@ -757,7 +896,7 @@ namespace MonoDevelop.Debugger box.VisibleWindow = false; var icon = Xwt.Drawing.Image.FromResource ("lightning-16.png"); box.Add (new Xwt.ImageView (icon).ToGtkWidget ()); - box.ButtonPressEvent += (o,e) => dlg.ShowButton (); + box.ButtonPressEvent += (o, e) => dlg.ShowButton (); var eb = new PopoverWidget (); eb.Theme.Padding = 2; eb.ShowArrow = true; @@ -769,7 +908,7 @@ namespace MonoDevelop.Debugger } } - class ExceptionCaughtTextEditorExtension: TextEditorExtension + class ExceptionCaughtTextEditorExtension : TextEditorExtension { public override bool KeyPress (KeyDescriptor descriptor) { diff --git a/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16.png b/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16.png Binary files differnew file mode 100644 index 0000000000..684db7eeba --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16.png diff --git a/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16@2x.png b/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16@2x.png Binary files differnew file mode 100644 index 0000000000..cb91f054c9 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/icons/exception-outline-16@2x.png diff --git a/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon.png b/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon.png Binary files differnew file mode 100644 index 0000000000..de457dabea --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon.png diff --git a/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon@2x.png b/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon@2x.png Binary files differnew file mode 100644 index 0000000000..02371299b1 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/icons/toolbar-icon@2x.png |