UIGalleryView.st
author Claus Gittinger <cg@exept.de>
Mon, 22 Mar 2004 12:57:20 +0100
changeset 1807 c9e94b879c44
parent 1729 cf1c2f488ba8
child 1895 b7d6683ebaca
permissions -rw-r--r--
removed via FileBrowser

"
 COPYRIGHT (c) 1997 by Claus Gittinger / 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:libtool2' }"

NoteBookView subclass:#UIGalleryView
	instanceVariableNames:'majorKey minorKeys minorKeysHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-UIPainter'
!

View subclass:#Canvas
	instanceVariableNames:'clientSpecHolder selection specification lastClickPoint
		menuSelector uiBuilder hiddenCounter'
	classVariableNames:''
	poolDictionaries:''
	privateIn:UIGalleryView
!

DropObject subclass:#DropSpec
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	privateIn:UIGalleryView::Canvas
!

!UIGalleryView class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by Claus Gittinger / 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
"
    implements a selection panel, keeping widgets which could be placed
    into other components by drag & drop or copy @ paste. The objects
    which are draged/droped must be kind of UISpecification's.
    The UISelectionPanel used by the UIPainter is implemented in this way.

    [author:]
	Claus Gittinger
	Claus Atzkern

    [see also:]
	UIPainter
	UISelectionPanel
"

!

examples
"
    opens a gallery

									[exBegin]
    |top sel|

    top := StandardSystemView new label:'gallery'; extent:500@300.
    sel := UIGalleryView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top.

    sel labels:#(    'Buttons'
		     'Panels'
		     'Text'
		   ).

    sel minorKeys:#( #standardButtonToggle
		     #standardPanels
		     #standardText
		   ).

    sel majorKey:UISelectionPanel.
    top open.
									[exEnd]
"
! !

!UIGalleryView methodsFor:'accessing'!

builder
    "get the builder used to setup a window from a specification (or nil in case
     of using a new builder)
    "
  ^ canvas builder
!

builder:aBuilderOrNil
    "set the builder used to setup a window from a specification (or nil in case
     of using a new builder)
    "
    canvas builder:aBuilderOrNil
!

canvas:aCanvas
    ^ self

!

labels:listOfLabels minorKeys:listOfMinorKeys majorKey:aMajorKey
    "setup for labels, selectors and class provider
    "
    self labels:listOfLabels.
    minorKeys := listOfMinorKeys.
    majorKey  := aMajorKey.
!

majorKey
    "get the class providing the window specifications
    "
  ^ majorKey
!

majorKey:aKey
    "get the class providing the window specifications
    "
    |appl|

    appl := self application.

    appl notNil ifTrue:[
	majorKey := appl resolveName:aKey
    ] ifFalse:[
	majorKey := Smalltalk resolveName:aKey inClass:self class
    ].
    self selection:nil
!

minorKeys
    "get the list of selector keys
    "
  ^ minorKeys
!

minorKeys:aListOfSelectors
    "set the list of selectors
    "
    minorKeys := aListOfSelectors.
    self selection:nil.
! !

!UIGalleryView methodsFor:'accessing-holders'!

clientSpecHolder
    "get the holder which keeps the current selection or in case of
     no selection the specification under the cursor
    "
  ^ canvas clientSpecHolder
!

clientSpecHolder:aHolder
    "set the holder which keeps the current selection or in case of
     no selection the specification under the cursor
    "
    canvas clientSpecHolder:aHolder
!

menuSelector
    ^ canvas menuSelector
!

menuSelector:aSelector
    ^ canvas menuSelector:aSelector
!

minorKeysHolder
    "get the holder keeping the minor keys; the selectors to access
     specifications from a class associated with the majorKey.
    "
  ^ minorKeysHolder
!

minorKeysHolder:aValueHolder
    "set the holder keeping the minor keys; the selectors to access
     specifications from a class associated with the majorKey.
    "
    minorKeysHolder notNil ifTrue:[
	minorKeysHolder removeDependent:self. 
    ].

    (minorKeysHolder := aValueHolder) notNil ifTrue:[
	minorKeysHolder addDependent:self.
    ].
    self minorKeys:(minorKeysHolder value)
