VDBSourceApplication.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 25 Jan 2019 13:33:51 +0000
changeset 143 df7f89efd39d
parent 133 16a1f7a5eed0
child 154 26937faa5a97
permissions -rw-r--r--
A complete rewrite of simple console ..that is not using `TerminalView`. The original (previous) implementation had various problems that were hard to fix, namely loosing some stream output in some cases. New (current) implementation uses custom console view (1VDBSimpleDebuggerConsoleView`) based on `TextCollector` rather than `TerminalView`. The resulting code is much much simpler, it does not use internal pipes nor REPL / pipe reader processes. Whole REPL runs completely in UI process.

"
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 }"

VDBAbstractApplication subclass:#VDBSourceApplication
	instanceVariableNames:'frameHolder sourceFileHolder sourceStringHolder sourceView'
	classVariableNames:''
	poolDictionaries:''
	category:'VDB-UI-Source'
!

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

!VDBSourceApplication class methodsFor:'interface specs'!

windowSpec
    "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."

    "
     UIPainter new openOnClass:VDBSourceApplication andSelector:#windowSpec
     VDBSourceApplication new openInterface:#windowSpec
     VDBSourceApplication open
    "

    <resource: #canvas>

    ^ 
    #(FullSpec
       name: windowSpec
       window: 
      (WindowSpec
         label: 'Source View'
         name: 'Source View'
         min: (Point 10 10)
         bounds: (Rectangle 0 0 300 300)
       )
       component: 
      (SpecCollection
         collection: (
          (NonScrollableArbitraryComponentSpec
             name: 'SourceView'
             layout: (LayoutFrame 0 0 0 0 0 1 0 1)
             model: sourceStringHolder
             component: sourceView
           )
          )
        
       )
     )
! !

!VDBSourceApplication 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
        #frameHolder
      ).

! !

!VDBSourceApplication methodsFor:'aspects'!

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.
    ].
!

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

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

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

    |oldValue newValue|

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

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

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

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

    |oldValue newValue|

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

sourceView
    sourceView isNil ifTrue:[ 
        sourceView := Tools::CodeView2 new.
        sourceView font: self textFont.
        sourceView compilerClass: (VDBEvaluator new setDebugger: debugger).    
        sourceView readOnly: true.
        sourceView services: #()        
    ].
    ^ sourceView

    "Created: / 21-09-2014 / 01:42:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 20-08-2018 / 11:03:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSourceApplication methodsFor:'change & update'!

update:aspect with:param from:sender 
    "Invoked when an object that I depend upon sends a change notification."
    
    sender == frameHolder ifTrue:[
        self updateSourceFile.
        ^ self.
    ].
    sender == sourceFileHolder ifTrue:[
        self updateSourceString.
        ^ self.
    ].
    super update:aspect with:param from:sender

    "Modified: / 02-10-2018 / 10:50:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateCurrentLine
    | frame file |

    frame := frameHolder value.
    file := sourceFileHolder value.
    (frame notNil and:[file notNil]) ifTrue:[
        | line |
        line := frame line.
        line notNil ifTrue:[
            sourceView selectLine:line.
            sourceView makeSelectionVisible.
            ^ self.
        ]
    ].
    sourceView unselect

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

updateSourceFile
    | frame |

    frame := frameHolder value.
    frame notNil ifTrue:[
        | file |

        file := frame file.
        file notNil ifTrue:[ file := file asFilename ].
        file notNil ifTrue:[ 
            self sourceFileHolder value: file.
        ] ifFalse:[
            "/ If file is nil, this means that it is either unknown (no 
            "/ debug info) or it cannot be resolved. If the latter, a 
            "/ help text is shown, see #updateSourceString.
            "/ 
            "/ Therefore, here we force an update to make sure that
            "/ help text is regenerated.
            self sourceFileHolder 
                setValue: file;
                changed: #value
        ]
    ].

    "Created: / 01-02-2018 / 15:16:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-01-2019 / 23:55:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateSourceString
    | source file |

    source := nil.
    file := sourceFileHolder value.
    (file notNil and:[file exists]) ifTrue:[
        source := file contents asString.
    ] ifFalse:[ 
        "/ We have no source. As a courtesy to the user, display some info
        "/ on what's the problem and
        | frame |

        frame := self frameHolder value.
        source := Text streamContents:[ :info |
            | frameFile frameFullname |
            info emphasis: #color -> (UserPreferences current codeViewTheme ? UserPreferences current) commentColor.
            info nextPutAll: '//' ; cr.
            info nextPutAll: '// '; nextPutAll: (resources string: 'No source available :-('); cr.
            info nextPutAll: '//' ; cr.
            frameFile := frame propertyAt: #file.
            frameFullname := frame propertyAt: #fullname.
            (frameFile isNil and:[ frameFullname notNil ]) ifTrue:[ 
                info nextPutAll: '// '; nextPutLine: (resources string: 'Source file reference missing (no debug info?)').
            ] ifFalse:[ 
                info nextPutAll: '// '; nextPutLine: (resources string: 'Source file cannot be resolved:').
                info nextPutAll: '// '; cr.
                frameFile notNil ifTrue:[
                    info nextPutAll: '//   '; nextPutLine: frameFile.
                ].
                frameFullname notNil ifTrue:[
                    info nextPutAll: '//   '; nextPutLine: frameFullname.
                ].
                info nextPutAll: '// '; cr.
                info nextPutAll: '// '; nextPutLine: (resources string: 'Configured source directories:').
                debugger directories do:[:each | 
                    info nextPutAll: '//   '; nextPutLine: each.
                ].
                info nextPutAll: '// '; cr.
                info nextPutAll: '// '; nextPutLine: (resources string: 'See also:').
                info nextPutAll: '// [1]: https://sourceware.org/gdb/onlinedocs/gdb/Source-Path.html'.
            ].

        ]

    ].
    self sourceStringHolder value:source.
    self updateCurrentLine.
    ^ self.

    "Modified: / 07-10-2018 / 20:47:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

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

delayedUpdateCurrentLine
    self updateCurrentLine

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

!VDBSourceApplication methodsFor:'event handling'!

onStoppedEvent: aGDBStoppedEvent
    self enqueueDelayedUpdate: #delayedUpdateCurrentLine

    "Created: / 01-02-2018 / 15:23:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 02-10-2018 / 11:04:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSourceApplication methodsFor:'initialization & release'!

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

    debugger announcer
        when: GDBStoppedEvent               send: #onStoppedEvent: to: self.

    sourceView notNil ifTrue:[ 
        sourceView compilerClass setDebugger: debugger.
    ].

    "Created: / 01-02-2018 / 15:18:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-03-2018 / 22:18:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSourceApplication class methodsFor:'documentation'!

version_HG

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