ShowMeHowItWorks.st
changeset 3799 bbb4c1dbce25
parent 3798 eafc4c1bb53e
child 3800 fb1763b613bf
equal deleted inserted replaced
3798:eafc4c1bb53e 3799:bbb4c1dbce25
     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
   560     "Created: / 19-07-2019 / 13:21:20 / Claus Gittinger"
   565     "Created: / 19-07-2019 / 13:21:20 / Claus Gittinger"
   561     "Modified: / 19-07-2019 / 16:10:19 / Claus Gittinger"
   566     "Modified: / 19-07-2019 / 16:10:19 / Claus Gittinger"
   562 !
   567 !
   563 
   568 
   564 clickIn:componentName
   569 clickIn:componentName
   565     "press-release"
   570     "press-release.
       
   571      Leaves component in lastComponent"
   566     
   572     
   567     <action>
   573     <action>
   568 
   574 
   569     ^ self click:1 inComponent:(self componentNamed:componentName)
   575     ^ self click:1 inComponent:(self componentNamed:componentName)
   570 
   576 
   716     newPos := currentPos + (dX @ dY).
   722     newPos := currentPos + (dX @ dY).
   717     self fastMovePointerToScreenPosition:newPos
   723     self fastMovePointerToScreenPosition:newPos
   718 !
   724 !
   719 
   725 
   720 fastMoveTo:componentName
   726 fastMoveTo:componentName
   721     "move the mouse to componentName without circling"
   727     "move the mouse to componentName without circling.
       
   728      Leaves component in lastComponent"
   722 
   729 
   723     <action>
   730     <action>
   724 
   731 
   725     |component|
   732     |component|
   726 
   733 
   736     "Modified: / 20-07-2019 / 08:14:16 / Claus Gittinger"
   743     "Modified: / 20-07-2019 / 08:14:16 / Claus Gittinger"
   737     "Modified (comment): / 23-07-2019 / 09:33:31 / Claus Gittinger"
   744     "Modified (comment): / 23-07-2019 / 09:33:31 / Claus Gittinger"
   738 !
   745 !
   739 
   746 
   740 key:aKeySymbol
   747 key:aKeySymbol
   741     "press/release a key"
   748     "press/release a key in last component"
   742 
   749 
   743     <action>
   750     <action>
   744 
   751 
   745     |t|
   752     |t|
   746 
   753 
   753     "Created: / 19-07-2019 / 15:50:40 / Claus Gittinger"
   760     "Created: / 19-07-2019 / 15:50:40 / Claus Gittinger"
   754 !
   761 !
   755 
   762 
   756 moveTo:componentName
   763 moveTo:componentName
   757     "move the mouse to componentName,
   764     "move the mouse to componentName,
   758      then circle around it a few times"
   765      then circle around it a few times.
       
   766      Leaves component in lastComponent"
   759 
   767 
   760     <action>
   768     <action>
   761 
   769 
   762     |component|
   770     |component|
   763 
   771 
   771 !
   779 !
   772 
   780 
   773 press:buttonNr
   781 press:buttonNr
   774     <action>
   782     <action>
   775 
   783 
   776     "press at the current position"
   784     "press at the current position in last component"
   777 
   785 
   778     self assert:(buttonNr isInteger).
   786     self assert:(buttonNr isInteger).
   779     ^ self press:buttonNr inComponent:lastComponent.
   787     ^ self press:buttonNr inComponent:lastComponent.
   780 
   788 
   781 "/    "press at the current position"
   789 "/    "press at the current position"
   809 !
   817 !
   810 
   818 
   811 release:buttonNr
   819 release:buttonNr
   812     <action>
   820     <action>
   813 
   821 
   814     "release at the current position"
   822     "release at the current position in last component"
   815     
   823     
   816     <action>
   824     <action>
   817 
   825 
   818     self assert:(buttonNr isInteger).
   826     self assert:(buttonNr isInteger).
   819     ^ self press:buttonNr inComponent:lastComponent.
   827     ^ self press: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"
  2259 
  2292 
  2260 item
  2293 item
  2261     ^ item
  2294     ^ item
  2262 !
  2295 !
  2263 
  2296 
       
  2297 itemValue
       
  2298     ^ item itemValue
       
  2299 !
       
  2300 
  2264 layout
  2301 layout
  2265     ^ item layout
  2302     ^ item layout
  2266 !
  2303 !
  2267 
  2304 
  2268 view
  2305 view