! !

!UIGalleryView methodsFor:'change & update'!

selectionHasChanged
    "selection changed
    "
    |specification selector selection application|

    selection := self listIndexOf:(self selection).

    minorKeysHolder notNil ifTrue:[
        minorKeys := minorKeysHolder value.
    ].
    (selection notNil and:[minorKeys size >= selection]) ifTrue:[
        selector := minorKeys at:selection.

        (majorKey respondsTo:selector) ifTrue:[
            specification := majorKey perform:selector
        ] ifFalse:[
            (application := self application) notNil ifTrue:[
                MessageNotUnderstood handle:[:ex|
                    (application class respondsTo:selector) ifTrue:[
                        specification := application class perform:selector
                    ]
                ] do:[
                    specification := application aspectFor:selector
                ]
            ]
        ]
    ].
    self withWaitCursorDo:[
        canvas specification:specification.
    ]
!

update
    self selectionHasChanged.
!

update:something with:aParameter from:changedObject
    "one of my models changed its value
    "
    changedObject == minorKeysHolder ifTrue:[
        ^ self minorKeys:( minorKeysHolder value)
    ].
    super update:something with:aParameter from:changedObject.

! !

!UIGalleryView methodsFor:'initialization & release'!

initialize
    "setup default attributes
    "
    canvas := Canvas in:self.

    super initialize.

    self action:[:something| self selectionHasChanged ].
!

release
    minorKeysHolder notNil ifTrue:[
        minorKeysHolder removeDependent:self. 
        minorKeysHolder := nil.
    ].
    super release.
! !

!UIGalleryView::Canvas methodsFor:'accessing'!

builder
    "get the builder used to setup a window from a specification (or nil in case
     of using a new builder)
    "
  ^ uiBuilder
!

builder:something
    "set the builder used to setup a window from a specification (or nil in case
     of using a new builder)
    "
    uiBuilder := something.
!

clientSpecHolder
    "get the holder which keeps the current selection or in case of
     no selection the specification under the cursor
    "
    ^ clientSpecHolder
!

clientSpecHolder:aHolder
    "set the holder which keeps the current selection or in case of
     no selection the specification under the cursor
    "
    |spec|

    spec := clientSpecHolder value.

    aHolder notNil ifTrue:[ clientSpecHolder := aHolder ]
                  ifFalse:[ clientSpecHolder := nil asValue ].

    clientSpecHolder value:spec.
!

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

    ^ menuSelector
!

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

    menuSelector := something.
!

specification
    "get current specification
    "
    ^ specification
!

