UX: improve navigation and single-stepping in disassembly view
authorJan Vrany <jan.vrany@fit.cvut.cz>
Sat, 01 Sep 2018 14:44:55 +0100
changeset 101 ef31619bc09c
parent 100 7c4093081c29
child 102 3049a43423cf
UX: improve navigation and single-stepping in disassembly view ..by adding actions to context menu. Allow for context menu to be pinned.
VDBAbstractListApplication.st
VDBInstructionListApplication.st
--- a/VDBAbstractListApplication.st	Sat Sep 01 14:40:24 2018 +0100
+++ b/VDBAbstractListApplication.st	Sat Sep 01 14:44:55 2018 +0100
@@ -367,10 +367,11 @@
 
 delayedInvalidateInternalList
     internalListView notNil ifTrue:[ 
-        internalListView scrolledView invalidate.
+        internalListView scrolledView invalidateRepairNow: true
     ].
 
     "Created: / 06-02-2018 / 12:43:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-09-2018 / 22:24:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 delayedUpdateInternalList
--- a/VDBInstructionListApplication.st	Sat Sep 01 14:40:24 2018 +0100
+++ b/VDBInstructionListApplication.st	Sat Sep 01 14:44:55 2018 +0100
@@ -13,7 +13,9 @@
 VDBAbstractTreeApplication subclass:#VDBInstructionListApplication
 	instanceVariableNames:'instructionListHolder instructionBasicBlocks
 		selectedInstructionHolder selectedInstructionBranchTargetAddress
-		selectedInstructionBasicBlock frameHolder'
+		selectedInstructionBasicBlock frameHolder
+		canExecStepOverInstructionHolder canExecStepIntoInstructionHolder
+		canExecBackOverInstructionHolder canExecBackIntoInstructionHolder'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'VDB-UI-Others'
@@ -40,6 +42,154 @@
     "Created: / 22-06-2018 / 12:25:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!VDBInstructionListApplication class methodsFor:'menu specs'!
+
+contextMenu
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+
+    "
+     MenuEditor new openOnClass:VDBInstructionListApplication andSelector:#contextMenu
+     (Menu new fromLiteralArrayEncoding:(VDBInstructionListApplication contextMenu)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(Menu
+        (
+         (MenuItem
+            label: 'Context Menu Slice'
+            isVisible: true
+            submenuChannel: contextMenuApplSlice
+            isMenuSlice: true
+          )
+         (MenuItem
+            label: 'Item Menu Slice'
+            isVisible: true
+            submenuChannel: contextMenuItemSlice
+            isMenuSlice: true
+          )
+         (MenuItem
+            label: 'Copy Menu Slice'
+            isVisible: true
+            submenuChannel: contextMenuCopySlice
+            isMenuSlice: true
+          )
+         (MenuItem
+            label: '-'
+            isVisible: true
+          )
+         (MenuItem
+            label: 'Inspect Menu Slice'
+            isVisible: true
+            submenuChannel: contextMenuInspectSlice
+            isMenuSlice: true
+          )
+         (MenuItem
+            label: '-'
+          )
+         (MenuItem
+            label: 'Pin Menu'
+            itemValue: doPinMenuAs:item:
+            isVisible: true
+            labelImage: (ResourceRetriever VDBIconLibrary pin 'Pin Menu')
+            argument: 'Disassembly Actions'
+          )
+         )
+        nil
+        nil
+      )
+
+    "Modified: / 01-09-2018 / 14:55:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+contextMenuApplSlice
+    "This resource specification was automatically generated
+     by the MenuEditor of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the MenuEditor may not be able to read the specification."
+
+
+    "
+     MenuEditor new openOnClass:VDBInstructionListApplication andSelector:#contextMenuApplSlice
+     (Menu new fromLiteralArrayEncoding:(VDBInstructionListApplication contextMenuApplSlice)) startUp
+    "
+
+    <resource: #menu>
+
+    ^ 
+     #(Menu
+        (
+         (MenuItem
+            enabled: canShowCurrentHolder
+            label: 'Show Current Instruction'
+            itemValue: doShowCurrent
+            isVisible: true
+          )
+         (MenuItem
+            enabled: canShowBranchTargetHolder
+            label: 'Show Branch Traget'
+            itemValue: doShowBranchTarget
+            isVisible: true
+          )
+         (MenuItem
+            enabled: canShowSelectionHolder
+            label: 'Show Selection'
+            itemValue: doShowSelection
+            isVisible: true
+          )
+         (MenuItem
+            label: '-'
+            isVisible: true
+          )
+         (MenuItem
+            enabled: canExecStepOverInstructionHolder         
+            label: 'Step Over'
+            itemValue: doExecStepOverInstruction
+            isVisible: true
+            labelImage: (ResourceRetriever VDBIconLibrary actionStepOver6x16 'Step Over One Instruction')
+          )
+         (MenuItem
+            enabled: canExecStepIntoInstructionHolder
+            label: 'Step Into'
+            itemValue: doExecStepIntoInstruction
+            isVisible: true
+            labelImage: (ResourceRetriever VDBIconLibrary actionStepInto6x16 'Step Into One Instruction')
+          )
+         (MenuItem
+            label: '-'
+            isVisible: true
+          )
+         (MenuItem
+             enabled: canExecBackOverInstructionHolder
+            label: 'Back Over'
+            itemValue: doExecBackOverInstruction
+            isVisible: true
+          )
+         (MenuItem
+            enabled: canExecBackIntoInstructionHolder
+            label: 'Back Into'
+            itemValue: doExecBackIntoInstruction
+            isVisible: true
+          )
+         (MenuItem
+            label: '-'
+            isVisible: true
+          )
+         )
+        nil
+        nil
+      )
+
+    "Modified: / 01-09-2018 / 22:02:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !VDBInstructionListApplication class methodsFor:'utilities'!
 
 instructions: aCollection title: aString
