Reacting to Keystrokes in Etoys

ajbn at cin.ufpe.br ajbn at cin.ufpe.br
Tue Jan 28 10:40:39 PST 2003


Hi Scott and Jahanzeb,

Using Karl Ramberg's CS (as mentioned by Kim
<http://www.squeakland.org/listarchive/squeakland/msg00467.html>), I have
created a simple project too. You can control the "Star" using the arrows
key in your keyboard :)I have attached both the project file and the change set file (sorry for
that, but I am not allowed to upload to
<http://www.squeakland.org:8080/super>. How can I get permission to do
this?).First, file in Karl Ramberg's change set (you can get a File List to do
that in the Tool category of the Object Catalog in the Supplies flap) and
then load my project. Press the go button and have fun with the arrows key
;)I have uploaded the project to Squealand-BSS too; the name is "Keyboard
Demo (Brazil)".Scott, what do think?
Cheers,

Antonio Barros
Graduate Student (and Squeak lover ;))
Federal University of Pernambuco
Brazil

> Several people have mentioned recently that they would like to be  able
> react to keystrokes in etoy scripts.
>
> Attached is a simple project that illustrates one straightforward way
> that this could be done.  Please have a look -- examine the
> "navigate" scripts of the two objects -- and see what you think.
>
> If there is interest, we could add this to the etoy system.  Comments
> please!
>
> Cheers,
>
>   -- Scott


-------------- next part --------------
A non-text attachment was scrubbed...
Name: Keyboard Demo (Brazil).001.pr
Type: application/x-zip-compressed
Size: 60009 bytes
Desc: not available
Url : http://squeakland.org/mailman/private/squeakland/attachments/20030128/c1daf57a/KeyboardDemoBrazil.001.bin
-------------- next part --------------
'From Squeak3.2 of 11 July 2002 [latest update: #4956] on 28 August 2002 at 4:34:45 pm'!
"Change Set:		etoy keystroke
Date:			28 August 2002
Author:			Karl Ramberg

Adds ability for any morphs to recive keystrokes and trigger etoy scripts.
To test this: 
Add a morph to your project.
Open a viewer on the morph.
Add a new script to it.
Set the trigger to keystroke.
Add a test tile to the script.
Select Basic category in the viewer flap.
Drag and drop a 'morph's keystroke' tile to the test part of the test tile.
Now set the 'morph's hasKeyboardFocus' to true.
Press a key. 
Look in the viewer keystroke tile and notice that there is a number next to it. This is the keystrokes ASCII number.
Change the test tile to check for conditions when the the keystroke is equal to that number. 
Then add a tile to the tests 'Yes' condition
something like 'morph forward by 5'
Now when the morph has keyboard focus and you press the key that equals the number you put in, the morph will move forward by 5.
Enjoy"!

BorderedMorph subclass: #PasteUpMorph
	instanceVariableNames: 'presenter model cursor padding backgroundMorph turtleTrailsForm turtlePen lastTurtlePositions isPartsBin autoLineLayout indicateCursor resizeToFit wantsMouseOverHalos worldState griddingOn '
	classVariableNames: 'DisableDeferredUpdates MinCycleLapse StillAlive '
	poolDictionaries: ''
	category: 'Morphic-Worlds'!

!Morph methodsFor: 'event handling' stamp: 'kfr 8/25/2002 09:42'!
getKeyStroke
 ^ self valueOfProperty: #userKey! !

!Morph methodsFor: 'event handling' stamp: 'ar 10/28/2000 22:18'!
handlesKeyboard: evt
	"Return true if the receiver wishes to handle the given keyboard event"
	self eventHandler ifNotNil: [^ self eventHandler handlesKeyboard: evt].
	^ false
! !

!Morph methodsFor: 'event handling' stamp: 'kfr 8/25/2002 09:43'!
keyDown: event
        self setProperty: #userKey toValue: event keyValue! !


