VDBInstructionListApplication.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Wed, 23 Jan 2019 22:05:43 +0000
changeset 151 bc7626f46210
parent 115 0dd989ce3ae7
child 154 26937faa5a97
permissions -rw-r--r--
Performance: do not update contents of windows when not needed ...such as when the tab with it is not visible. This ought to make debugger feel more "snappy" for complex programs running on slow machines and / or during remote debugging sessions. Common code for this has been factored out to new abstract class `VDBAbstractContentsApplication`. `VDBSbstractListApplication` and subclasses have been adapted to use this feature.

"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
"{ Package: 'jv:vdb' }"

"{ NameSpace: Smalltalk }"

VDBAbstractTreeApplication subclass:#VDBInstructionListApplication
	instanceVariableNames:'instructionListHolder instructionBasicBlocks
		selectedInstructionHolder selectedInstructionBranchTargetAddress
		selectedInstructionBasicBlock frameHolder
		canExecStepOverInstructionHolder canExecStepIntoInstructionHolder
		canExecBackOverInstructionHolder canExecBackIntoInstructionHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'VDB-UI-Others'
!

!VDBInstructionListApplication class methodsFor:'documentation'!

copyright
"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
! !

!VDBInstructionListApplication class methodsFor:'accessing'!

defaultWindowTitle
    ^ self resources string:'Assembly'

    "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
    ^ self new  
        instructionList: aCollection;
        title: aString;
        yourself

    "Created: / 26-06-2018 / 11:03:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'accessing'!

frame
    ^ self frameHolder value

    "Created: / 06-08-2018 / 13:24:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

frame: aGDBFrame
    self frameHolder value: aGDBFrame

    "Created: / 06-08-2018 / 13:22:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

instructionList
    ^ self instructionListHolder value

    "Created: / 07-08-2018 / 13:27:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

instructionList: aCollection
    self instructionListHolder value: aCollection

    "Created: / 22-06-2018 / 12:48:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'aspects'!

backgroundColorFor: aVDBPresenter
    (frameHolder value notNil and:[aVDBPresenter isInstructionPresenter]) ifTrue:[ 
        frameHolder value address == aVDBPresenter address ifTrue:[ 
            ^ Color green.
        ].
    ].

    selectedInstructionBranchTargetAddress notNil ifTrue:[ 
        aVDBPresenter isInstructionPresenter ifTrue:[ 
            aVDBPresenter instruction address = selectedInstructionBranchTargetAddress ifTrue:[ 
                ^ Color blue lighter lighter
            ].
        ].
        selectedInstructionBasicBlock notNil ifTrue:[ 
            | successor2 |

            successor2 := selectedInstructionBasicBlock successor2.
            (successor2 notNil and:[ successor2 includesAddress: aVDBPresenter address] ) ifTrue:[
                ^ Color blue lighter lighter lighter
            ].
        ].
    ].
    selectedInstructionBasicBlock notNil ifTrue:[ 
        (selectedInstructionBasicBlock includesAddress: aVDBPresenter address) ifTrue:[ 
            ^ Color yellow lighter lighter
        ].
    ].
    ^ nil

    "Created: / 26-06-2018 / 11:26:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-08-2018 / 11:50:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

foregroundColorFor: aVDBAbstractPresenter
    ^ aVDBAbstractPresenter isInstructionsAndSourcePresenter 
        ifTrue:[ Color gray ]
        ifFalse:[ nil ]

    "Created: / 26-06-2018 / 13:07:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

frameHolder
    "return/create the 'frameHolder' value holder (automatically generated)"

    frameHolder isNil ifTrue:[
        frameHolder := ValueHolder new.
        frameHolder addDependent:self.
    ].
    ^ frameHolder
!

frameHolder:something
    "set the 'frameHolder' value holder (automatically generated)"

    |oldValue newValue|

    frameHolder notNil ifTrue:[
        oldValue := frameHolder value.
        frameHolder removeDependent:self.
    ].
    frameHolder := something.
    frameHolder notNil ifTrue:[
        frameHolder addDependent:self.
    ].
    newValue := frameHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:frameHolder.
    ].
!

instructionListHolder
    "return/create the 'instructionListHolder' value holder (automatically generated)"

    instructionListHolder isNil ifTrue:[
        instructionListHolder := ValueHolder new.
        instructionListHolder addDependent:self.
    ].
    ^ instructionListHolder
