[squeak-dev] The Inbox: Morphic-mt.755.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Jan 26 14:34:23 UTC 2015


Marcel Taeumel uploaded a new version of Morphic to project The Inbox:
http://source.squeak.org/inbox/Morphic-mt.755.mcz

==================== Summary ====================

Name: Morphic-mt.755
Author: mt
Time: 26 January 2015, 3:33:59.723 pm
UUID: 2d4a39f5-5d85-d84e-bb0a-0d82257dd6c7
Ancestors: Morphic-mt.754

A keyboard event handler that supports multiple repeated key event processing. Normal #keyStroke: does not repeat if more than one key is pressed. Scenario: Multi-player Tetris. ^__^

The class comment includes instructions.

=============== Diff against Morphic-mt.754 ===============

Item was added:
+ Object subclass: #KeyboardEventHandler
+ 	instanceVariableNames: 'mutex pressedKeys longDelay shortDelay keyMap loop'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'Morphic-Events'!
+ 
+ !KeyboardEventHandler commentStamp: 'mt 1/26/2015 15:30' prior: 0!
+ I allow for simulating repetition behavior of multiple "key strokes" because normal Squeak/OS cannot do that.
+ 
+ HOW TO USE
+ ---
+ 
+ 1) Subclass a morph, create an instance of me, give me a #keyMap, and call #startLoop, e.g. in #intoWorld:.
+ 2) Overwrite #handleKeyDown: and #handleKeyUp: and pass the events to me via #keyDown: resp. #keyUp:.
+ 2a) Call #value on the return value of #keyDown: if not nil to process the first call back immediately.
+ 3) Don't forget to call #stopLoop in, e.g., #outOfWorld: of your morph.
+ 
+ You can play around with #delay: and #rate: .!

Item was added:
+ ----- Method: KeyboardEventHandler>>delay (in category 'accessing') -----
+ delay
+ 
+ 	^ longDelay!

Item was added:
+ ----- Method: KeyboardEventHandler>>delay: (in category 'accessing') -----
+ delay: milliseconds
+ 	"Time between first stroke and repetition."
+ 
+ 	mutex critical: [longDelay := milliseconds].!

Item was added:
+ ----- Method: KeyboardEventHandler>>fire: (in category 'running') -----
+ fire: keyValue
+ 
+ 	(keyMap at: keyValue ifAbsent: [])
+ 		ifNotNil: [:callback | WorldState addDeferredUIMessage: callback].!

Item was added:
+ ----- Method: KeyboardEventHandler>>initialize (in category 'initialization') -----
+ initialize
+ 
+ 	super initialize.
+ 	
+ 	mutex := Mutex new.
+ 	pressedKeys := IdentityDictionary new.
+ 	longDelay := 200. "ms"
+ 	shortDelay := 20. "ms"!

Item was added:
+ ----- Method: KeyboardEventHandler>>keyDown: (in category 'event handling') -----
+ keyDown: evt
+ 	"Returns the callback if any. Caller has to ensure immediate fire!!"
+ 
+ 	| result |
+ 	result := nil.
+ 	
+ 	mutex critical: [
+ 		pressedKeys at: evt keyValue ifAbsentPut: [
+ 			result := keyMap at: evt keyValue ifAbsent: [].
+ 			Time millisecondClockValue + longDelay]].
+ 
+ 	^ result!

Item was added:
+ ----- Method: KeyboardEventHandler>>keyMap (in category 'accessing') -----
+ keyMap
+ 
+ 	^ keyMap!

Item was added:
+ ----- Method: KeyboardEventHandler>>keyMap: (in category 'accessing') -----
+ keyMap: aKeyMap
+ 	"Maps actual key values to callbacks."
+ 
+ 	mutex critical: [keyMap := aKeyMap copy].!

Item was added:
+ ----- Method: KeyboardEventHandler>>keyUp: (in category 'event handling') -----
+ keyUp: evt
+ 
+ 	mutex critical: [
+ 		pressedKeys removeKey: evt keyValue ifAbsent: [] ].!

Item was added:
+ ----- Method: KeyboardEventHandler>>process (in category 'running') -----
+ process
+ 	"Look for callbacks to fire."
+ 
+ 	mutex critical: [
+ 		Time millisecondClockValue in: [:ms |
+ 			pressedKeys associationsDo: [:assoc |
+ 				ms >= assoc value ifTrue: [
+ 					self fire: assoc key.
+ 					assoc value: ms + shortDelay]]]].!

Item was added:
+ ----- Method: KeyboardEventHandler>>rate (in category 'accessing') -----
+ rate
+ 
+ 	^ 1000 // shortDelay!

Item was added:
+ ----- Method: KeyboardEventHandler>>rate: (in category 'accessing') -----
+ rate: strokesPerSecond
+ 
+ 	mutex critical: [shortDelay := 1000 // strokesPerSecond].!

Item was added:
+ ----- Method: KeyboardEventHandler>>startLoop (in category 'running') -----
+ startLoop
+ 
+ 	self stopLoop.
+ 	
+ 	loop := [ 
+ 		| delay |
+ 		delay := Delay forMilliseconds: 8.  	
+ 		[ self process. delay wait ] repeat ] fork.!

Item was added:
+ ----- Method: KeyboardEventHandler>>stopLoop (in category 'running') -----
+ stopLoop
+ 
+ 	loop ifNotNil: #terminate.
+ 	loop := nil.!



More information about the Squeak-dev mailing list