Dynamically preventing a drop
When determining if a drop is allowed on a part, the VA Smalltalk default drag and drop support checks only to see if the class of each object being dragged is acceptable to the drag target. Often, more rigorous testing is required to properly support drag and drop for your applications. The dragOver event offers you an opportunity to perform such testing. Let's try it with the card game.
When playing Black Jack, some hands are automatic winners. A hand that totals 21 exactly is one such automatic winner. Having a hand with five cards whose values add up to 21 or less is another. We can modify the BlackJackPlayerView part so that a card cannot be dropped on such a winning hand. Another case that can be handled is when the cards in the hand total more than 21. In this case the player has "busted" and should is not allowed to draw another card.
Open the Script Editor for the BlackJackPlayerView part. Add EwConstants to the poolDictionaries in the class definition. When you are done, the class definition should look like this:
AbtAppBldrView subclass: #BlackJackPlayerView
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: 'EwConstants'
The EwConstants pool dictionary provides many constants for drag and drop operations.
Add the following public instance script:
dragOver: callData
"Do not allow a drop when the hand is at 21 or more...
or the player has a 5-card trolley."
| cnr items |
cnr := (self subpartNamed: 'Container Details1').
items := cnr items.
callData targetModel: items.
self canTakeCard
ifTrue: [cnr imageDefaultDragOver: callData]
ifFalse: [ callData vote: #() ].
The dragOver: script works in a manner similar to some of the scripts you wrote when working with portable containers. The callData object has several attributes, including an ordered collection of the objects being dragged (the items attribute).
Most interesting is the vote attribute. This attribute can take on an array of constants including XmMOVE, XmCOPY, and XmLINK. This attribute is accessed by VA Smalltalk after the completion of the script to determine what default operations the part supports. Setting the vote attribute to an empty array, as is done in the dragOver: script, indicates that a drop operation is not allowed. When this value is set, VA Smalltalk automatically displays the "drop forbidden" mouse pointer over the window.
If a drop operation is allowed, you can have your scripts send the imageDefaultDragOver: message to the part. The part will then take over the drag operation, including checking that the class of each object being dragged is acceptable to the drag target.
Now, add the following public instance script:
canTakeCard
"Answer false if the player has a 5-card trolley,
a winning hand (21), or is busted (over 21)."
| sum items |
sum := 0.
items := (self subpartNamed: 'Container Details1') items.
items do: [:card | sum := sum + (card rank)].
^(items size > 4 or: sum > 20 ]) not
This script simply checks for the conditions outlined earlier and answers true if a drop is allowed.
Switch to the Composition Editor. Connect the dragOver event of the container to the dragOver: script. Save your part.
Testing the drag and drop support
Select the BlackJackGameView visual part and then Test iconto test the part.
Create a single player. Drag an Ace and a King from the deck to the hand. You should be unable to drop a third card on the hand because the value of these two cards add up to 21. Drag all the cards in the hand to the Discard window.
Drag a Queen, Jack, and 10 from the deck to the hand. You should be unable to drop a fourth card because the player has "busted." Drag all the cards in the hand to the Discard window.
Drag all four deuces and a three to the hand. You should be unable to drop a sixth card, because the player has a five-card trolley.
Last modified date: 06/11/2018