@@ -235,9 +385,11 @@
 !
 
 updateAfterFrameChanged
-    self debugger: self frame debugger
+    self debugger: self frame debugger.
+    self updateButtonEnablements.
 
     "Created: / 06-08-2018 / 13:24:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-09-2018 / 22:13:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 updateAfterSelectedInstructionChanged
@@ -265,6 +417,26 @@
 
     "Created: / 26-06-2018 / 11:33:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 03-07-2018 / 14:56:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+updateButtonEnablements
+    | frame thread threadIsStopped canReverse |
+
+    frame := self frameHolder value.
+    frame notNil ifTrue:[ 
+        thread := frame thread.
+    ].
+    threadIsStopped := thread notNil and:[ thread isStopped ].
+    canReverse := debugger hasFeature: 'reverse'.
+
+    self canExecStepIntoInstructionHolder value: threadIsStopped.
+    self canExecStepOverInstructionHolder value: threadIsStopped.
+
+    self canExecBackIntoInstructionHolder value: threadIsStopped & canReverse.
+    self canExecBackOverInstructionHolder value: threadIsStopped & canReverse.
+
+    "Created: / 01-09-2018 / 14:49:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-09-2018 / 22:15:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !VDBInstructionListApplication methodsFor:'change & update-delayed'!
@@ -326,12 +498,28 @@
 
 !VDBInstructionListApplication methodsFor:'event handling'!
 
