'From etoys3.0 of 24 February 2008 [latest update: #2020] on 21 June 2008 at 2:44:46 pm'! "Change Set: renameDndOutMethods-tak Date: 21 June 2008 Author: Takashi Yamamiya Dag and Drop output related methods are renamed to use word 'dndOut' "! !HandMorph methodsFor: 'grabbing/dropping' stamp: 'tak 6/21/2008 14:34'! dropMorph: aMorph event: anEvent "Drop the given morph which was carried by the hand" | event dropped | self handleDndOutMorph: aMorph. (anEvent isMouseUp and:[aMorph shouldDropOnMouseUp not]) ifTrue:[^self]. "Note: For robustness in drag and drop handling we remove the morph BEFORE we drop him, but we keep his owner set to the hand. This prevents system lockups when there is a problem in drop handling (for example if there's an error in #wantsToBeDroppedInto:). THIS TECHNIQUE IS NOT RECOMMENDED FOR CASUAL USE." self privateRemove: aMorph. aMorph privateOwner: self. dropped _ aMorph. (dropped hasProperty: #addedFlexAtGrab) ifTrue:[dropped _ aMorph removeFlexShell]. event _ DropEvent new setPosition: self position contents: dropped hand: self. self sendEvent: event focus: nil. event wasHandled ifFalse:[aMorph rejectDropMorphEvent: event]. aMorph owner == self ifTrue:[aMorph delete]. self mouseOverHandler processMouseOver: anEvent.! ! !HandMorph methodsFor: 'grabbing/dropping' stamp: 'tak 6/21/2008 14:27'! grabMorph: aMorph from: formerOwner "Grab the given morph (i.e., add it to this hand and remove it from its current owner) without changing its position. This is used to pick up a morph under the hand's current position, versus attachMorph: which is used to pick up a morph that may not be near this hand." | grabbed offset targetPoint grabTransform fullTransform | self releaseMouseFocus. "Break focus" grabbed _ aMorph. aMorph keepsTransform ifTrue:[ grabTransform _ fullTransform _ IdentityTransform new. ] ifFalse:[ "Compute the transform to apply to the grabbed morph" grabTransform _ formerOwner ifNil: [IdentityTransform new] ifNotNil: [formerOwner grabTransform]. "Compute the full transform for the grabbed morph" fullTransform _ formerOwner ifNil: [IdentityTransform new] ifNotNil: [formerOwner transformFrom: owner]. ]. "targetPoint is point in aMorphs reference frame" targetPoint _ fullTransform globalPointToLocal: self position. "but current position will be determined by grabTransform, so compute offset" offset _ targetPoint - (grabTransform globalPointToLocal: self position). "apply the transform that should be used after grabbing" grabbed _ grabbed transformedBy: grabTransform. grabbed == aMorph ifFalse: [grabbed setProperty: #addedFlexAtGrab toValue: true]. "offset target to compensate for differences in transforms" grabbed position: grabbed position - offset asIntegerPoint. "And compute distance from hand's position" targetOffset _ grabbed position - self position. self addMorphBack: grabbed. grabbed justGrabbedFrom: formerOwner. self dndOutStart: grabbed! ! !HandMorph methodsFor: 'private events' stamp: 'tak 6/21/2008 14:30'! generateDropFilesEvent: evtBuf "Generate the appropriate mouse event for the given raw event buffer" "Note: This is still in an experimental phase and will need more work" | position buttons modifiers stamp numFiles dragType | stamp := evtBuf second. stamp = 0 ifTrue: [stamp := Time millisecondClockValue]. dragType := evtBuf third. position := evtBuf fourth @ evtBuf fifth. buttons := 0. modifiers := evtBuf sixth. buttons := buttons bitOr: (modifiers bitShift: 3). numFiles := evtBuf seventh. dragType = 4 ifTrue: ["e.g., drop" owner borderWidth: 0. ^DropFilesEvent new setPosition: position contents: numFiles hand: self]. "the others are currently not handled by morphs themselves" dragType = 1 ifTrue: ["experimental drag enter" owner borderWidth: 4; borderColor: owner color asColor negated]. dragType = 2 ifTrue: ["experimental drag move" ]. dragType = 3 ifTrue: ["experimental drag leave" owner borderWidth: 0]. dragType = 5 ifTrue: [self handleDndOut]. ^nil! ! !HandMorph methodsFor: 'external dragging' stamp: 'tak 6/21/2008 14:28'! dndOutStart: aMorph | types nullSeparated | "Drag and Drop session is initialized in this method." types := aMorph mimeTypes. nullSeparated := String streamContents: [:str | types do: [:type | str nextPutAll: type] separatedBy: [str nextPut: (Character value: 0)]]. self primitiveDndOutStart: nullSeparated! ! !HandMorph methodsFor: 'external dragging' stamp: 'tak 6/21/2008 14:37'! handleDndOut | morph stream writer type | "Send dragging object data to requester window." morph := self valueOfProperty: #dndOutMorph ifAbsent: [^ self]. type := self primitiveDndOutAcceptedType. type = 'image/png' ifTrue: [stream := ByteArray new writeStream. writer := PNGReadWriter on: stream binary. writer nextPutImage: morph imageForm. writer close. stream contents. ^ self primitiveDndOutSend: stream contents]. type = 'UTF8_STRING' ifTrue: [^ self primitiveDndOutSend: (morph getCharacters convertToEncoding: 'utf8')]! ! !HandMorph methodsFor: 'external dragging' stamp: 'tak 6/21/2008 14:33'! handleDndOutMorph: aMorph "Remember target morph for dnd out" self setProperty: #dndOutMorph toValue: aMorph! ! !NewHandleMorph methodsFor: 'submorphs-add/remove' stamp: 'tak 6/21/2008 14:34'! delete hand ifNotNil:[ hand showTemporaryCursor: nil. hand handleDndOutMorph: nil. ]. super delete.! ! HandMorph removeSelector: #dragOutStart:! HandMorph removeSelector: #handleDragOutside:! HandMorph removeSelector: #handleDropOut! HandMorph removeSelector: #handleDropOutMorph:!