!

instructionListHolder:valueModel
    "set the 'instructionListHolder' value holder (automatically generated)"

    |oldValue newValue|

    instructionListHolder notNil ifTrue:[
        oldValue := instructionListHolder value.
        instructionListHolder removeDependent:self.
    ].
    instructionListHolder := valueModel.
    instructionListHolder notNil ifTrue:[
        instructionListHolder addDependent:self.
    ].
    newValue := instructionListHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:instructionListHolder.
    ].
!

selectedInstructionHolder
    "return/create the 'selectedInstructionHolder' value holder (automatically generated)"

    selectedInstructionHolder isNil ifTrue:[
        selectedInstructionHolder := ValueHolder new.
        selectedInstructionHolder addDependent:self.
    ].
    ^ selectedInstructionHolder
!

selectedInstructionHolder:valueModel
    "set the 'selectedInstructionHolder' value holder (automatically generated)"

    |oldValue newValue|

    selectedInstructionHolder notNil ifTrue:[
        oldValue := selectedInstructionHolder value.
        selectedInstructionHolder removeDependent:self.
    ].
    selectedInstructionHolder := valueModel.
    selectedInstructionHolder notNil ifTrue:[
        selectedInstructionHolder addDependent:self.
    ].
    newValue := selectedInstructionHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:selectedInstructionHolder.
    ].
! !

!VDBInstructionListApplication methodsFor:'change & update'!

enqueueDelayedUpdateBasicBlocks
    self enqueueDelayedUpdate: #delayedUpdateBasicBlocks

    "Created: / 26-06-2018 / 12:20:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

enqueueDelayedUpdateButtonEnablements
    self enqueueDelayedUpdate: #delayedUpdateButtonEnablements

    "Created: / 03-10-2018 / 12:12:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

update:aspect with:param from:sender
    "Invoked when an object that I depend upon sends a change notification."

    sender == instructionListHolder ifTrue:[
        self enqueueDelayedUpdateInternalList.
        ^ self.
    ].
    sender == frameHolder ifTrue:[ 
        self enqueueDelayedUpdateContents.
        ^ self.
    ].
    sender == selectedInstructionHolder ifTrue:[ 
        self updateAfterSelectedInstructionChanged.
    ].
    super update:aspect with:param from:sender

    "Modified: / 23-01-2019 / 16:37:11 / jv"
    "Modified: / 14-02-2019 / 16:52:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateAfterSelectedInstructionChanged
    | selected |

    selected := self selectedInstructionHolder value.
    selected notNil ifTrue:[
        selected isBranch ifTrue:[ 
            selectedInstructionBranchTargetAddress := selected branchTarget.
        ] ifFalse:[ 
            selectedInstructionBranchTargetAddress := nil.
        ].
        instructionBasicBlocks size > 1 ifTrue:[
            selectedInstructionBasicBlock := instructionBasicBlocks detect:[:e | e includesAddress: selected address ] ifNone: [ nil ]
        ] ifFalse:[ 
            selectedInstructionBasicBlock := nil.
        ].
    ] ifFalse:[ 
        selectedInstructionBranchTargetAddress := nil.
        selectedInstructionBasicBlock := nil.

    ].

    self enqueueDelayedInvalidateInternalList.

    "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 notNil and:[ 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: / 28-09-2018 / 07:04:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'change & update-delayed'!