!Morph class methodsFor: 'scripting' stamp: 'kfr 8/26/2002 11:01'!
additionsToViewerCategoryBasic
	"Answer viewer additions for the 'basic' category"

	^#(
		basic 
		(
			(slot x 'The x coordinate' Number readWrite Player getX Player setX:)
			(slot y  	'The y coordinate' Number readWrite Player 	getY Player setY:)
			(slot heading  'Which direction the object is facing.  0 is straight up' Number readWrite Player getHeading Player setHeading:)
			(command forward: 'Moves the object forward in the direction it is heading' Number)
			(command turn: 'Change the heading of the object by the specified amount' Number)
			(command beep: 'Make the specified sound' Sound)
			(slot keyStroke 'the key currently pressed' number readWrite player getKeyStroke  unused unused)
			(slot hasKeyboardFocus 'whether the object recieve keyboard events' Boolean readWrite Player getKeyboardFocus unused setKeyboardFocus:)
		)
	)
! !


!PasteUpMorph methodsFor: 'event handling' stamp: 'kfr 8/25/2002 09:46'!
handlesKeyboard: evt
	^(self isWorldMorph or:[evt keyCharacter == Character tab and:[self hasProperty: #tabAmongFields]]) ! !


!PasteUpMorph class methodsFor: 'scripting' stamp: 'kfr 8/25/2002 09:44'!
additionsToViewerCategories
	"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories."

	^ # (

(playfield (
(command initiatePainting 'Initiate painting of a new object in the standard playfield.')
(slot mouseX 'The x coordinate of the mouse pointer' Number readWrite Player getMouseX  unused unused)
(slot mouseY 'The y coordinate of the mouse pointer' Number readWrite Player getMouseY  unused unused)
(command roundUpStrays 'Bring all out-of-container subparts back into view.')
(slot numberAtCursor 'the Number at the cursor' Number readWrite Player getNumberAtCursor Player setNumberAtCursor: )
(slot playerAtCursor 'the object currently at the cursor' Player readWrite Player getValueAtCursor  unused unused)
(slot graphicAtCursor 'the graphic worn by the object at the cursor' Graphic readOnly Player getGraphicAtCursor  unused unused)
(command unhideHiddenObjects 'Unhide all hidden objects.')))

(collections (
(slot cursor 'The index of the chosen element' Number readWrite Player getCursor Player setCursorWrapped:)
(slot playerAtCursor 'the object currently at the cursor' Player readWrite Player getValueAtCursor  unused unused)
(slot firstElement  'The first object in my contents' Player  readWrite Player getFirstElement  Player  setFirstElement:)
(slot NumberAtCursor 'the number at the cursor' Number readWrite Player getNumberAtCursor Player setNumberAtCursor: )
(slot graphicAtCursor 'the graphic worn by the object at the cursor' Graphic readOnly Player getGraphicAtCursor  unused unused)
(command removeAll 'Remove all elements from the playfield')
(command shuffleContents 'Shuffle the contents of the playfield')
(command append: 'Add the object to my content' Player)
(command prepend: 'Add the object to my content' Player)
))

(#'stack navigation' (
(command goToNextCardInStack 'Go to the next card')
(command goToPreviousCardInStack  'Go to the previous card')
(command goToFirstCardInBackground 'Go to the first card of the current background')
(command goToFirstCardOfStack 'Go to the first card of the entire stack')
(command goToLastCardInBackground 'Go to the last card of the current background')
(command goToLastCardOfStack 'Go to the last card of the entire stack')
(command deleteCard 'Delete the current card')
(command insertCard 'Create a new card')))

(viewing (
(slot viewingNormally 'whether contents are viewed normally' Boolean readWrite Player getViewingByIcon Player setViewingByIcon: )))


(#'pen trails' (
(command liftAllPens 'Lift the pens on all the objects in my interior.')
(command lowerAllPens  'Lower the pens on all the objects in my interior.')
(command arrowheadsOnAllPens  'Put arrowheads on the ends of strokes of pens on all objects.')
(command noArrowheadsOnAllPens  'Stop putting arrowheads on the ends of strokes of pens on all objects.')
(command clearTurtleTrails 'Clear all the pen trails in the interior.'))))
! !


