SqueakByExample:11.7
드래그 앤 드롭(Drag-and-drop)
Morphic 은 이제까지 배운것 외에도 드래그 앤 드롭을 지원합니다.
수신자receiver 역할의 morph 와 내려놓아지는dropped 역할의 morph, 이 2 가지 객체에 대한 간단한 경우를 생각해 보겠습니다.
수신자는 내려놓은 morph 가 주어진 조건을 만족하는 경우에만 내려놓음drop 을 수락합니다: 이 예제에서 morph 는 파란색으로 하겠습니다. 수락이 거부되는경우, 내려놓아진 morph 가 뭘 할지도 결정하게 됩니다.
클래스 11.20: 다른 morph 를 내려놓을 수 있는 morph 를 정의하기
Morph subclass: #ReceiverMorph
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'SBE-Morphic'
늘 하던것처럼 initialization 메서드를 정의하십시오:
메서드 11.21: ReceiverMorph 의 초기화
ReceiverMorph»initialize
super initialize.
color := Color red.
bounds := 0 @ 0 extent: 200 @ 200
만약 받는쪽의 morph 는 drop 에 대한 수락 또는 거부를 어떻게 판단할까요? 대부분의 경우, 받는쪽과 내려놓아지는쪽의 양쪽 morph 모두 drop 작업에 동의해야 합니다. drop 을 받는쪽은 wantsDroppedMorph:event: 메시지에 반응하는것으로 행동을 결정할 수 있으며, 이 경우 메시지의 첫번짜 인자는 내려놓아진 morph, 두번째 인자는 마우스 이벤트이므로 drop 을 받는객체는 이 상황에 대한 판단을 할 수 있습니다. 예를들어, 받는객체는 drop 시점에서 어떤 modifier key 가 눌려져 있는지를 조사할 수 있다는거죠. 내려놓아진 morph, 또는 내려놓아지는 과정에 있는 morph 는 수신객체가 drop 을 받는 시점에서 wantToBeDroppedInto: 메시지를 받았을때에 받는객체가 내가 원하는 객체인지 알아볼 수 있는 기회를 가지게 됩니다. wantToBeDroppedInto: 메서드의 기본값(이 값은 Morph 클래스에 정의되어있습니다)으로 true 를 반환합니다.
메서드 11.22: morph 의 색상을 기준하여, 내려놓아진 morph 를 수락하기
ReceiverMorph»wantsDroppedMorph: aMorph event: anEvent
↑ aMorph color = Color blue
만약 받는 morph 가 떨어진 morph 를 원하지 않는 다면, 내려놓아진 morph 에는 어떤일이 일어날까요? 이 경우에 대한 기본동작은 아무것도 하지 않는 것으로 되어있으며, 이것은 내려놓아진 morph 가 받는 morph 상단에 위치하며 받는 모프와 상호작용은 하지 않는다는것을 의미합니다. 내려놓아진 morph 에 대한 좀 더 직관적인 동작은 해당되는 morph 의 드래그 이전, 원래의 위치로 돌아가는 것입니다. 이렇게 원래위치로 되돌아가는 작업은 수신객체가 내려놓아진 morph 를 원하지 않을 때, 메시지 repelsMorph:event: 에 true 로 답변할때 진행됩니다.
메서드 11.23: 내려놓아진 morph 가 거절 될 때 해당되는 morph 의 동작을 변경하기
ReceiverMorph>>repelsMorph: aMorph event: ev
↑ (self wantsDroppedMorph: aMorph event: ev) not
여기까지가, 수신객체에 대해 알아야할 모든 내용입니다.
워크스페이스에서 ReveiverMorph 와 EllipseMorph 의 인스턴스를 생성해주세요:
ReceiverMorph new openInWorld.
EllipseMorph new openInWorld.
수신객체에 노란색의 EllipseMorph 를 드래그 앤 드롭합니다. 이 작업은 거부될 것이며 떨어뜨려진 객체는 초기 위치로 다시 이동되겠죠.
이 동작을 변경 하기 위해, Inspector 를 사용하여 타원 morph 의 색상을 변경하십시오. 파랑 모프는 반드시 ReceiverMorph 에 대해서는 수락되어야만 합니다.
DroppedMorph 라는 이름을 가진 Morph 클래스의 특별한 서브클래스를 만들고, 이것을 이용해서 좀 더 많은 실험을 해보도록 하겠습니다:
클래스 11.24: ReceiverMorph 에 드래그 앤 드롭을 할 수 있도록 morph 를 정의하겠습니다.
Morph subclass: #DroppedMorph
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'SBE-Morphic'
메서드 11.25: DroppedMorph 초기화 하기
DroppedMorph>>initialize
super initialize.
color := Color blue.
self position: 250@100
떨어지게된 morph 가 받는객체에서 거절될때, 해야할 작업을 설정할 수 있습니다. 여기서, morph 는 마우스 포인터에 달려있게 될겁니다"
메서드 11.26: 모프를 내려다 놓았지만, 거절되지 않았다면 반응하기
DroppedMorph»rejectDropMorphEvent: anEvent
|h|
h := anEvent hand.
WorldState
addDeferredUIMessage: [h grabMorph: self].
anEvent wasHandled: true
이벤트에 hand 메세지를 보내면, HangMorph 의 인스턴스인 hand 를 반환하며, 이 객체는 마우스 포인터를 나타내고있고, 마우스 포인터에 대한건 뭐든지 가지고 있습니다. 여기서 drop 이 거부된 morph 인 self 를 잡고있어야 한다고 world 에게 지시하고 있죠.
DroppedMorph의 인스턴스들을 만들고, 수신자 위에 해당 인스턴스들을 끌어다 놓으십시오.
ReceiverMorph new openInWorld.
(DroppedMorph new color: Color blue) openInWorld.
(DroppedMorph new color: Color green) openInWorld.
녹색의 morph 는 거절되었으므로, 마우스 포인터에 잡혀있게 됩니다..