delayedInvalidateInternalList
    | frame |

    "/ First, force update of )cached) frames to get 
    "/ updated PC.
    frame := self frame.
    (frame notNil and:[frame thread isStopped]) ifTrue:[
        frame thread stack        
    ].    
    super delayedInvalidateInternalList

    "Created: / 03-10-2018 / 12:10:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateBasicBlocks
    | instructions |

    instructions := OrderedCollection new.
    self instructionsDo: [ :e | instructions add: e ].
    instructionBasicBlocks := VDBInstructionBasicBlock analyze: instructions.
    self enqueueDelayedInvalidateInternalList.

    "Created: / 26-06-2018 / 12:20:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-08-2018 / 11:33:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateButtonEnablements
    | frame thread threadIsStopped canReverse |

    frame := self frameHolder value.
    frame notNil ifTrue:[ 
        thread := frame thread.
    ].
    threadIsStopped := thread notNil and:[ thread isStopped ].
    canReverse := debugger notNil and:[ debugger hasFeature: 'reverse' ].

    self canExecStepIntoInstructionHolder value: threadIsStopped.
    self canExecStepOverInstructionHolder value: threadIsStopped.

    self canExecBackIntoInstructionHolder value: threadIsStopped & canReverse.
    self canExecBackOverInstructionHolder value: threadIsStopped & canReverse.

    "Created: / 03-10-2018 / 12:12:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateContents
    | frame |

    frame := self frame.
    (frame notNil and:[ frame hasSymbol ]) ifTrue:[
        self instructionList:frame disassemble.
    ] ifFalse:[
        self instructionList:#().
    ].
    self updateButtonEnablements.

    "Created: / 01-10-2018 / 12:55:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-02-2019 / 16:09:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateInternalList
    | root |

    root := self internalListHolder root.
    root children:
        ((self instructionListHolder value ? #()) collect:[:model | 
            (model isKindOf: GDBInstructionsAndSourceLine) ifTrue:[
                (VDBInstructionsAndSourcePresenter new) setInstructionsAndSource: model;
                    parent:root;
                    yourself
            ] ifFalse:[ 
                (VDBInstructionPresenter new) setInstruction: model;
                    parent:root;
                    yourself
            ].
        ]).
    root expand.
    root children do:[:each | each expand ].
    self frame notNil ifTrue:[ 
        self scrollToAddress: self frame address.
    ].
    internalListView notNil ifTrue:[
        internalListView invalidate.
    ].
    self enqueueDelayedUpdateBasicBlocks.

    "Created: / 27-02-2015 / 15:47:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-08-2018 / 16:13:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateSelection
    | internalSelection |

    internalSelection := self internalSelectionHolder value.
    internalSelection notNil ifTrue:[
        self selectedInstructionHolder value: internalSelection instruction
    ] ifFalse:[ 
        self selectedInstructionHolder value: nil
    ].

    "Modified: / 22-06-2018 / 15:08:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!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 enqueueDelayedUpdateButtonEnablements

    "Created: / 21-09-2014 / 22:44:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 03-10-2018 / 12:12:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onStoppedEvent: aGDBStoppedEvent
    self frame notNil ifTrue:[
        self enqueueDelayedInvalidateInternalList.
        self enqueueDelayedUpdateButtonEnablements.
    ].

    "Created: / 06-08-2018 / 14:45:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 03-10-2018 / 12:13:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'hooks'!

postBuildInternalListView: aView
    super postBuildInternalListView: aView.
    internalListView addDependent: self.

    "Created: / 23-01-2019 / 16:10:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'initialization & release'!

release
    super release.
    internalListView notNil ifTrue:[ 
        internalListView removeDependent: self.
    ].

    "Created: / 23-01-2019 / 16:11:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

subscribe   
    "Register for debugger events. To be overrided by subclasses"

    debugger announcer 
        when: GDBStoppedEvent       send: #onStoppedEvent:  to: self;
        when: GDBRunningEvent       send: #onRunningEvent:  to: self;
        "/when: GDBExitEvent          send: #onExitEvent:     to: self;
        when: GDBCommandResultEvent send: #onCommandResultEvent: to: self.

    contentsValid := false.

    "Created: / 06-08-2018 / 14:44:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 23-01-2019 / 14:29:29 / 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'!

instructionPresentersDo: aBlock
    self internalListHolder root children do:[:each |
        each isInstructionPresenter ifTrue:[ 
            aBlock value: each
        ] ifFalse:[ 
            each children do: aBlock
        ].
    ]

    "Created: / 26-06-2018 / 12:30:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

instructionsDo: aBlock
    self instructionListHolder value ? #() do:[:each |
        each instructionsDo: aBlock
    ]

    "Created: / 16-08-2018 / 11:32:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'queries'!

canSelect: anItem
    ^ anItem isInstructionPresenter

    "Created: / 22-06-2018 / 15:07:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication methodsFor:'scrolling'!

scrollToAddress: address
    internalListView isNil ifTrue:[ ^ self ].
    (self frame notNil and:[ self instructionList notEmptyOrNil ]) ifTrue:[ 
        self instructionPresentersDo:[ :each |
            each address = address ifTrue:[ 
                self scrollToListItem: each.
            ].
        ]
    ].

    "Created: / 07-08-2018 / 13:36:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBInstructionListApplication class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !