DragHandler.st
author ab
Mon, 30 May 2005 18:40:14 +0200
changeset 2043 72801901ff1c
parent 1836 c1e0cf991a4d
child 2044 6ac5271d6e40
permissions -rw-r--r--
add flushSaveArea in Opaque (set saveArea to nil).

"
 COPYRIGHT (c) 1998 by eXept Software AG / Claus Gittinger
              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:libview2' }"

Object subclass:#DragHandler
	instanceVariableNames:'rootView lastRootPoint'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-DragAndDrop'
!

DragHandler subclass:#Generic
	instanceVariableNames:'prevPoint lastPoint dragBlock'
	classVariableNames:''
	poolDictionaries:''
	privateIn:DragHandler
!

DragHandler subclass:#Line
	instanceVariableNames:'startPoint endPoint lineMode'
	classVariableNames:''
	poolDictionaries:''
	privateIn:DragHandler
!

DragHandler subclass:#Opaque
	instanceVariableNames:'dragSize dragBlock dragOffset saveUnder saveArea tmpForm'
	classVariableNames:''
	poolDictionaries:''
	privateIn:DragHandler
!

!DragHandler class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1998 by eXept Software AG / Claus Gittinger
              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
"
    this abstract class describes the protocol common to any DragHandler.
    The DragAndDropManger creates one instance responsible to show the
    dragging objects on the screen.

    [author:]
        Claus Gittinger

    [see also:]
        DragAndDropManager
"



! !

!DragHandler class methodsFor:'instance creation'!

startArrowDragAt:aStartPoint
    "creates and returns the drag handler which is responsible
     for an arrow drag.
    "
    ^ Line new startPoint:aStartPoint mode:#arrow
!

startGenericDrag:aTwoArgDragBlock
    "creates and returns the drag handler which is responsible
     for a generic drag.
    "
    ^ Generic new dragBlock:aTwoArgDragBlock
!

startLineDragAt:aStartPoint
    "creates and returns the drag handler which is responsible
     for a line drag.
    "
    ^ Line new startPoint:aStartPoint mode:nil
!

startOpaqueDrag:aTwoArgDragBlock extent:anExtent offset:anOffset
    "creates and returns the drag handler which is responsible
     for a generic opaque drag.
    "
    ^ Opaque new dragSize:anExtent dragOffset:anOffset dragBlock:aTwoArgDragBlock
! !

!DragHandler methodsFor:'event dropTarget'!

dropTargetWillChange
    "called before the drop target or widget changed.
     restore root view ... (optional)
    "

!

isInterestedInDropTarget
    "returns true, if the handler is interested in the underlying
     drop target and the target should be tested to be able to drop
     the objects.
    "
    ^ true


! !

!DragHandler methodsFor:'protocol'!

dragTo:aRootPoint
    "drag to a root point
    "
    self subclassResponsibility


!

flushSaveArea
!

postDragging
    "after dragging; restore root view ...
    "
    self subclassResponsibility


!

preDraggingIn:aSourceWidget
    "called before starting the drag & drop operation
    "
    rootView := aSourceWidget device rootView.

!

rereadSaveArea
! !

!DragHandler::Generic class methodsFor:'documentation'!

documentation
"
    this class handles a generic drag on the screen. It is not visible to
    the user and is created automatically by the DragAndDropManger.

    [author:]
        Claus Gittinger

    [see also:]
        DragAndDropManager
"


! !

!DragHandler::Generic methodsFor:'instance creation'!

dragBlock:aTwoArgBlock
    "the dragBlock will be called with two arguments, aPoint and the drawing GC,
     to perform the drawing at some dragPoint.
    "
    dragBlock := aTwoArgBlock
! !

!DragHandler::Generic methodsFor:'protocol'!

dragTo:aRootPoint
    "drag to a root point
    "
    prevPoint notNil ifTrue:[
        self postDragging
    ].
    lastPoint := nil.
    prevPoint := lastRootPoint := aRootPoint.
    self postDragging
!

postDragging

    lastPoint isNil ifTrue:[
        lastPoint := prevPoint.
    ].
    rootView clippedByChildren:false.

    rootView xoring:[
        rootView lineWidth:0.
        dragBlock value:lastPoint value:rootView.
        rootView flush
    ]

! !

!DragHandler::Line class methodsFor:'documentation'!

documentation
"
    this class handles a line or arrow drag on the screen. It is not visible to
    the user and is created automatically by the DragAndDropManger.

    [author:]
        Claus Gittinger

    [see also:]
        DragAndDropManager
"


! !

!DragHandler::Line methodsFor:'event dropTarget'!

isInterestedInDropTarget
    ^ false


! !

!DragHandler::Line methodsFor:'instance creation'!

startPoint:aPoint mode:aMode

    lineMode   := aMode.
    startPoint := aPoint.


! !

!DragHandler::Line methodsFor:'protocol'!

dragTo:aRootPoint
    "do a line or arrow drag
    "
    self postDragging.
    endPoint := lastRootPoint := aRootPoint.
    self postDragging.
!

