SubCanvas.st
author tm
Fri, 15 Dec 2000 16:46:45 +0100
changeset 1905 20ff18462cc6
parent 1895 a1b2502c91d7
child 1906 0b64cfae3419
permissions -rw-r--r--
care for keepClientView setting (do not reinstall clientView as scrolledView, if it is already a subview of the scrolledView - this leads to destroying of the subcanvas components)

"
 COPYRIGHT (c) 1998 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"


"{ Package: 'stx:libwidg2' }"

ScrollableView subclass:#SubCanvas
	instanceVariableNames:'builder spec client clientHolder specHolder clientView
		clientViewIsScrolled lateBuild useApplicationSubView
		keepClientView useOwnBuilder'
	classVariableNames:''
	poolDictionaries:''
	category:'Views-Basic'
!

!SubCanvas class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1998 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

!

documentation
"
    a view for a subApplication.

    Made to be VW compatible as much as possible (try opening a RefactoringBrowser ...).
    However, the default setup is not very useful, to embedd arbitrary applications
    which are meant to be separate stand-alone applications.
    Play with the settings:
        keepClientView          (default: true)
        useApplicationSubView   (default: false)
        useOwnBuilder           (default: false)

    [author:]
        Claus Atzkern
"
! !

!SubCanvas class methodsFor:'defaults'!

defaultHorizontalScrollable
    ^ false


!

defaultVerticalScrollable
    ^ false


! !

!SubCanvas methodsFor:'accessing'!

builder
    "return the value of the instance variable 'builder' (automatically generated)"

    ^ builder
!

client
    "return the value of the instance variable 'client' (automatically generated)"

    ^ client
!

client:anApplication spec:aWindowSpecOrSpecSymbol builder:aBuilder
    "release existing components and generate new components from
     the given windowSpec, using the given builder."

    |myApp|

    (client notNil and:[client ~~ anApplication]) ifTrue:[
        client releaseAsSubCanvas.
        client := nil.
    ].

    (builder := aBuilder) isNil ifTrue:[
        builder := anApplication perform:#builder ifNotUnderstood:[UIBuilder new]
    ].

    spec := aWindowSpecOrSpecSymbol.

    "/ check for master application
    (anApplication notNil and:[anApplication masterApplication isNil]) ifTrue:[
        myApp := self application.
        myApp ~~ anApplication ifTrue:[
            anApplication masterApplication:myApp
        ]
    ].

    client := anApplication.
    self rebuild.
    ^ builder
!

makeClientViewScrollable:aBoolean
    |vs|

    aBoolean ~~ clientViewIsScrolled ifTrue:[
        clientView isNil ifTrue:[
            useApplicationSubView ifTrue:[
                clientView := ApplicationSubView new.
            ] ifFalse:[
                clientView := View new.
            ]
        ].
        aBoolean ifTrue:[
            self scrolledView:(vs := ViewScroller new).
            vs scrolledView:clientView.
        ] ifFalse:[
            self scrolledView:clientView.
        ].
        clientViewIsScrolled := aBoolean.
    ]

    "Modified: / 30.1.2000 / 21:36:29 / cg"
!

setClient:anApplicationModel
    "set the client - do NOT rebuild"

    client := anApplicationModel 
!

spec
    "return the value of the instance variable 'spec' (automatically generated)"

    ^ spec
!

spec:something
    "set the value of the instance variable 'spec' (automatically generated)"

    spec := something.
    self rebuild.
!

widget
    "ST80 compatibility. 
     I am my own widget"

    ^ self

    "Created: / 10.3.1998 / 16:20:52 / stefan"
! !

!SubCanvas methodsFor:'accessing - canvasView handling'!

keepClientView:aBoolean
    keepClientView := aBoolean
!

useApplicationSubView:aBoolean
    useApplicationSubView := aBoolean
!

useOwnBuilder:aBoolean
    useOwnBuilder := aBoolean
! !

!SubCanvas methodsFor:'accessing-channels'!

clientHolder
    ^ clientHolder
!

clientHolder:aValueHolder

    clientHolder notNil ifTrue:[
        clientHolder removeDependent:self
    ].
    (clientHolder := aValueHolder) notNil ifTrue:[
        clientHolder addDependent:self
    ].
    self updateFromChannels
!

