29
using System.Threading;
32
28
using Mono.Debugging.Client;
33
29
using MonoDevelop.Core;
31
using System.Threading;
32
using MonoDevelop.Components;
33
using MonoDevelop.Ide.TextEditing;
34
using MonoDevelop.Ide;
35
using MonoDevelop.Ide.Gui.Content;
35
37
namespace MonoDevelop.Debugger
37
public partial class ExceptionCaughtDialog : Gtk.Dialog
39
public partial class ExceptionCaughtWidget : Gtk.Bin
41
Gtk.TreeStore stackStore;
39
42
ExceptionInfo exception;
42
public ExceptionCaughtDialog (ExceptionInfo exception)
45
public ExceptionCaughtWidget (ExceptionInfo exception)
49
stackStore = new TreeStore (typeof(string), typeof(string), typeof(int), typeof(int));
50
treeStack.Model = stackStore;
51
var crt = new CellRendererText ();
53
crt.WrapMode = Pango.WrapMode.WordChar;
54
treeStack.AppendColumn ("", crt, "markup", 0);
55
treeStack.ShowExpanders = false;
48
57
valueView.AllowExpanding = true;
49
58
valueView.Frame = DebuggingService.CurrentFrame;
50
59
this.exception = exception;
52
61
exception.Changed += HandleExceptionChanged;
62
treeStack.SizeAllocated += delegate(object o, SizeAllocatedArgs args) {
63
if (crt.WrapWidth != args.Allocation.Width)
64
crt.WrapWidth = args.Allocation.Width;
68
treeStack.RowActivated += HandleRowActivated;
71
void HandleRowActivated (object o, RowActivatedArgs args)
74
if (!stackStore.GetIter (out it, args.Path))
76
string file = (string) stackStore.GetValue (it, 1);
77
int line = (int) stackStore.GetValue (it, 2);
78
if (!string.IsNullOrEmpty (file))
79
IdeApp.Workbench.OpenDocument (file, line, 0);
57
82
void HandleExceptionChanged (object sender, EventArgs e)
69
95
valueView.ClearValues ();
71
97
labelType.Markup = GettextCatalog.GetString ("<b>{0}</b> has been thrown", exception.Type);
72
labelMessage.Text = string.IsNullOrEmpty (exception.Message)?
98
labelMessage.Text = string.IsNullOrEmpty (exception.Message) ?
74
100
exception.Message;
76
if (!exception.IsEvaluating) {
77
StringBuilder stack = new StringBuilder ();
78
ShowStackTrace (stack, exception);
79
stackTextView.Buffer.Text = stack.ToString ();
81
if (exception.Instance != null) {
82
valueView.AddValue (exception.Instance);
83
valueView.ExpandRow (new TreePath ("0"), false);
102
ShowStackTrace (exception, false);
104
if (!exception.IsEvaluating && exception.Instance != null) {
105
valueView.AddValue (exception.Instance);
106
valueView.ExpandRow (new TreePath ("0"), false);
108
if (exception.StackIsEvaluating) {
109
stackStore.AppendValues (GettextCatalog.GetString ("Loading..."), "", 0, 0);
113
void ShowStackTrace (ExceptionInfo exc, bool showExceptionNode)
115
TreeIter it = TreeIter.Zero;
116
if (showExceptionNode) {
117
treeStack.ShowExpanders = true;
118
string tn = exc.Type + ": " + exc.Message;
119
it = stackStore.AppendValues (tn, null, 0, 0);
122
foreach (ExceptionStackFrame frame in exc.StackTrace) {
123
string text = GLib.Markup.EscapeText (frame.DisplayText);
124
if (!string.IsNullOrEmpty (frame.File)) {
125
text += "\n<small>" + GLib.Markup.EscapeText (frame.File);
126
if (frame.Line > 0) {
127
text += ":" + frame.Line;
128
if (frame.Column > 0)
129
text += "," + frame.Column;
88
void ShowStackTrace (StringBuilder stack, ExceptionInfo ex)
90
ExceptionInfo inner = ex.InnerException;
93
stack.AppendFormat ("{0}: {1} ---> ", ex.Type, ex.Message);
94
ShowStackTrace (stack, inner);
95
stack.AppendLine (" --- End of inner exception stack trace ---");
97
stack.AppendFormat ("{0}: {1}\n", ex.Type, ex.Message);
100
foreach (ExceptionStackFrame frame in ex.StackTrace) {
102
stack.AppendLine (frame.DisplayText);
106
protected override bool OnDeleteEvent (Gdk.Event evnt)
112
protected virtual void OnButtonOkClicked (object sender, System.EventArgs e)
133
if (!it.Equals (TreeIter.Zero))
134
stackStore.AppendValues (it, text, frame.File, frame.Line, frame.Column);
136
stackStore.AppendValues (text, frame.File, frame.Line, frame.Column);
139
ExceptionInfo inner = exc.InnerException;
141
ShowStackTrace (inner, true);
117
144
protected override void OnDestroyed ()
120
147
exception.Changed -= HandleExceptionChanged;
121
148
base.OnDestroyed ();
152
class ExceptionCaughtDialog: Gtk.Dialog
154
ExceptionCaughtWidget widget;
156
ExceptionCaughtMessage msg;
158
public ExceptionCaughtDialog (ExceptionInfo val, ExceptionCaughtMessage msg)
160
Title = GettextCatalog.GetString ("Exception Caught");
162
widget = new ExceptionCaughtWidget (val);
165
VBox box = new VBox ();
167
box.PackStart (widget, true, true, 0);
168
HButtonBox buttonBox = new HButtonBox ();
169
buttonBox.BorderWidth = 6;
171
var copy = new Gtk.Button (GettextCatalog.GetString ("Copy to Clipboard"));
172
buttonBox.PackStart (copy, false, false, 0);
173
copy.Clicked += HandleCopyClicked;
175
var close = new Gtk.Button (GettextCatalog.GetString ("Close"));
176
buttonBox.PackStart (close, false, false, 0);
177
close.Clicked += (sender, e) => msg.Close ();
178
close.Activated += (sender, e) => msg.Close ();
180
box.PackStart (buttonBox, false, false, 0);
190
protected override bool OnDeleteEvent (Gdk.Event evnt)
196
void HandleCopyClicked (object sender, EventArgs e)
198
var text = ex.ToString ();
199
var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
200
clipboard.Text = text;
201
clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false));
202
clipboard.Text = text;
206
class ExceptionCaughtMessage
209
ExceptionCaughtDialog dialog;
210
ExceptionCaughtButton button;
211
ExceptionCaughtMiniButton miniButton;
213
public ExceptionCaughtMessage (ExceptionInfo val, FilePath file, int line, int col)
220
public FilePath File {
228
public bool IsMinimized {
229
get { return miniButton != null; }
232
public void ShowDialog ()
234
if (dialog == null) {
235
dialog = new ExceptionCaughtDialog (ex, this);
236
MessageService.ShowCustomDialog (dialog, IdeApp.Workbench.RootWindow);
241
public void ShowButton ()
243
if (dialog != null) {
247
if (button == null) {
248
button = new ExceptionCaughtButton (ex, this, File, Line);
249
TextEditorService.RegisterExtension (button);
251
if (miniButton != null) {
252
miniButton.Dispose ();
257
public void ShowMiniButton ()
259
if (dialog != null) {
263
if (button != null) {
267
if (miniButton == null) {
268
miniButton = new ExceptionCaughtMiniButton (this, File, Line);
269
TextEditorService.RegisterExtension (miniButton);
273
public void Dispose ()
275
if (dialog != null) {
279
if (button != null) {
283
if (miniButton != null) {
284
miniButton.Dispose ();
288
Closed (this, EventArgs.Empty);
296
public event EventHandler Closed;
299
class ExceptionCaughtButton: TopLevelWidgetExtension
301
ExceptionCaughtMessage dlg;
302
ExceptionInfo exception;
303
Gtk.Label messageLabel;
304
Gdk.Pixbuf closeSelImage;
305
Gdk.Pixbuf closeSelOverImage;
307
public ExceptionCaughtButton (ExceptionInfo val, ExceptionCaughtMessage dlg, FilePath file, int line)
309
this.exception = val;
314
closeSelImage = Gdk.Pixbuf.LoadFromResource ("MonoDevelop.Close.Selected.png");
315
closeSelOverImage = Gdk.Pixbuf.LoadFromResource ("MonoDevelop.Close.Selected.Over.png");
318
protected override void OnLineDeleted ()
323
public override Widget CreateWidget ()
325
var icon = Gdk.Pixbuf.LoadFromResource ("lightning.png");
326
var image = new Gtk.Image (icon);
328
HBox box = new HBox (false, 6);
329
VBox vb = new VBox ();
330
vb.PackStart (image, false, false, 0);
331
box.PackStart (vb, false, false, 0);
332
vb = new VBox (false, 6);
333
vb.PackStart (new Gtk.Label () {
334
Markup = GettextCatalog.GetString ("<b>{0}</b> has been thrown", exception.Type),
337
messageLabel = new Gtk.Label () {
341
vb.PackStart (messageLabel);
343
var detailsBtn = new Xwt.LinkLabel (GettextCatalog.GetString ("Show Details"));
344
HBox hh = new HBox ();
345
detailsBtn.NavigateToUrl += (o,e) => dlg.ShowDialog ();
346
hh.PackStart (detailsBtn.ToGtkWidget (), false, false, 0);
347
vb.PackStart (hh, false, false, 0);
349
box.PackStart (vb, true, true, 0);
352
var closeButton = new ImageButton () {
353
InactiveImage = closeSelImage,
354
Image = closeSelOverImage
356
closeButton.Clicked += delegate {
357
dlg.ShowMiniButton ();
359
vb.PackStart (closeButton, false, false, 0);
360
box.PackStart (vb, false, false, 0);
362
exception.Changed += delegate {
363
Application.Invoke (delegate {
369
PopoverWidget eb = new PopoverWidget ();
371
eb.EnableAnimation = true;
372
eb.PopupPosition = PopupPosition.Left;
373
eb.ContentBox.Add (box);
380
if (!string.IsNullOrEmpty (exception.Message)) {
381
messageLabel.Show ();
382
messageLabel.Text = exception.Message;
383
if (messageLabel.SizeRequest ().Width > 400) {
384
messageLabel.WidthRequest = 400;
385
messageLabel.Wrap = true;
388
messageLabel.Hide ();
393
class ExceptionCaughtMiniButton: TopLevelWidgetExtension
395
ExceptionCaughtMessage dlg;
397
public ExceptionCaughtMiniButton (ExceptionCaughtMessage dlg, FilePath file, int line)
405
protected override void OnLineDeleted ()
410
public override Widget CreateWidget ()
412
Gtk.EventBox box = new EventBox ();
413
box.VisibleWindow = false;
414
var icon = Gdk.Pixbuf.LoadFromResource ("lightning.png");
415
box.Add (new Gtk.Image (icon));
416
box.ButtonPressEvent += (o,e) => dlg.ShowButton ();
417
PopoverWidget eb = new PopoverWidget ();
418
eb.Theme.Padding = 2;
420
eb.EnableAnimation = true;
421
eb.PopupPosition = PopupPosition.Left;
422
eb.ContentBox.Add (box);
428
class ExceptionCaughtTextEditorExtension: TextEditorExtension
430
public override bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier)
432
if (key == Gdk.Key.Escape && DebuggingService.ExceptionCaughtMessage != null &&
433
!DebuggingService.ExceptionCaughtMessage.IsMinimized &&
434
DebuggingService.ExceptionCaughtMessage.File.CanonicalPath == Document.FileName.CanonicalPath) {
436
DebuggingService.ExceptionCaughtMessage.ShowMiniButton ();
440
return base.KeyPress (key, keyChar, modifier);