postDragging
    "invert for a line or arrow drag
    "
    |arrow|

    endPoint isNil ifTrue:[
        ^ self
    ].
    rootView clippedByChildren:false.

    rootView xoring:[
        rootView lineWidth:0. 

        lineMode == #arrow ifTrue:[
            arrow := Arrow from:startPoint to:endPoint.
            arrow arrowHeadLength:(rootView device horizontalPixelPerMillimeter * 4) rounded.
            arrow displayFilledOn:rootView.
        ] ifFalse:[
            rootView displayLineFrom:startPoint to:endPoint.
        ].
        rootView flush
    ]

! !

!DragHandler::Opaque class methodsFor:'constants'!

additionalSaveSize
    ^ 50 @ 50


! !

!DragHandler::Opaque class methodsFor:'documentation'!

documentation
"
    this class handles an generic opaque drag on the screen. It is not visible
    to the user and is created automatically by the DragAndDropManger.

    [author:]
        Claus Gittinger

    [see also:]
        DragAndDropManager
"


! !

!DragHandler::Opaque methodsFor:'instance creation'!

dragSize:anExtent dragOffset:anOffset dragBlock:aTwoArgBlock
    "the dragBlock will be called with two arguments, aPoint and the drawing GC,
     to perform the drawing at some dragPoint.
    "
    dragSize   := anExtent.
    dragOffset := anOffset.
    dragBlock  := aTwoArgBlock
! !

!DragHandler::Opaque methodsFor:'protocol'!

dragTo:aRootPoint
    "drag to a root point
    "
    |p extent point area|

    (saveArea notNil and:[lastRootPoint notNil]) ifTrue:[
        (    lastRootPoint x == aRootPoint x
        and:[lastRootPoint y == aRootPoint y]
        ) ifTrue:[
            "/ nothing changed
            ^ self
        ].
    ].

    lastRootPoint := aRootPoint.
    "/
    "/ copy from screen to saveUnder
    "/
    rootView clippedByChildren:false.
    extent := saveUnder extent.
    point  := aRootPoint - dragOffset.

    saveArea notNil ifTrue:[
        (     (saveArea left   <= point x)
         and:[(saveArea top    <= point y)
         and:[(saveArea right  >= (point x + dragSize x))
         and:[(saveArea bottom >= (point y + dragSize y))]]]
        ) ifFalse:[
            "/
            "/ draggable objects no longer contained in saved area;
            "/ thus we have to restore the saved area on the screen.
            "/
            self postDragging
        ]
    ].

    saveArea isNil ifTrue:[
        "/
        "/ screen not yet saved; thus we have to save the area
        "/
        p := point  - (self class additionalSaveSize).

        saveUnder copyFrom:rootView 
                         x:p x
                         y:p y
                       toX:0 
                         y:0 
                     width:extent x
                    height:extent y.
        saveArea := p extent:extent.
    ].
    area := saveArea.

    "/
    "/ draw into the form using the dragAction block
    "/
    tmpForm copyFrom:saveUnder toX:0 y:0. 
    tmpForm paint:Color black.

    dragBlock value:(point  - saveArea origin + dragOffset) value:tmpForm.

    area == saveArea ifFalse:[
        "saveArea changed during dragB;lock operation"
        ^ self
    ].
    rootView copyFrom:tmpForm
                    x:area origin x
                    y:area origin y 
                width:extent x 
               height:extent y
!

dropTargetWillChange
    "restore old saveArea
    "
    self postDragging


!

flushSaveArea
    saveArea := nil
!

postDragging
    "restore from saveUnder for a generic opaque drag
    "
    saveArea notNil ifTrue:[
        rootView clippedByChildren:false.
        "/
        "/ copy from saveUnder back to screen
        "/
        rootView copyFrom:saveUnder 
                        x:saveArea origin x 
                        y:saveArea origin y 
                    width:saveArea extent x  
                   height:saveArea extent y.

        saveArea := nil.
    ]
!

preDraggingIn:aSourceWidget
    "setup my default values
    "
    |depth extent device|

    super preDraggingIn:aSourceWidget.

    device    := aSourceWidget device.
    depth     := rootView device depth.
    extent    := dragSize + (2 * (self class additionalSaveSize)).
    saveUnder := Form extent:extent depth:depth on:device.
    tmpForm   := Form extent:extent depth:depth on:device.

    saveUnder clippedByChildren:false.
    tmpForm initGC.
    tmpForm font:(aSourceWidget font).


!

rereadSaveArea
    saveArea notNil ifTrue:[
        rootView clippedByChildren:false.
        "/
        "/ copy from saveUnder back to screen
        "/
        saveUnder copyFrom:rootView 
                        x:saveArea origin x 
                        y:saveArea origin y 
                    width:saveArea extent x  
                   height:saveArea extent y.
    ]
!

restoreFromSaveArea
    lastRootPoint notNil ifTrue:[
        self dragTo:lastRootPoint
    ].
! !

!DragHandler class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libview2/DragHandler.st,v 1.6 2005-05-30 16:40:14 ab Exp $'
! !