+onCommandResultEvent: aGDBStoppedEvent
+    self updateButtonEnablements
+
+    "Created: / 01-06-2017 / 23:43:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+onRunningEvent: aGDBStoppedEvent
+    self updateButtonEnablements
+
+    "Created: / 21-09-2014 / 22:44:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-06-2017 / 23:18:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 onStoppedEvent: aGDBStoppedEvent
-    self frame notNil ifTrue:[ 
+    self frame notNil ifTrue:[
+        self frame thread stack. "/ to force update of (cached) frames.
         self enqueueDelayedInvalidateInternalList
     ].
+    self updateButtonEnablements
 
     "Created: / 06-08-2018 / 14:45:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-09-2018 / 22:39:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !VDBInstructionListApplication methodsFor:'initialization & release'!
@@ -340,9 +528,159 @@
     "Register for debugger events. To be overrided by subclasses"
 
     debugger announcer 
-        when: GDBStoppedEvent send: #onStoppedEvent: to: self.
+        when: GDBStoppedEvent       send: #onStoppedEvent:  to: self;
+        when: GDBRunningEvent       send: #onRunningEvent:  to: self;
+        "/when: GDBExitEvent          send: #onExitEvent:     to: self;
+        when: GDBCommandResultEvent send: #onCommandResultEvent: to: self.
 
     "Created: / 06-08-2018 / 14:44:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-09-2018 / 14:48:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBInstructionListApplication methodsFor:'menu actions'!
+
+doShowBranchTarget
+    | selection |
+
+   selection := self selectedInstructionHolder value.
+   (selection notNil and:[selection isBranch]) ifTrue:[ 
+        | branchTarget |
+
+        branchTarget := selection branchTarget.
+        "/ For indirect jumps, `branchTarget` is `nil`.
+        branchTarget notNil ifTrue:[ 
+            self doShowInstructionAtAddress: branchTarget  
+        ].
+   ].
+
+    "Modified: / 01-09-2018 / 14:32:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doShowCurrent
+    | frame |
+
+    frame := self frameHolder value.
+    frame notNil ifTrue:[ 
+        self doShowInstructionAtAddress: frame address  
+    ].
+
+    "Modified: / 01-09-2018 / 14:27:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doShowInstructionAtAddress: address
+    self scrollToAddress: address
+
+    "Created: / 01-09-2018 / 14:26:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doShowSelection
+   | selection |
+
+   selection := self selectedInstructionHolder value.
+   selection notNil ifTrue:[ 
+       self doShowInstructionAtAddress: selection address
+   ].
+
+    "Modified: / 01-09-2018 / 14:32:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBInstructionListApplication methodsFor:'menu actions-exec'!
+
+doExec: command
+    debugger send: command andWait: false.
+    self enqueueDelayedInvalidateInternalList
+
+    "Created: / 21-09-2014 / 21:50:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-03-2018 / 17:57:15 / jv"
+    "Modified: / 01-09-2018 / 22:33:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doExecBackIntoInstruction
+    self doExec:(GDBMI_exec_step_instruction arguments:#('--reverse'))
+
+    "Modified: / 01-09-2018 / 22:16:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doExecBackOverInstruction
+    self doExec:(GDBMI_exec_next_instruction arguments:#('--reverse'))
+
+    "Modified: / 01-09-2018 / 22:16:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doExecSteIntoInstruction
+    self doExec:GDBMI_exec_step_instruction new
+
+    "Created: / 01-09-2018 / 22:00:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+doExecStepOverInstruction
+    self doExec:GDBMI_exec_next_instruction new
+
+    "Modified: / 01-09-2018 / 21:59:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBInstructionListApplication methodsFor:'menu aspects'!
+
+canShowBranchTargetHolder
+    ^ BlockValue 
+        with:[ :selection | selection value notNil and:[selection value isBranch and:[selection value branchTarget notNil]]] 
+        argument: self selectedInstructionHolder
+
+    "Modified: / 01-09-2018 / 15:32:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+canShowCurrentHolder
+    ^ BlockValue 
+        with:[ :frame | frame value notNil and:[frame value address notNil ]]
+        argument: self frameHolder
+
+    "Modified: / 01-09-2018 / 15:33:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+canShowSelectionHolder
+    ^ BlockValue 
+        with:[ :selection | selection value notNil ] 
+        argument: self selectedInstructionHolder
+
+    "Modified: / 01-09-2018 / 15:33:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBInstructionListApplication methodsFor:'menu aspects-exec'!
+
+canExecBackIntoInstructionHolder
+    canExecBackIntoInstructionHolder isNil ifTrue:[
+        canExecBackIntoInstructionHolder := ValueHolder with: false.
+    ].
+    ^ canExecBackIntoInstructionHolder
+
+    "Modified: / 01-09-2018 / 22:07:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+canExecBackOverInstructionHolder
+    canExecBackOverInstructionHolder isNil ifTrue:[
+        canExecBackOverInstructionHolder := ValueHolder with: false.
+    ].
+    ^ canExecBackOverInstructionHolder
+
+    "Modified: / 01-09-2018 / 22:07:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+canExecStepIntoInstructionHolder
+    canExecStepOverInstructionHolder isNil ifTrue:[
+        canExecStepOverInstructionHolder := ValueHolder with: false.
+    ].
+    ^ canExecStepOverInstructionHolder
+
+    "Modified: / 01-09-2018 / 22:08:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+canExecStepOverInstructionHolder
+    canExecStepOverInstructionHolder isNil ifTrue:[
+        canExecStepOverInstructionHolder := ValueHolder with: false.
+    ].
+    ^ canExecStepOverInstructionHolder
+
+    "Modified: / 01-09-2018 / 22:08:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !VDBInstructionListApplication methodsFor:'private'!