!Player methodsFor: 'slot getters/setters' stamp: 'kfr 1/21/2001 19:34'!
getKeyStroke
 ^self  costume getKeyStroke! !

!Player methodsFor: 'slot getters/setters' stamp: 'kfr 8/28/2002 16:30'!
getKeyStrokeAndFireScript
     self getKeyStroke.
	self fireOnce! !

!Player methodsFor: 'slot getters/setters' stamp: 'kfr 8/26/2002 10:58'!
getKeyboardFocus
	^ costume = ActiveHand keyboardFocus! !

!Player methodsFor: 'slot getters/setters' stamp: 'kfr 8/28/2002 16:29'!
setKeyboardFocus: aBoolean
	aBoolean
	ifTrue: [costume on: #keyStroke send: #getKeyStrokeAndFireScript to: self.
ActiveHand newKeyboardFocus: costume]
	ifFalse:[ActiveHand releaseKeyboardFocus]! !

!Player methodsFor: 'scripts-execution' stamp: 'kfr 8/27/2002 23:49'!
fireOnce
	"If the receiver has any script armed to be triggered on mouse down and/or mouse-up, run those scripts now -- first the mouseDown ones, then the mouseUp ones."

	self instantiatedUserScriptsDo:
		[:aScriptInst |
			aScriptInst status == #mouseDown ifTrue: [aScriptInst fireOnce]].
	self instantiatedUserScriptsDo:
		[:aScriptInst |
			aScriptInst status == #mouseUp ifTrue: [aScriptInst fireOnce]].
	self instantiatedUserScriptsDo:
		[:aScriptInst |
			aScriptInst status == #keyStroke ifTrue: [aScriptInst fireOnce]].

! !


!ScriptInstantiation methodsFor: 'status control' stamp: 'kfr 8/25/2002 00:10'!
presentScriptStatusPopUp
	"Put up a menu of status alternatives and carry out the request"

	| aMenu reply standardStati  m |
	"NB; the keyStroke branch commented out temporarily until keystrokes can actually be passed along to the user's scripting code"

	standardStati _ #(normal paused ticking mouseDown mouseStillDown mouseUp mouseEnter mouseLeave mouseEnterDragging mouseLeaveDragging opening closing keyStroke).
	aMenu _ SelectionMenu labelList:  #(
		'normal'		" -- run when called"		
		'paused' 		"ready to run all the time"
		'ticking'		"run all the time"
		'mouseDown'	"run when mouse goes down on me"
		'mouseStillDown'	"while mouse still down"
		'mouseUp'		"when mouse comes back up"
		'mouseEnter'	"when mouse enters my bounds, button up"
		'mouseLeave'	"when mouse exits my bounds, button up"
		'mouseEnterDragging'	"when mouse enters my bounds, button down"
		'mouseLeaveDragging'	"when mouse exits my bounds, button down"
		'opening'	"when I am being opened"
		'closing'	"when I am being closed"
		'keyStroke'	"run when user hits a key"
		'what do these mean?'
		'apply my status to all siblings'
		)
		lines: #(1 3 6 10 12 13)
		selections: (standardStati, #(explainStatusAlternatives assignStatusToAllSiblings)).

	reply _ aMenu startUpWithCaption: 'When should this script run?'.
	"(reply == #keyStroke) ifTrue: [^ self inform: 'user-scripted fielding
of keystrokes is not
yet available.']."

	reply == #explainStatusAlternatives ifTrue: [^ self explainStatusAlternatives].
	reply == #assignStatusToAllSiblings ifTrue: [^ self assignStatusToAllSiblings].
	reply ifNotNil: 
		[self status: reply.  "Gets event handlers fixed up"
		reply == #paused ifTrue:
			[m _ player costume.
			(m isKindOf: SpeakerMorph) ifTrue: [m stopSound]].
		self updateAllStatusMorphs]! !

PasteUpMorph removeSelector: #getKeyStroke!
PasteUpMorph removeSelector: #keyDown:!


More information about the Squeakland mailing list