12 |
12 |
13 'From Smalltalk/X, Version:2.10.5 on 4-may-1995 at 6:17:35 am'! |
13 'From Smalltalk/X, Version:2.10.5 on 4-may-1995 at 6:17:35 am'! |
14 |
14 |
15 Controller subclass:#ButtonController |
15 Controller subclass:#ButtonController |
16 instanceVariableNames:'enabled pressed active entered isTriggerOnDown autoRepeat |
16 instanceVariableNames:'enabled pressed active entered isTriggerOnDown autoRepeat |
17 repeatBlock initialDelay repeatDelay pressActionBlock |
17 repeatBlock initialDelay repeatDelay pressActionBlock |
18 releaseActionBlock isToggle' |
18 releaseActionBlock isToggle' |
19 classVariableNames:'' |
19 classVariableNames:'' |
20 poolDictionaries:'' |
20 poolDictionaries:'' |
21 category:'Interface-Support' |
21 category:'Interface-Support' |
22 ! |
22 ! |
23 |
23 |
37 " |
37 " |
38 ! |
38 ! |
39 |
39 |
40 version |
40 version |
41 " |
41 " |
42 $Header: /cvs/stx/stx/libwidg/ButtonController.st,v 1.7 1995-05-06 14:16:24 claus Exp $ |
42 $Header: /cvs/stx/stx/libwidg/ButtonController.st,v 1.8 1995-05-09 01:54:58 claus Exp $ |
43 " |
43 " |
44 ! |
44 ! |
45 |
45 |
46 documentation |
46 documentation |
47 " |
47 " |
48 ButtonControllers are used with buttons and handle all user interaction. |
48 ButtonControllers are used with buttons and handle all user interaction. |
49 These are automatically created when a Button is created, therefore no manual |
49 These are automatically created when a Button is created, therefore no manual |
50 action is required for creation. |
50 action is required for creation. |
|
51 In normal applications, you dont have to care for the controller; access to the |
|
52 controllers behavior is also possible via messages to the button. |
|
53 (setting actions, controlling autorepeat etc.) |
51 |
54 |
52 Instance variables: |
55 Instance variables: |
53 |
56 |
54 enabled <Boolean> pressing is allowed (default: true) |
57 enabled <Boolean> pressing is allowed (default: true) |
|
58 |
55 pressed <Boolean> true if currently pressed (read-only) |
59 pressed <Boolean> true if currently pressed (read-only) |
|
60 |
56 entered <Boolean> true if the cursor is currently in this view |
61 entered <Boolean> true if the cursor is currently in this view |
|
62 |
57 isTriggerOnDown <Boolean> controls if the action should be executed on |
63 isTriggerOnDown <Boolean> controls if the action should be executed on |
58 press or on release (default: on release). |
64 press or on release (default: on release). |
|
65 |
|
66 isToggle <Boolean> controls if the button should show toggle |
|
67 behavior (as opposed to one-shot behavior) |
|
68 |
59 pressActionBlock <Block> block to evaluate when pressed (default: noop) |
69 pressActionBlock <Block> block to evaluate when pressed (default: noop) |
|
70 |
60 releaseActionBlock <Block> block to evaluate when released (default: noop) |
71 releaseActionBlock <Block> block to evaluate when released (default: noop) |
|
72 |
61 autoRepeat <Boolean> auto-repeats when pressed long enough (default: false) |
73 autoRepeat <Boolean> auto-repeats when pressed long enough (default: false) |
|
74 |
62 initialDelay <Number> seconds till first auto-repeat (default: 0.2) |
75 initialDelay <Number> seconds till first auto-repeat (default: 0.2) |
|
76 |
63 repeatDelay <Number> seconds of repeat intervall (default: 0.025) |
77 repeatDelay <Number> seconds of repeat intervall (default: 0.025) |
|
78 |
64 repeatBlock <Block> block evaluated for auto-repeat (internal) |
79 repeatBlock <Block> block evaluated for auto-repeat (internal) |
|
80 |
65 active <Boolean> true during action evaluation (internal) |
81 active <Boolean> true during action evaluation (internal) |
66 " |
82 " |
67 ! ! |
83 ! ! |
68 |
84 |
69 !ButtonController class methodsFor:'defaults'! |
85 !ButtonController class methodsFor:'defaults'! |
246 |
263 |
247 buttonPress:button x:x y:y |
264 buttonPress:button x:x y:y |
248 |sym action| |
265 |sym action| |
249 |
266 |
250 (button == 1 or:[button == #select]) ifFalse:[ |
267 (button == 1 or:[button == #select]) ifFalse:[ |
251 ^ super buttonPress:button x:x y:y |
268 ^ super buttonPress:button x:x y:y |
252 ]. |
269 ]. |
253 |
270 |
254 enabled ifTrue:[ |
271 enabled ifTrue:[ |
255 isToggle ifTrue:[ |
272 isToggle ifTrue:[ |
256 self toggle. |
273 self toggle. |
257 ^ self |
274 ^ self |
258 ]. |
275 ]. |
259 |
276 |
260 pressed ifFalse:[ |
277 pressed ifFalse:[ |
261 pressed := true. |
278 pressed := true. |
262 view showActive. |
279 view showActive. |
263 |
280 |
264 (pressActionBlock notNil or:[model notNil]) ifTrue:[ |
281 (pressActionBlock notNil or:[model notNil]) ifTrue:[ |
265 " |
282 " |
266 force output - so that button is drawn correctly in case |
283 force output - so that button is drawn correctly in case |
267 of any long-computation (at high priority) |
284 of any long-computation (at high priority) |
268 " |
285 " |
269 view device synchronizeOutput. |
286 view device synchronizeOutput. |
270 ]. |
287 ]. |
271 |
288 |
272 active := true. |
289 self performAction. |
273 |
290 |
274 self performAction. |
291 autoRepeat ifTrue:[ |
275 |
292 Processor addTimedBlock:repeatBlock afterSeconds:initialDelay |
276 active := false. |
293 ] |
277 |
294 ] |
278 autoRepeat ifTrue:[ |
|
279 Processor addTimedBlock:repeatBlock afterSeconds:initialDelay |
|
280 ] |
|
281 ] |
|
282 ] |
295 ] |
283 ! |
296 ! |
284 |
297 |
285 buttonRelease:button x:x y:y |
298 buttonRelease:button x:x y:y |
286 "button was released - if enabled, perform releaseaction" |
299 "button was released - if enabled, perform releaseaction" |
287 |
300 |
288 |sym| |
301 |sym| |
289 |
302 |
290 (button == 1 or:[button == #select]) ifFalse:[ |
303 (button == 1 or:[button == #select]) ifFalse:[ |
291 ^ super buttonRelease:button x:x y:y |
304 ^ super buttonRelease:button x:x y:y |
292 ]. |
305 ]. |
293 |
306 |
294 isToggle ifTrue:[ |
307 isToggle ifTrue:[ |
295 ^ self |
308 ^ self |
296 ]. |
309 ]. |
297 |
310 |
298 pressed ifTrue:[ |
311 pressed ifTrue:[ |
299 autoRepeat ifTrue:[ |
312 autoRepeat ifTrue:[ |
300 Processor removeTimedBlock:repeatBlock |
313 Processor removeTimedBlock:repeatBlock |
301 ]. |
314 ]. |
302 pressed := false. |
315 pressed := false. |
303 view showPassive. |
316 view showPassive. |
304 |
317 |
305 enabled ifTrue:[ |
318 enabled ifTrue:[ |
306 " |
319 " |
307 only perform action if released within myself |
320 only perform action if released within myself |
308 " |
321 " |
309 ((x >= 0) |
322 ((x >= 0) |
310 and:[x <= view width |
323 and:[x <= view width |
311 and:[y >= 0 |
324 and:[y >= 0 |
312 and:[y <= view height]]]) ifTrue:[ |
325 and:[y <= view height]]]) ifTrue:[ |
313 (releaseActionBlock notNil or:[model notNil]) ifTrue:[ |
326 (releaseActionBlock notNil or:[model notNil]) ifTrue:[ |
314 " |
327 " |
315 force output - so that button is drawn correctly in case |
328 force output - so that button is drawn correctly in case |
316 of any long-computation (at high priority) |
329 of any long-computation (at high priority) |
317 " |
330 " |
318 view device synchronizeOutput. |
331 view device synchronizeOutput. |
319 ]. |
332 ]. |
320 |
333 |
321 active := true. |
334 self performAction. |
322 |
335 ] |
323 self performAction. |
336 ] |
324 |
|
325 active := false. |
|
326 ] |
|
327 ] |
|
328 ] |
337 ] |
329 ! |
338 ! |
330 |
339 |
331 pointerEnter:state x:x y:y |
340 pointerEnter:state x:x y:y |
332 "redraw with enteredColors if they differ from the normal colors" |
341 "mouse pointer entered my view. |
|
342 Redraw with enteredColors if they differ from the normal colors" |
333 |
343 |
334 entered := true. |
344 entered := true. |
335 pressed ifTrue:[ |
345 enabled ifTrue:[ |
336 " |
346 pressed ifTrue:[ |
337 reentered after a leave with mouse-button down; |
347 " |
338 restart autorepeating and/or if I am a button with |
348 reentered after a leave with mouse-button down; |
339 isTriggerOnDown, show active again. |
349 restart autorepeating and/or if I am a button with |
340 " |
350 triggerOnDown, show active again. |
341 enabled ifTrue:[ |
351 " |
342 autoRepeat ifTrue:[ |
352 autoRepeat ifTrue:[ |
343 Processor addTimedBlock:repeatBlock afterSeconds:initialDelay |
353 Processor addTimedBlock:repeatBlock afterSeconds:initialDelay |
344 ]. |
354 ]. |
345 isTriggerOnDown ifFalse:[ |
355 isTriggerOnDown ifFalse:[ |
346 view showActive. |
356 view showActive. |
347 ] |
357 ] |
348 ] |
358 ] ifFalse:[ |
349 ] ifFalse:[ |
|
350 enabled ifTrue:[ |
|
351 view redraw |
359 view redraw |
352 ] |
360 ] |
353 ] |
361 ] |
354 ! |
362 ! |
355 |
363 |
356 pointerLeave:state |
364 pointerLeave:state |
357 "redraw with normal colors if they differ from enteredColors" |
365 "mouse pointer left my view. |
|
366 Redraw with normal colors if they differ from enteredColors" |
358 |
367 |
359 entered := false. |
368 entered := false. |
360 pressed ifTrue:[ |
369 pressed ifTrue:[ |
361 " |
370 " |
362 leave with mouse-button down; |
371 leave with mouse-button down; |
377 ! |
386 ! |
378 |
387 |
379 performAction |
388 performAction |
380 |action| |
389 |action| |
381 |
390 |
|
391 " |
|
392 ST/X style actionBlock evaluation ... |
|
393 " |
382 pressed ifTrue:[ |
394 pressed ifTrue:[ |
383 action := pressActionBlock |
395 action := pressActionBlock |
384 ] ifFalse:[ |
396 ] ifFalse:[ |
385 action := releaseActionBlock |
397 action := releaseActionBlock |
386 ]. |
398 ]. |
387 action notNil ifTrue:[action value]. |
399 action notNil ifTrue:[ |
388 |
400 active := true. |
|
401 action numArgs == 0 ifTrue:[ |
|
402 action value |
|
403 ] ifFalse:[ |
|
404 action value:pressed |
|
405 ]. |
|
406 active := false. |
|
407 ]. |
|
408 |
|
409 " |
|
410 ST-80 style model notification ... |
|
411 " |
389 (isToggle |
412 (isToggle |
390 or:[(isTriggerOnDown and:[pressed]) |
413 or:[(isTriggerOnDown and:[pressed]) |
391 or:[isTriggerOnDown not and:[pressed not]]]) ifTrue:[ |
414 or:[isTriggerOnDown not and:[pressed not]]]) ifTrue:[ |
392 "the ST-80 way of doing things" |
415 "the ST-80 way of doing things" |
393 view notNil ifTrue:[ |
416 view notNil ifTrue:[ |
394 view sendChangeMessageWith:pressed. |
417 active := true. |
395 ]. |
418 view sendChangeMessageWith:pressed. |
|
419 active := false. |
|
420 ]. |
396 ]. |
421 ]. |
397 ! |
422 ! |
398 |
423 |
399 buttonMultiPress:button x:x y:y |
424 buttonMultiPress:button x:x y:y |
400 ^ self buttonPress:button x:x y:y |
425 ^ self buttonPress:button x:x y:y |
401 ! |
426 ! |
402 |
427 |
403 keyPress:key x:x y:y |
428 keyPress:key x:x y:y |
404 "only trigger, if I am the focusView of my group" |
429 "trigger on Return and space, if I am the focusView of my group |
405 |
430 (i.e. if I got an explicit focus)" |
406 |group| |
431 |
407 |
432 (key == #Return or:[key == Character space]) ifTrue:[ |
408 ((group := view windowGroup) notNil |
433 view hasFocus ifTrue:[ |
409 and:[group focusView == view]) ifTrue:[ |
|
410 (key == #Return or:[key == Character space]) ifTrue:[ |
|
411 "just simulate a buttonPress/release here." |
434 "just simulate a buttonPress/release here." |
412 self buttonPress:1 x:0 y:0. |
435 self buttonPress:1 x:0 y:0. |
413 self buttonRelease:1 x:0 y:0. |
436 self buttonRelease:1 x:0 y:0. |
414 ^ self. |
437 ^ self. |
415 ] |
438 ] |