VDBStackApplication.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:#VDBStackApplication
	instanceVariableNames:'selectedThreadGroupHolder selectedThreadHolder
		selectedFrameHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'VDB-UI-Others'
!

!VDBStackApplication 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/
"
! !

!VDBStackApplication class methodsFor:'accessing'!

defaultWindowTitle
    ^ self resources string: 'Callstack'

    "Created: / 11-07-2017 / 16:37:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 03-10-2018 / 15:39:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBStackApplication class methodsFor:'plugIn spec'!

aspectSelectors
    "This resource specification was automatically generated
     by the UIPainter of ST/X."

    "Do not manually edit this. If it is corrupted,
     the UIPainter may not be able to read the specification."

    "Return a description of exported aspects;
     these can be connected to aspects of an embedding application
     (if this app is embedded in a subCanvas)."

    ^ #(
        #debuggerHolder
        #selectedFrameHolder
        #selectedThreadGroupHolder
        #selectedThreadHolder
      ).

! !

!VDBStackApplication methodsFor:'aspects'!

foregroundColorFor: aVDBAbstractPresenter
    ^ (aVDBAbstractPresenter isFramePresenter and:[ aVDBAbstractPresenter frame thread isStopped not])
        ifTrue:[  Color gray ]
        ifFalse:[ nil ]

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

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

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

    "Created: / 21-09-2014 / 23:51:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

selectedFrameHolder:aValueModel
    "set the 'selectionHolder' value holder (automatically generated)"

    |oldValue newValue|

    selectedFrameHolder notNil ifTrue:[
        oldValue := selectedFrameHolder value.
        selectedFrameHolder removeDependent:self.
    ].
    selectedFrameHolder := aValueModel.
    selectedFrameHolder notNil ifTrue:[
        selectedFrameHolder addDependent:self.
    ].
    newValue := selectedFrameHolder value.
    oldValue ~~ newValue ifTrue:[
        self update:#value with:newValue from:selectedFrameHolder.
    ].

    "Created: / 21-09-2014 / 23:50:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

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

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

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

    |oldValue newValue|

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

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

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

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

    |oldValue newValue|

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

!VDBStackApplication methodsFor:'change & update'!

enqueueUpdateAfterThreadStopped:aGDBThread 
    self enqueueDelayedUpdate:#delayedUpdateAfterThreadStopped:
        with:aGDBThread

    "Created: / 22-09-2014 / 23:15:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 17-01-2018 / 06:52:50 / jv"
!

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

    "stub code automatically generated - please change as required"

    sender == selectedFrameHolder ifTrue:[
         self updateInternalSelection.
         ^ self.
    ].
    super update:aspect with:param from:sender

    "Modified: / 27-02-2015 / 15:44:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateInternalSelection
    | frame presenter |

    frame := self selectedFrameHolder value.
    presenter := self internalListHolder value detect:[:e | e subject == frame ] ifNone:[ nil ].
    self internalSelectionHolder
        value: presenter
        withoutNotifying: self.

    "Created: / 20-09-2014 / 23:05:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 30-07-2018 / 07:40:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateSelection
    | internalSelection frame thread group |

    internalSelection := self internalSelectionHolder value.
    internalSelection notNil ifTrue:[ 
        internalSelection isFramePresenter ifTrue:[
            frame := internalSelection frame.
            thread := frame thread.
            group := thread group.
        ] ifFalse:[ 
            internalSelection isThreadPresenter ifTrue:[ 
                thread := internalSelection thread.
                group := thread group.
            ] ifFalse:[  
                group := internalSelection threadGroup.
            ]
        ].
    ].

    self selectedThreadGroupHolder value: group withoutNotifying: self.
    self selectedThreadHolder value: thread withoutNotifying: self.
    self selectedFrameHolder value: frame withoutNotifying: self.

    "Created: / 20-09-2014 / 23:10:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 22-09-2014 / 00:17:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

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

