## page was renamed from ErrorTrappingInForms = Error Trapping in Dyalog Forms = ||{{attachment:myapp1.jpg}} {{attachment:myapp2.jpg}} || An application's GUI looks like a Form with stuff on it. So it is appealing to describe it that way. That is to say, to define the GUI as a class derived from a Dyalog native Form. Here is a tiny example; the SolitaireGame is a more elaborate one. {{{ :Class MyApp: 'Form' ∇ make :Access Public :Implements Constructor Caption←'My Application' BTN←⎕NEW'Button'(⊂'Caption' 'Push me') BTN.onSelect←'ButtonHandler' ∇ ∇ ButtonHandler(obj xxx) obj.Caption←'Ouch' ∇ :EndClass }}} Usage is trivial: {{{(⎕NEW MyApp).Wait}}}. The {{{Wait}}} method is enough to keep the {{{MyApp}}} instance in existence until the {{{Kill}}} button is clicked. Then everything disappears: no objects left, no clean-up to do. This is an appealing way to code a GUI because of the high degree of encapsulation. Everything the application's GUI needs is contained in the Form. It doesn't even require a name assigned to it. However, trapping such an application requires a little thought. If your error traps have relied on knowing the names of forms and so on, you will find them difficult to use here. Let's make the reasonable assumption an error might occur elsewhere in the active workspace, not necessarily in a method of {{{MyApp}}}. Let's suppose that in the event of an error or an interrupt we want to (a) log the event and local environment, and (b) cut back and either restart or resume the application. One thing we can't do is cut back the stack so far that {{{MyApp}}}'s methods are no longer on it. For example, let's insert a domain error into {{{ButtonHandler}}}: {{{ ∇ ButtonHandler(obj xxx) obj.Caption←'Ouch' ÷0 ∇ }}} start it, and push the button. {{{ (⎕NEW MyApp).Wait DOMAIN ERROR ButtonHandler[2] ÷0 ∧ )SI [#.[MyApp]] #.MyApp.ButtonHandler[2]* ⎕DQ ⎕THIS #.[MyApp] }}} You might think that you could set {{{⎕TRAP}}} to cut back to the instance and resume, by writing: {{{ ⎕TRAP←⊂0 'C' '⎕←''TRAPPED'' ⋄ ⎕←↑⎕DM ⋄ Wait' }}} either in the class script or in its constructor. But it turns out that {{{⎕TRAP}}} is set in the workspace root, not in the object. When the trap fires, the stack is cut back to immediate execution, and the {{{MyApp}}} instance vanishes. A more robust approach overrides the {{{Wait}}} method {{{MyApp}}} inherited from the {{{Form}}} class. We can localise {{{⎕TRAP}}} in {{{Wait}}}, log the error from the environment in which it occurred, then ensure the stack is cut back only to a point at which we can resume. {{{ ∇ Wait;⎕TRAP;done :Access Public ⎕TRAP←⊂(⍳500)'E' '⎕←↑¨⎕SI ⎕LC ⋄ ⎕SIGNAL 911' :Repeat :Trap 911 done←0∊⍴⎕BASE.Wait :Else done←0 :EndTrap :Until done ∇ }}} Here is a slightly more elaborate version taken from a commercial application. This application's user-interface object needs its error trapping to report what is in its {{{ThisObj}}} slot. {{{ ∇ Wait;⎕TRAP;done :Access Public ⎕TRAP←⊂(911~⍨⍳1006)'E' '#.SESSION.Log.Error ⎕DM ⋄ ⎕SIGNAL 911' :Repeat :Trap 911 done←0∊⍴⎕BASE.Wait :Else #.SESSION.Log.Record'Error in ',⍕ThisObj CursorObj←#.GUI.CURSOR.Default #.GUI.Error'System has trapped and logged an error in ',⍕⊃⊃⎕CLASS ThisObj done←0 :EndTrap :Until done ∇ }}} Author: StephenTaylor ---- See also: ErrorTrappingWithDyalog ---- CategoryGuides