requires: {#SceneElement. #DisplayTransform}. provides: {#Morph. #Hand}. Graphics addPrototype: #Morph derivedFrom: {DisplayedSceneElement}. Morph addSlot: #coloredBorder. Morph addSlot: #totalRegion. Morph addSlot: #visibleRegion. Graphics addSlot: #MorphDefaultState valued: Cloneable clone. Morph addDelegate: #defaultState valued: MorphDefaultState. Morph addProtectedSlot: #locked in: #defaultState valued: False. Morph addProtectedSlot: #visible in: #defaultState valued: True. Morph addProtectedSlot: #sticky in: #defaultState valued: False. m@(Morph traits) clips "Whether the morph clips its children." [ True ]. m@(Morph traits) delete "Morph deletion should involve all clean-up tasks and responsibilities. Perform the basic removal task by default." [ m treeParent ifNotNil: [m treeParent remove: m] ]. m@(Morph traits) grabTransform [ m treeParent ifNil: [IdentityTransform] ifNotNil: [m treeParent grabTransform] ]. m@(Morph traits) handle: e@(Event traits) "The default handling for all events in general is to do nothing." "TODO: turn the method into handleInput:?" [ m ]. Graphics addPrototype: #Sheet derivedFrom: {Morph}. Sheet addSlot: #enabled valued: True. sm@(Sheet traits) viewable "Return whether the sheet will be viewable. This requires all of the parent Sheets to be enabled." [ sm enabled and: [sm treeParent viewable] ]. Graphics addPrototype: #Transform derivedFrom: {Morph}. Transform addSlot: #transform valued: IdentityTransform. tm@(Transform traits) grabTransform [ m treeParent ifNil: [IdentityTransform] ifNotNil: [m treeParent grabTransform ++ m transform] ]. Graphics addPrototype: #Hand derivedFrom: {Morph}. Graphics addPrototype: #DropEvent derivedFrom: {PointerEvent}. DropEvent addSlot: #contents. de@(DropEvent traits) newAt: p contents: m from: h [| newDE | newDE: DropEvent clone. newDE position: p. newDE contents: m. newDE pointer: h. newDE ]. m@(Morph traits) reject: de@(DropEvent traits) "The drop event has been rejected, and the morph must be put back somewhere." [ "Originally uses #formerOwner and #formerPosition, and then tries for the Trash." ]. h@(Hand traits) attach: m@(Morph traits) "Position the center of the morph under the hand, and then grab it. This grabs far away or created morphs." [| delta | h releasePointerFocus. delta: m bounds extent // 2. m position: h position - delta. m lastPos: m position. h targetOffset: m position - h position. h addLast: m. h ]. h@(Hand traits) drop: m@(Morph traits) on: e@(Event) [| event | event: (DropEvent newAt: h position contents: m from: h). "Send the event to the hand WRT the focus." event handled ifFalse: [m reject: e]. m owner == h ifTrue: [m delete]. "TODO: process the event as a mouse-over here?" ]. h@(Hand traits) dropAll "Drop all submorphs at this position, maintaining z-order." [ h children reverseDo: [| :each | h drop: each on: e] ]. h@(Hand traits) grab: m@(Morph traits) from: src@(Morph traits) [| grabbed offset targetPos grabTransform fullTransform | h releaseFocus. grabbed: m. grabTransform: src grabTransform. fullTransform: (src transformFrom: h owner). "the point in m's reference frame." targetPos: (fullTransform actOn: h position). "compute the offset due to using grabTransform to find the current position" offset: targetPos - (grabTransform actOn: h position). "apply the transform needed" grabbed: (grabbed transformedBy: grabTransform). "short for grabTransform isIdentity" grabbed == m ifFalse: ["Set FlexAtGrab On"]. "apply the offset needed" grabbed position: grabbed position - offset truncated. "TODO: find out if targetOffset is needed." h targetOffset: grabbed position - h position. h addBack: grabbed. h ]. h@(Hand traits) grab: m@(Morph traits) from: src@Nil "This is a simplified version of the general method." "TODO: factor out the common method from both." [ h releaseFocus. h targetOffset: m position - h position. h addBack: grabbed. ]. h@(Hand traits) grab: m@(Morph traits) "Grab the morph without changing its position, as distinguished from attach: which can move the morph (to the hand)." [| grabbed | h releaseFocus. (grabbed: (m morphForGrabbingBy: h)) ifNil: [^ h]. grabbed: grabbed leastTopRenderer. h grab: grabbed from: grabbed owner ].