delayedUpdateAfterThreadStopped:thread 
    "/ It may happen that by te time we get here the thread is running
    "/ again, so care for this.

    contentsValid ifFalse:[ 
        self enqueueUpdateAfterThreadStopped: thread.               
        ^ self
    ].

    thread isStopped ifTrue:[
        |threadP framePs frameP|

        threadP := self internalListHolder value root 
                recursiveDetect:[:e | e isThreadPresenter and:[ e thread == thread ] ].
        framePs := threadP children.
        framePs notEmpty ifTrue:[
            frameP := threadP children first.
            frameP parent expand.
            self internalSelectionHolder value:frameP
        ].
    ].

    "Created: / 22-09-2014 / 23:21:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-01-2018 / 20:22:04 / jv"
    "Modified: / 14-02-2019 / 16:53:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateInternalList
    | root  list |

    debugger isNil ifTrue:[
        self internalListHolder root children:#().
        ^ self.
    ].
    root := self internalListHolder root.
    list := debugger inferiors 
            select:[:inferior | true "inferior isRunning or:[ inferior isStopped ]" ]
            thenCollect:[:inferior | 
                (VDBThreadGroupPresenter new)
                    setThreadGroup:inferior;
                    parent:root
            ].
    root children:list.
    root expand.
    root children size == 1 ifTrue:[
        root children anElement expand.
        root children anElement children size == 1 ifTrue:[
            root children anElement children anElement expand.
        ]
    ].
    self delayedInvalidateInternalList

    "Created: / 20-09-2014 / 23:05:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-04-2018 / 19:52:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateSelection
    | internalSelection frame thread group |

    internalSelection := self internalSelectionHolder value.
    internalSelection notNil ifTrue:[ 
        internalSelection isFramePresenter ifTrue:[
            frame := internalSelection frame.
            thread := frame thread.
            group := thread group.
        ] ifFalse:[ 
            internalSelection isThreadPresenter ifTrue:[ 
                thread := internalSelection thread.
                group := thread group.
            ] ifFalse:[  
                group := internalSelection threadGroup.
            ]
        ].
    ].

    self selectedThreadGroupHolder value: group withoutNotifying: self.
    self selectedThreadHolder value: thread withoutNotifying: self.
    self selectedFrameHolder value: frame withoutNotifying: self.

    "Created: / 27-02-2015 / 15:33:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBStackApplication methodsFor:'event handling'!

onRunningEvent: event
    self selectedFrameHolder value notNil ifTrue:[ 
        self internalSelectionHolder value: nil withoutNotifying: self.
    ].
    self enqueueDelayedInvalidateInternalList

    "Created: / 30-09-2014 / 00:02:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 17-01-2018 / 06:59:11 / jv"
    "Modified: / 01-10-2018 / 12:59:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onStoppedEvent: event
    | stoppedThread |

    self enqueueDelayedUpdateContents.
    stoppedThread := event stoppedThread.
    stoppedThread notNil ifTrue:[
        self enqueueUpdateAfterThreadStopped:event stoppedThread.
    ].

    "Created: / 17-09-2014 / 23:04:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 15-01-2018 / 11:51:51 / jv"
    "Modified: / 14-02-2019 / 16:31:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onThreadGroupExitedEvent: event
    self enqueueDelayedUpdateContents.

    "Created: / 18-09-2014 / 23:30:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-02-2019 / 16:31:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onThreadGroupStartedEvent: event
    self enqueueDelayedUpdateContents.

    "Created: / 02-03-2015 / 06:42:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-02-2019 / 16:31:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBStackApplication methodsFor:'initialization & release'!

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

    debugger announcer
        when: GDBRunningEvent               send: #onRunningEvent: to: self;
        when: GDBStoppedEvent               send: #onStoppedEvent: to: self;
        when: GDBThreadGroupStartedEvent    send: #onThreadGroupStartedEvent: to: self;
        when: GDBThreadGroupExitedEvent     send: #onThreadGroupExitedEvent: to: self

    "Created: / 07-06-2014 / 14:33:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 02-03-2015 / 06:42:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 17-01-2018 / 06:56:46 / jv"
! !

!VDBStackApplication methodsFor:'queries'!

canSelect: anItem
    ^ anItem isFramePresenter not or:[ anItem frame thread isStopped ]

    "Created: / 09-04-2018 / 20:52:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBStackApplication class methodsFor:'documentation'!

version_HG

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