clientView:aView

    clientView notNil ifTrue:[
        clientView destroy
    ].
    clientView := aView
!

specHolder
    ^ specHolder
!

specHolder:aValueHolder
    |oldSpec|

    specHolder notNil ifTrue:[
        oldSpec := specHolder value.
        specHolder removeDependent:self
    ].
    (specHolder := aValueHolder) notNil ifTrue:[
        specHolder addDependent:self
    ].
    oldSpec ~~ specHolder value ifTrue:[
        self updateFromChannels
    ]
! !

!SubCanvas methodsFor:'building'!

XXrebuild
    "rebuild
    "
    |v subSpec savedView builderClass boundsOrLayout|

    superView isNil ifTrue:[
        lateBuild := true.
        ^ self
    ].

    clientView notNil ifTrue:[
        clientView destroySubViews
    ].

    spec notNil ifTrue:[
        (subSpec := spec) isSymbol ifTrue:[
            client isNil ifTrue:[
                'SubCanvas [warning]: no client - cannot build spec' infoPrintCR.
                ^ self
            ].
            (subSpec := client class interfaceSpecFor:spec) isNil ifTrue:[
                "/ Transcript showCR:'SubCanvas: nil spec'.
                ^ self
            ]
        ].

        builder isNil ifTrue:[
            client isNil ifTrue:[
                builderClass := UIBuilder
            ] ifFalse:[
                builderClass := client builderClass
            ].
            builder := builderClass new.
        ].

        "/ old:
"/         builder buildFromSpec:subSpec in:clientView.

        "/ new (let app know (somehow) that this is a build
        "/ for a subcanvas (i.e. it can redefine the buildSubCanvase-method
        "/:
        savedView := builder window.
        builder window:clientView.
        [
            client buildSubCanvas:subSpec withBuilder:builder.
        ] valueNowOrOnUnwindDo:[
            builder window:savedView.
        ].
        clientViewIsScrolled ifTrue:[
            boundsOrLayout := builder spec window layout.
            boundsOrLayout isNil ifTrue:[
                 boundsOrLayout := builder spec window bounds
            ].
            clientView
                extent:(boundsOrLayout rectangleRelativeTo:self bounds preferred:nil) extent.
        ].

        self realized ifTrue:[
            clientView realizeAllSubViews
        ]
    ]

    "Modified: / 20.6.1998 / 14:29:00 / cg"
!

container:aView
    super container:aView.

    "/ my builder can only build the components, when I have a container
    "/ lateBuild is set, if the spec was set some time ago, when I had no container
    "/ Now, we know where to build the GUI ...
    "/ ... and must hurry up to create the widgets.
    lateBuild == true ifTrue:[
        lateBuild := false.
        self rebuild
    ].
!

rebuild
    "rebuild
    "
    |v subSpec savedView savedBuilder builderClass|

    "/ if the superView is not yet created,
    "/ we MUST delay building... (sigh)
    superView isNil ifTrue:[          
        lateBuild := true.
        ^ self
    ].

    clientView notNil ifTrue:[
        clientView destroySubViews.
    ].

    spec notNil ifTrue:[
        (subSpec := spec) isSymbol ifTrue:[
            client isNil ifTrue:[
                'SubCanvas [warning]: no client - cannot build spec' infoPrintCR.
                ^ self
            ].
            (subSpec := client class interfaceSpecFor:spec) isNil ifTrue:[
                "/ Transcript showCR:'SubCanvas: nil spec'.
                ^ self
            ]
        ].
        subSpec isArray ifTrue:[
            subSpec := subSpec decodeAsLiteralArray
        ].

        builder isNil ifTrue:[
            client isNil ifTrue:[
                builderClass := UIBuilder
            ] ifFalse:[
                builderClass := client builderClass
            ].
            builder := builderClass new.
        ].

        "/ old:
        "/  builder buildFromSpec:subSpec in:clientView.

        "/ new (let app know (somehow) that this is a build
        "/ for a subcanvas (i.e. it can redefine the buildSubCanvas-method):

        keepClientView ifFalse:[
            (clientView notNil and:[clientView application ~~ client]) ifTrue:[
                clientView destroy.
                clientView := nil.
            ].
        ].

        clientView isNil ifTrue:[
            useApplicationSubView ifTrue:[
                clientView := ApplicationSubView new.
                clientView application:client.
            ] ifFalse:[
                clientView := View new.
            ]
        ].

        savedView := builder window.
        builder window:clientView.
        useOwnBuilder ifTrue:[
            savedBuilder := client builder.
            client builder:builder.
        ].

        [

            client buildSubCanvas:subSpec withBuilder:builder.
            keepClientView ifFalse:[    
                (scrolledView notNil and:[clientView isSubViewOf:scrolledView]) ifTrue:[
                    self halt
                ] ifFalse:[
                    self scrolledView:clientView.
                ]
            ]
        ] valueNowOrOnUnwindDo:[
            savedView notNil ifTrue:[
                builder window:savedView.
            ].
            useOwnBuilder ifTrue:[
                savedBuilder notNil ifTrue:[
                    client builder:savedBuilder.
                ]
            ]
        ].

        clientViewIsScrolled ifTrue:[
            clientView extent:((subSpec window layout) ? (subSpec window bounds)) extent.
        ].

        self realized ifTrue:[
            clientView realizeAllSubViews
        ].
    ]

    "Modified: / 30.1.2000 / 21:36:40 / cg"