specification:aSpecOrSpecArray
    "set a new specification
    "
    |builder|

    self selection:nil.
    self destroySubViews.

    (     aSpecOrSpecArray notNil
     and:[(specification := UISpecification from:aSpecOrSpecArray) notNil
     and:[specification respondsTo:#'buildViewFor:in:']]
    ) ifFalse:[
        specification := nil.
        ^ self
    ].

    (builder := uiBuilder) isNil ifTrue:[
        builder := UIBuilder new isEditing:true.
        builder showDefaults:true.
    ].

    specification buildViewFor:builder in:self.

    subViews size ~~ 0 ifTrue:[
        subViews do:[:v|
            (self findSpecFor:v) notNil ifTrue:[
                v borderWidth:1
            ]
        ].
        realized ifTrue:[ self realizeAllSubViews ].
    ].
! !

!UIGalleryView::Canvas methodsFor:'building'!

buildSpecFrom:aSpec
    "build spec out of spec
    "
    |spec comp coll|

    (aSpec notNil and:[aSpec canUIDrag]) ifFalse:[
	^ nil
    ].

    spec := aSpec copy.

    (aSpec class supportsSubComponents and:[aSpec component notNil]) ifFalse:[
	^ spec
    ].
    comp := aSpec component.
    spec component:nil.

    comp canUIDrag ifFalse:[
      ^ spec
    ].
    coll := OrderedCollection new.

    comp do:[:anEntry||spc|
	(spc := self buildSpecFrom:anEntry) notNil ifTrue:[
	    coll add:spc
	]
    ].
    coll isEmpty ifTrue:[
      ^ spec
    ].
    comp := comp copy.
    comp collection:coll.
    spec component:comp.
  ^ spec




! !

!UIGalleryView::Canvas methodsFor:'drag & drop'!

startDragFrom:evView
    "start drag at a point
    "
    |spec dragObj offset clickPos|

    clickPos := lastClickPoint.
    clickPos isNil ifTrue:[^ self].
    lastClickPoint := nil.

    spec := clientSpecHolder value.
    spec isNil ifTrue:[^ self].

    self selectionHiddenDo:[
        spec := self buildSpecFrom:spec.
        spec name:nil.

        dragObj := DropSpec for:selection specification:spec.
        offset  := clickPos - selection origin.
    ].

    DragAndDropManager startDrag:dragObj from:evView offset:offset.
! !

!UIGalleryView::Canvas methodsFor:'event handling'!

processEvent:anEvent
    |evView p|

    evView := anEvent view.
    evView isNil ifTrue:[ ^ false ].

    evView == self ifFalse:[
        (evView isComponentOf:self) ifFalse:[ ^ false ].
    ].

    anEvent isButtonEvent ifFalse:[
        anEvent isInputEvent ifTrue:[^ true].
        anEvent isDamage ifTrue:[ self redrawSelection ].
        ^ false
    ].

    anEvent isButtonReleaseEvent ifTrue:[
        lastClickPoint := nil.
        ^ true
    ].

    anEvent isButtonMotionEvent ifTrue:[
        (lastClickPoint notNil and:[anEvent state ~~ 0]) ifTrue:[
            p := Point x:(anEvent x) y:(anEvent y).

            (lastClickPoint dist:p) > 10.0 ifTrue:[
                self startDragFrom:evView.
                lastClickPoint := nil.
            ]
        ].
        ^ true
    ].

    anEvent isButtonPressEvent ifTrue:[ |button application|
        button := anEvent button.
        lastClickPoint := nil.

        (button == 1 or:[button == #select]) ifTrue:[
            p := Point x:(anEvent x) y:(anEvent y).
            p := device translatePoint:p fromView:evView toView:self.

            self selection:(self findObjectAt:p).

            selection notNil ifTrue:[
                lastClickPoint := p
            ]
        ] ifFalse:[
            (menuSelector notNil and:[(application := self application) notNil]) ifTrue:[
                MessageNotUnderstood catch:[
                    application aspectFor:menuSelector
                ]
            ]
        ].
        ^ true
    ].

    ^ true
! !

!UIGalleryView::Canvas methodsFor:'initialization'!

initialize
    super initialize.
    clientSpecHolder := nil asValue.
    hiddenCounter := 0.
!

realize
    super realize.
    self windowGroup addPreEventHook:self.
! !

!UIGalleryView::Canvas methodsFor:'searching'!

findObjectAt:aPoint
    "find the origin/corner of the currentWidget
    "
    |p x y|

    subViews size == 0 ifTrue:[^ nil].

    subViews do:[:v|
        p := device translatePoint:aPoint fromView:self toView:v.
        x := p x.
        y := p y.

        (     x >= 0 and:[x <= v width
         and:[y >= 0 and:[y <= v height
         and:[(self findSpecFor:v) notNil]]]]
        ) ifTrue:[
            ^ v
        ]
    ].
    ^ nil
!

findSpecFor:aView
    "returns subspec assigned to instance or nil
    "
    |name|

    aView notNil ifTrue:[
        name := aView name.

        specification do:[:aSpec|
            (aSpec notNil and:[aSpec name = name]) ifTrue:[
                aSpec canUIDrag ifTrue:[^ aSpec ].
                ^ nil
            ]
        ]
    ].
    ^ nil

    "Modified: / 18.5.1999 / 14:47:25 / cg"
! !

!UIGalleryView::Canvas methodsFor:'selection'!

handlesOf:aComponent do:aOneArgBlock
    "evaluate the block on each handle; the argument to the block
     is a rectangle
    "
    aComponent notNil ifTrue:[
	aOneArgBlock value:(aComponent origin       - (2@2) extent:6@6).
	aOneArgBlock value:(aComponent corner       - (1@1) extent:6@6).
	aOneArgBlock value:(aComponent topRight     - (1@2) extent:6@6).
	aOneArgBlock value:(aComponent bottomLeft   - (2@1) extent:6@6).
	aOneArgBlock value:(aComponent leftCenter   - (2@0) extent:6@6).
	aOneArgBlock value:(aComponent rightCenter  - (1@0) extent:6@6).
	aOneArgBlock value:(aComponent topCenter    - (0@2) extent:6@6).
	aOneArgBlock value:(aComponent bottomCenter - (0@1) extent:6@6).
    ]


!

redrawSelection
    "redraw all items selected
    "
    (shown and:[selection notNil and:[hiddenCounter == 0]]) ifTrue:[
        self clippedByChildren:false.

        self handlesOf:selection do:[:aRectangle|
            self fillRectangle:aRectangle
        ].
        self clippedByChildren:true.
    ].
!

selection:aView
    "selection changed
    "
    |spec|

    selection == aView ifTrue:[^ self].

    self selectionHiddenDo:[
        spec := self findSpecFor:aView.

        spec notNil ifTrue:[ selection := aView ]
                   ifFalse:[ selection := nil ].

        clientSpecHolder value:spec.
    ].
!

selectionHiddenDo:aOneArgBlock
    |r|

    [   hiddenCounter :=  hiddenCounter + 1.

        hiddenCounter == 1 ifTrue:[
            (shown and:[selection notNil]) ifTrue:[
                self clippedByChildren:false.

                self handlesOf:selection do:[:aRectangle|
                    self clearRectangle:aRectangle
                ].
                self clippedByChildren:true.

                r := selection bounds.

                subViews do:[:sv|
                    |absOrg absFrame|

                    (sv bounds intersects:r) ifTrue:[
                        sv borderColor:(Color white).           "/ to force a redraw
                        sv borderColor:(Color black).

                        sv withAllSubViewsDo:[:v|
                            v realized ifTrue:[
                                v fill:v viewBackground.
                                v exposeX:0 y:0 width:v width height:v height.
                            ]
                        ]
                    ]
                ]
            ].
        ].
        aOneArgBlock value.
    ] ensure:[
        hiddenCounter := hiddenCounter - 1.
        self redrawSelection.
    ].
! !

!UIGalleryView::Canvas::DropSpec class methodsFor:'instance creation'!

for:aView specification:aSpec
    "create drop object for a view derived from a specification
    "
    |point extent rootView device inst displayObject|

    device   := aView device.
    rootView := device rootView.
    extent   := aView extent.
    point    := device translatePoint:0@0 fromView:aView toView:rootView.

    (point x > 0 and:[point y > 0]) ifTrue:[
        point := point + extent.
        (point x < rootView width and:[point y < rootView height]) ifTrue:[
            aView topView raise.
            device flush.
            aView invalidate.
            aView windowGroup processExposeEvents.
            displayObject := Image fromView:aView grab:false.
        ]
    ].
    displayObject isNil ifTrue:[
        displayObject := Form extent:extent depth:1.
        displayObject colorMap:(Array with:Color white with:Color black).
        displayObject fill:(Color colorId:0).
        displayObject paint:(Color colorId:1).
        displayObject displayRectangleX:0 y:0 width:aView extent x height:aView extent y.
    ].
    aSpec class == UISubSpecification ifTrue:[
        aSpec layout:(LayoutOrigin fromPoint:0@0)
    ].

    inst := self new.
    inst displayObject:displayObject.
    inst theObject:aSpec.
  ^ inst.

    "Modified: / 10.10.2001 / 14:03:00 / cg"
! !

!UIGalleryView class methodsFor:'documentation'!

version
    ^ '$Header$'
! !