6 |
6 |
7 Object subclass:#ShowMeHowItWorks |
7 Object subclass:#ShowMeHowItWorks |
8 instanceVariableNames:'application opStream streamStack lastComponentName lastComponent |
8 instanceVariableNames:'application opStream streamStack lastComponentName lastComponent |
9 lastResult voice translate language verifying |
9 lastResult voice translate language verifying |
10 closeApplicationWhenFinished defaultComponentWaitTime ui |
10 closeApplicationWhenFinished defaultComponentWaitTime ui |
11 theShowFile' |
11 theShowFile defaultElementTimeout' |
12 classVariableNames:'IntroShownCount DebugMode StartLabel' |
12 classVariableNames:'IntroShownCount DebugMode StartLabel' |
13 poolDictionaries:'' |
13 poolDictionaries:'' |
14 category:'Interface-Help' |
14 category:'Interface-Help' |
15 ! |
15 ! |
16 |
16 |
89 (waitFor: '<component>' timeout:seconds) |
89 (waitFor: '<component>' timeout:seconds) |
90 wait for a component to appear |
90 wait for a component to appear |
91 |
91 |
92 open 'nameOfAppModelClass' |
92 open 'nameOfAppModelClass' |
93 open an application (class) |
93 open an application (class) |
|
94 |
|
95 raise 'application' |
|
96 raise 'masterApplication' |
|
97 |
94 intro |
98 intro |
95 |
99 |
96 component naming: |
100 component naming: |
97 '<component>' can be: |
101 '<component>' can be: |
98 name of a component, as defined in the UI-spec's nameKey, |
102 name of a component, as defined in the UI-spec's nameKey, |
236 |diagramEditor pinPO| |
240 |diagramEditor pinPO| |
237 |
241 |
238 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
242 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
239 diagramEditor := lastComponent scrolledView |
243 diagramEditor := lastComponent scrolledView |
240 ]. |
244 ]. |
241 pinPO := diagramEditor |
245 pinPO := self pinPOForPin:pinName ofStep:stepName. |
242 detectPOForWhich:[:po | |
246 |
243 po isPin |
|
244 and:[ po name = pinName |
|
245 and:[ po owningStepPO name = stepName ]] |
|
246 ]. |
|
247 diagramEditor selection:{ pinPO }. |
247 diagramEditor selection:{ pinPO }. |
248 diagramEditor doubleClickOn:pinPO. |
248 diagramEditor doubleClickOn:pinPO. |
249 self fastMoveTo:(lastComponentName,'/','EditField'). |
249 self fastMoveTo:(lastComponentName,'/','EditField'). |
250 self click. |
250 self click. |
251 self type:freezeString. |
251 self type:freezeString. |
335 ! |
335 ! |
336 |
336 |
337 selectPin:pinName ofStep:stepName |
337 selectPin:pinName ofStep:stepName |
338 <action> |
338 <action> |
339 |
339 |
340 |diagramEditor pinPo| |
340 |diagramEditor pinPO| |
341 |
341 |
342 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
342 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
343 diagramEditor := lastComponent scrolledView |
343 diagramEditor := lastComponent scrolledView |
344 ]. |
344 ]. |
345 pinPo := diagramEditor |
345 pinPO := self pinPOForPin:pinName ofStep:stepName. |
346 detectPOForWhich:[:po | |
346 self movePointerToComponent:diagramEditor offset:pinPO frame center. |
347 po isPin |
347 diagramEditor selection:{ pinPO }. |
348 and:[ po name = pinName |
|
349 and:[ po owningStepPO name = stepName ]] |
|
350 ]. |
|
351 self movePointerToComponent:diagramEditor offset:pinPo frame center. |
|
352 diagramEditor selection:{ pinPo }. |
|
353 |
|
354 ! |
348 ! |
355 |
349 |
356 show:message |
350 show:message |
357 "showing (and speak) some message." |
351 "showing (and speak) some message." |
358 |
352 |
462 self show:(self randomThankYou). |
456 self show:(self randomThankYou). |
463 |
457 |
464 "Created: / 23-07-2019 / 10:50:43 / Claus Gittinger" |
458 "Created: / 23-07-2019 / 10:50:43 / Claus Gittinger" |
465 ! |
459 ! |
466 |
460 |
|
461 timeout:seconds |
|
462 <action> |
|
463 |
|
464 defaultElementTimeout := seconds. |
|
465 |
|
466 "Created: / 23-07-2019 / 10:27:02 / Claus Gittinger" |
|
467 ! |
|
468 |
467 wait:seconds |
469 wait:seconds |
468 <action> |
470 <action> |
469 |
471 |
470 verifying ifTrue:[^ self]. |
472 verifying ifTrue:[^ self]. |
471 DebugMode == true ifTrue:[^ self]. |
473 DebugMode == true ifTrue:[^ self]. |
477 ! |
479 ! |
478 |
480 |
479 waitFor:componentName timeout:seconds |
481 waitFor:componentName timeout:seconds |
480 <action> |
482 <action> |
481 |
483 |
482 |endTime| |
484 |endTime component| |
483 |
485 |
484 verifying ifTrue:[^ self]. |
486 verifying ifTrue:[^ self]. |
485 |
487 |
|
488 lastComponentName := componentName. |
486 endTime := Timestamp now + seconds. |
489 endTime := Timestamp now + seconds. |
487 [ |
490 [ |
488 (self findComponent:componentName inAllApplications:true ifMultiple:nil) notNil ifTrue:[ |
491 (component := self findComponent:componentName inAllApplications:true ifMultiple:nil) notNil ifTrue:[ |
|
492 lastComponent := component. |
489 ^ self |
493 ^ self |
490 ]. |
494 ]. |
491 Delay waitForSeconds:0.05. |
495 Delay waitForSeconds:0.1. |
492 Timestamp now > endTime ifTrue:[ |
496 Timestamp now > endTime ifTrue:[ |
493 self error:('component %1 not present after %2' bindWith:componentName with:seconds) |
497 self error:('component %1 not present after %2' bindWith:componentName with:seconds) |
494 ] |
498 ] |
495 ] loop |
499 ] loop |
496 ! ! |
500 ! ! |
497 |
501 |
498 !ShowMeHowItWorks methodsFor:'commands - checking'! |
502 !ShowMeHowItWorks methodsFor:'commands - checking'! |
499 |
503 |
500 isEmpty:componentName |
504 isEmpty:componentName |
|
505 "true if the addressed textview/field is empty. |
|
506 Leaves component in lastComponent" |
|
507 |
501 <action> |
508 <action> |
502 |
509 |
503 |component| |
510 |component| |
504 |
511 |
505 component := self componentNamed:componentName. |
512 component := self componentNamed:componentName. |
506 component isScrollWrapper ifTrue:[ component := component scrolledView ]. |
513 component isScrollWrapper ifTrue:[ component := component scrolledView ]. |
507 component isTextView ifTrue:[ |
514 component isTextView ifTrue:[ |
508 ^ component contents isEmptyOrNil |
515 ^ component contents isEmptyOrNil |
509 ] ifFalse:[ |
516 ]. |
510 self halt. |
517 self error:'isEmpty: unhandled (non-text) component type: ',component displayString. |
511 ]. |
|
512 self error:'isEmpty: unhandled component type: ',component displayString. |
|
513 |
518 |
514 "Created: / 19-07-2019 / 15:33:47 / Claus Gittinger" |
519 "Created: / 19-07-2019 / 15:33:47 / Claus Gittinger" |
515 ! |
520 ! |
516 |
521 |
517 unless:query do:actions |
522 unless:query do:actions |
528 ! ! |
533 ! ! |
529 |
534 |
530 !ShowMeHowItWorks methodsFor:'commands - mouse & keyboard'! |
535 !ShowMeHowItWorks methodsFor:'commands - mouse & keyboard'! |
531 |
536 |
532 clear |
537 clear |
533 "clear entry fields" |
538 "clear entry fields of last component" |
534 |
539 |
535 <action> |
540 <action> |
536 |
541 |
537 verifying ifTrue:[^ self]. |
542 verifying ifTrue:[^ self]. |
538 |
543 |
539 lastComponent contents:nil |
544 lastComponent contents:nil |
540 ! |
545 ! |
541 |
546 |
542 click |
547 click |
543 "press-release" |
548 "press-release in last component" |
544 |
549 |
545 <action> |
550 <action> |
546 |
551 |
547 ^ self click:1 inComponent:lastComponent |
552 ^ self click:1 inComponent:lastComponent |
548 |
553 |
549 "Created: / 19-07-2019 / 16:11:03 / Claus Gittinger" |
554 "Created: / 19-07-2019 / 16:11:03 / Claus Gittinger" |
550 ! |
555 ! |
551 |
556 |
552 click:buttonNr |
557 click:buttonNr |
553 "press-release" |
558 "press-release in last component" |
554 |
559 |
555 <action> |
560 <action> |
556 |
561 |
557 self assert:(buttonNr isInteger). |
562 self assert:(buttonNr isInteger). |
558 ^ self click:buttonNr inComponent:lastComponent |
563 ^ self click:buttonNr inComponent:lastComponent |
1206 "retrieve a component by name or report an error if not found. |
1214 "retrieve a component by name or report an error if not found. |
1207 Can return either a view or a menu item" |
1215 Can return either a view or a menu item" |
1208 |
1216 |
1209 |component| |
1217 |component| |
1210 |
1218 |
|
1219 verifying ifFalse:[ |
|
1220 self waitFor:componentName timeout:(defaultElementTimeout ? 1). |
|
1221 ^ lastComponent. |
|
1222 ]. |
|
1223 |
1211 lastComponentName := componentName. |
1224 lastComponentName := componentName. |
1212 |
1225 |
1213 component := self findComponent:componentName. |
1226 component := self findComponent:componentName. |
1214 component isNil ifTrue:[ |
1227 component isNil ifTrue:[ |
1215 self error:'no component found for: ',componentName mayProceed:verifying. |
1228 self error:'no component found for: ',componentName mayProceed:verifying. |
1308 ] ifFalse:[ |
1321 ] ifFalse:[ |
1309 idxString := idxString withoutQuotes. |
1322 idxString := idxString withoutQuotes. |
1310 idxString includesMatchCharacters ifTrue:[ |
1323 idxString includesMatchCharacters ifTrue:[ |
1311 item := |
1324 item := |
1312 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
1325 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
1313 (item nameKey matches: idxString) |
1326 (idxString match:(item nameKey ? '') ) |
1314 or:[ (item textLabel matches: idxString) |
1327 or:[ (idxString match:(item textLabel ? '')) |
1315 or:[ (item value isSymbol and:[item value matches: idxString])]] |
1328 or:[ (item value isSymbol and:[idxString match:(item value)])]] |
1316 ] |
1329 ] |
1317 ] ifFalse:[ |
1330 ] ifFalse:[ |
1318 item := |
1331 item := |
1319 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
1332 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
1320 item nameKey = idxString |
1333 item nameKey = idxString |
1321 or:[ item textLabel = idxString |
1334 or:[ item textLabel = idxString |
1394 ] on:MessageNotUnderstood do:[:ex | ]. |
1407 ] on:MessageNotUnderstood do:[:ex | ]. |
1395 ] |
1408 ] |
1396 ]. |
1409 ]. |
1397 foundIt ifFalse:[ |
1410 foundIt ifFalse:[ |
1398 each isMenu ifTrue:[ |
1411 each isMenu ifTrue:[ |
|
1412 |comp| |
|
1413 |
1399 (item := each detectItemForNameKey:componentNameSymbol) notNil ifTrue:[ |
1414 (item := each detectItemForNameKey:componentNameSymbol) notNil ifTrue:[ |
1400 foundByName add:item. foundIt := true |
1415 comp := ItemInView new view:each item:item boundsInView:(item layout). |
|
1416 foundByName add:comp. foundIt := true |
1401 ]. |
1417 ]. |
1402 foundIt ifFalse:[ |
1418 foundIt ifFalse:[ |
1403 (item := each detectItemForKey:componentNameSymbol) notNil ifTrue:[ |
1419 (item := each detectItemForKey:componentNameSymbol) notNil ifTrue:[ |
1404 foundByName add:item. foundIt := true |
1420 comp := ItemInView new view:each item:item boundsInView:(item layout). |
|
1421 foundByName add:comp. foundIt := true |
1405 ]. |
1422 ]. |
1406 foundIt ifFalse:[ |
1423 foundIt ifFalse:[ |
1407 (item := each detectItemForLabel:componentNameSymbol) notNil ifTrue:[ |
1424 (item := each detectItemForLabel:componentNameSymbol) notNil ifTrue:[ |
1408 foundByLabel add:item. foundIt := true |
1425 comp := ItemInView new view:each item:item boundsInView:(item layout). |
|
1426 foundByLabel add:comp. foundIt := true |
1409 ]. |
1427 ]. |
1410 ]. |
1428 ]. |
1411 ]. |
1429 ]. |
1412 ]. |
1430 ]. |
1413 ]. |
1431 ]. |
1420 |visibleItems| |
1438 |visibleItems| |
1421 |
1439 |
1422 (itemsFound conform:[:each | each askFor:#isMenuItem]) ifTrue:[ |
1440 (itemsFound conform:[:each | each askFor:#isMenuItem]) ifTrue:[ |
1423 (itemsFound collect:[:item | item itemValue]) asSet size == 1 ifTrue:[ |
1441 (itemsFound collect:[:item | item itemValue]) asSet size == 1 ifTrue:[ |
1424 "/ choose one which is visible, if possible |
1442 "/ choose one which is visible, if possible |
1425 visibleItems := itemsFound select:[:item | item menuPanel shown]. |
1443 visibleItems := itemsFound select:[:item | item view shown]. |
1426 visibleItems notEmpty ifTrue:[ |
1444 visibleItems notEmpty ifTrue:[ |
1427 ^ visibleItems first |
1445 ^ visibleItems first |
1428 ]. |
1446 ]. |
1429 ^ itemsFound first. |
1447 ^ itemsFound first. |
1430 ]. |
1448 ]. |
1525 " |
1543 " |
1526 |
1544 |
1527 "Created: / 19-07-2019 / 12:02:30 / Claus Gittinger" |
1545 "Created: / 19-07-2019 / 12:02:30 / Claus Gittinger" |
1528 "Modified: / 19-07-2019 / 16:44:30 / Claus Gittinger" |
1546 "Modified: / 19-07-2019 / 16:44:30 / Claus Gittinger" |
1529 "Modified (comment): / 23-07-2019 / 09:32:44 / Claus Gittinger" |
1547 "Modified (comment): / 23-07-2019 / 09:32:44 / Claus Gittinger" |
|
1548 ! |
|
1549 |
|
1550 pinPOForPin:pinName ofStep:stepName |
|
1551 |diagramEditor pinPO| |
|
1552 |
|
1553 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
|
1554 diagramEditor := lastComponent scrolledView |
|
1555 ]. |
|
1556 pinPO := diagramEditor |
|
1557 detectPOForWhich:[:po | |
|
1558 po isPin |
|
1559 and:[ po name = pinName |
|
1560 and:[ po owningStepPO name = stepName ]] |
|
1561 ]. |
|
1562 ^ pinPO |
1530 ! |
1563 ! |
1531 |
1564 |
1532 screenBoundsOfComponent:aWidgetOrMenuItemOrTab |
1565 screenBoundsOfComponent:aWidgetOrMenuItemOrTab |
1533 |itemLayout| |
1566 |itemLayout| |
1534 |
1567 |
1767 |
1800 |
1768 |bounds position| |
1801 |bounds position| |
1769 |
1802 |
1770 bounds := self screenBoundsOfComponent:aWidgetOrMenuItemOrTab. |
1803 bounds := self screenBoundsOfComponent:aWidgetOrMenuItemOrTab. |
1771 bounds isNil ifTrue:[ |
1804 bounds isNil ifTrue:[ |
1772 self error:'no bounds found for: ',aWidgetOrMenuItemOrTab printString. |
1805 self error:('no bounds found for: %1 (%2)' bindWith:lastComponentName with:aWidgetOrMenuItemOrTab printString). |
1773 ]. |
1806 ]. |
1774 position := bounds center rounded. |
1807 position := bounds center rounded. |
1775 self movePointerToScreenPosition:position speed:pixelsPerSecond. |
1808 self movePointerToScreenPosition:position speed:pixelsPerSecond. |
1776 |
1809 |
1777 "Created: / 20-07-2019 / 08:12:49 / Claus Gittinger" |
1810 "Created: / 20-07-2019 / 08:12:49 / Claus Gittinger" |