!

releaseAllComponents
    clientView destroySubViews.
    builder := nil.
    spec    := nil.
    client  := nil.

    "Modified: / 31.1.2000 / 16:56:14 / cg"
! !

!SubCanvas methodsFor:'change & update'!

update:something with:aParameter from:changedObject
    "one of my models changed its value
    "
    (changedObject == clientHolder or:[changedObject == specHolder]) ifTrue:[
        self updateFromChannels
    ] ifFalse:[
        super update:something with:aParameter from:changedObject.
    ]

!

updateFromChannels
    "update canvas from channel
    "
    |client spec|

    clientHolder isNil ifTrue:[
        client := self application
    ] ifFalse:[
        client := clientHolder value
    ].

    specHolder isNil ifTrue:[
        spec := #windowSpec
    ] ifFalse:[
        spec := specHolder value
    ].
    (client notNil and:[spec notNil]) ifTrue:[
    ] ifFalse:[
"/        spec notNil ifTrue:[
"/            self halt:'spec but no app'.
"/        ].
        client := nil.
        spec := #windowSpec.  "/ is that true ?
    ].

    self client:client spec:spec builder:nil

    "Modified: / 5.8.1999 / 13:35:26 / cg"
! !

!SubCanvas methodsFor:'initialization'!

destroy
    client notNil ifTrue:[
        client == self application ifTrue:[
            client releaseAsSubCanvas.
        ] ifFalse:[
            client release
        ].
    ].

    clientHolder notNil ifTrue:[
        clientHolder removeDependent:self.
        clientHolder := nil.
    ].
    specHolder notNil ifTrue:[
        specHolder removeDependent:self.
        specHolder := nil.
    ].
    super destroy.

    "Modified: / 13.2.2000 / 23:31:12 / cg"
!

initialize

    super initialize.
"/    self scrolledView:(clientView := ApplicationSubView new).
    clientViewIsScrolled := false.

    "/ these defaults make subCanvas compatible with VW;
    "/ however, they make our life difficult sometimes.
    keepClientView := true.
    useApplicationSubView := false.
    useOwnBuilder := false.

    spec := #windowSpec.

    "Modified: / 31.1.2000 / 16:56:31 / cg"
! !

!SubCanvas methodsFor:'layout'!

usedScrolledViewHMarginWhenHasV:hasV andHasH:hasH
    "return the horizontal margin around (outer margin).
     Redefined to avoid margin when no scrollers are present"

    ^ (hasV or:[hasH]) ifTrue:[scrolledViewHMargin] ifFalse:[0]


!

usedScrolledViewVMarginWhenHasV:hasV andHasH:hasH
    "return the horizontal margin around (outer margin).
     Redefined to avoid margin when no scrollers are present"

    ^ (hasV or:[hasH]) ifTrue:[scrolledViewVMargin] ifFalse:[0]


! !

!SubCanvas methodsFor:'queries'!

application
    "return the application, under which this view was opened,
    "

    client notNil ifTrue:[
        ^ client
    ].
    ^ super application

! !

!SubCanvas class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libwidg2/SubCanvas.st,v 1.32 2000-12-15 15:46:45 tm Exp $'
! !