228 "Created: / 23-07-2019 / 10:27:02 / Claus Gittinger" |
228 "Created: / 23-07-2019 / 10:27:02 / Claus Gittinger" |
229 ! ! |
229 ! ! |
230 |
230 |
231 !ShowMeHowItWorks methodsFor:'commands'! |
231 !ShowMeHowItWorks methodsFor:'commands'! |
232 |
232 |
|
233 freezePin:pinName ofStep:stepName with:freezeString |
|
234 <action> |
|
235 |
|
236 |diagramEditor pinPO| |
|
237 |
|
238 (diagramEditor := lastComponent) isScrollWrapper ifTrue:[ |
|
239 diagramEditor := lastComponent scrolledView |
|
240 ]. |
|
241 pinPO := diagramEditor |
|
242 detectPOForWhich:[:po | |
|
243 po isPin |
|
244 and:[ po name = pinName |
|
245 and:[ po owningStepPO name = stepName ]] |
|
246 ]. |
|
247 diagramEditor selection:{ pinPO }. |
|
248 diagramEditor doubleClickOn:pinPO. |
|
249 self fastMoveTo:(lastComponentName,'/','EditField'). |
|
250 self click. |
|
251 self type:freezeString. |
|
252 self key:#Return. |
|
253 ! |
|
254 |
233 intro |
255 intro |
234 <action> |
256 <action> |
235 |
257 |
236 verifying ifTrue:[^ self]. |
258 verifying ifTrue:[^ self]. |
237 |
259 |
649 |
700 |
650 "Created: / 19-07-2019 / 12:34:25 / Claus Gittinger" |
701 "Created: / 19-07-2019 / 12:34:25 / Claus Gittinger" |
651 "Modified (format): / 19-07-2019 / 14:55:34 / Claus Gittinger" |
702 "Modified (format): / 19-07-2019 / 14:55:34 / Claus Gittinger" |
652 ! |
703 ! |
653 |
704 |
|
705 fastMoveRelativeX:dX y:dY |
|
706 "move the mouse to a new relative position" |
|
707 |
|
708 <action> |
|
709 |
|
710 |screen newPos currentPos| |
|
711 |
|
712 verifying ifTrue:[^ self]. |
|
713 |
|
714 screen := Screen current. |
|
715 currentPos := screen pointerPosition. |
|
716 newPos := currentPos + (dX @ dY). |
|
717 self fastMovePointerToScreenPosition:newPos |
|
718 ! |
|
719 |
654 fastMoveTo:componentName |
720 fastMoveTo:componentName |
655 "move the mouse to componentName without circling" |
721 "move the mouse to componentName without circling" |
656 |
722 |
657 <action> |
723 <action> |
658 |
724 |
667 " |
733 " |
668 |
734 |
669 "Created: / 19-07-2019 / 15:39:23 / Claus Gittinger" |
735 "Created: / 19-07-2019 / 15:39:23 / Claus Gittinger" |
670 "Modified: / 20-07-2019 / 08:14:16 / Claus Gittinger" |
736 "Modified: / 20-07-2019 / 08:14:16 / Claus Gittinger" |
671 "Modified (comment): / 23-07-2019 / 09:33:31 / Claus Gittinger" |
737 "Modified (comment): / 23-07-2019 / 09:33:31 / Claus Gittinger" |
|
738 ! |
|
739 |
|
740 key:aKeySymbol |
|
741 "press/release a key" |
|
742 |
|
743 <action> |
|
744 |
|
745 |t| |
|
746 |
|
747 verifying ifTrue:[^ self]. |
|
748 |
|
749 t := Display ctrlDown ifTrue:[0.05] ifFalse:[0.1]. |
|
750 lastComponent |
|
751 simulateKey:aKeySymbol at:(lastComponent extent // 2) sendDisplayEvent:false keyPressTime:t |
|
752 |
|
753 "Created: / 19-07-2019 / 15:50:40 / Claus Gittinger" |
672 ! |
754 ! |
673 |
755 |
674 moveTo:componentName |
756 moveTo:componentName |
675 "move the mouse to componentName, |
757 "move the mouse to componentName, |
676 then circle around it a few times" |
758 then circle around it a few times" |
825 Delay waitForSeconds:0.1. |
907 Delay waitForSeconds:0.1. |
826 component simulateButtonRelease:1 at:(0 @ (yPos + 3)) sendDisplayEvent:false. |
908 component simulateButtonRelease:1 at:(0 @ (yPos + 3)) sendDisplayEvent:false. |
827 "/ component selection:idx. |
909 "/ component selection:idx. |
828 ^ self |
910 ^ self |
829 ]. |
911 ]. |
830 |
912 (component isKindOf:SelectionInListModelView) ifTrue:[ |
831 self error:'cannot select this component' |
913 |idx yPos| |
|
914 |
|
915 itemsIndexOrLabelOrPattern isInteger ifTrue:[ |
|
916 idx := itemsIndexOrLabelOrPattern |
|
917 ] ifFalse:[ |
|
918 itemsIndexOrLabelOrPattern includesMatchCharacters ifTrue:[ |
|
919 idx := component indexOfElementForWhich:[:el | el notNil and:[itemsIndexOrLabelOrPattern match:el string]]. |
|
920 ] ifFalse:[ |
|
921 idx := component indexOfElementForWhich:[:el | el notNil and:[el string = itemsIndexOrLabelOrPattern]]. |
|
922 ]. |
|
923 idx == 0 ifTrue:[ |
|
924 self error:'no such item in hierarchicalList: ',itemsIndexOrLabelOrPattern |
|
925 ]. |
|
926 ]. |
|
927 yPos := component yVisibleOfLine:idx. |
|
928 self movePointerToComponent:component offset:(0 @ (yPos + 3)). |
|
929 component simulateButtonPress:1 at:(0 @ (yPos + 3)) sendDisplayEvent:false. |
|
930 Delay waitForSeconds:0.1. |
|
931 component simulateButtonRelease:1 at:(0 @ (yPos + 3)) sendDisplayEvent:false. |
|
932 "/ component selection:idx. |
|
933 ^ self |
|
934 ]. |
|
935 |
|
936 (component isKindOf:ItemInView) ifTrue:[ |
|
937 component isMenuItem ifTrue:[ |
|
938 self movePointerToComponent:component. |
|
939 self halt. |
|
940 ]. |
|
941 ]. |
|
942 |
|
943 self error:('cannot select this component: %1' bindWith:component className) |
832 |
944 |
833 "Created: / 19-07-2019 / 12:34:25 / Claus Gittinger" |
945 "Created: / 19-07-2019 / 12:34:25 / Claus Gittinger" |
834 "Modified (format): / 19-07-2019 / 14:55:34 / Claus Gittinger" |
946 "Modified (format): / 19-07-2019 / 14:55:34 / Claus Gittinger" |
835 ! |
947 ! |
836 |
948 |
1154 findComponent:componentNameOrPath in:anApplicationOrViewOrMenuItem |
1266 findComponent:componentNameOrPath in:anApplicationOrViewOrMenuItem |
1155 "find a component by name inside an app or inside a view. |
1267 "find a component by name inside an app or inside a view. |
1156 Uses the NameKey of the spec, and optionally the label or modelKey. |
1268 Uses the NameKey of the spec, and optionally the label or modelKey. |
1157 Can return either a view or a menu item" |
1269 Can return either a view or a menu item" |
1158 |
1270 |
1159 |idxString idx app window component componentNameSymbol |
1271 |quoted idxString idx app window component componentNameSymbol |
1160 foundByName foundByHelpKey foundByTitle foundByLabel item |
1272 foundByName foundByHelpKey foundByTitle foundByLabel item |
1161 checkIfAllMenuItemsDoTheSame| |
1273 checkIfAllMenuItemsDoTheSame| |
1162 |
1274 |
1163 (componentNameOrPath includes:$/) ifTrue:[ |
1275 "/ split at "/"; |
1164 (idx := componentNameOrPath indexOf:$/) ~~ 0 ifTrue:[ |
1276 "/ but not if inside quotes |
1165 |containerName restPath container| |
1277 quoted := false. |
1166 |
1278 componentNameOrPath doWithIndex:[:ch :idx | |
1167 containerName := componentNameOrPath copyTo:idx-1. |
1279 ch == $" ifTrue:[ |
1168 restPath := componentNameOrPath copyFrom:idx+1. |
1280 quoted := quoted not. |
1169 container := self findComponent:containerName in:anApplicationOrViewOrMenuItem. |
1281 ] ifFalse:[ |
1170 container isNil ifTrue:[ ^ nil ]. |
1282 ((ch == $/) and:[quoted not]) ifTrue:[ |
1171 ^ self findComponent:restPath in:container |
1283 |containerName restPath container| |
|
1284 |
|
1285 containerName := componentNameOrPath copyTo:idx-1. |
|
1286 restPath := componentNameOrPath copyFrom:idx+1. |
|
1287 container := self findComponent:containerName in:anApplicationOrViewOrMenuItem. |
|
1288 container isNil ifTrue:[ ^ nil ]. |
|
1289 ^ self findComponent:restPath in:container |
|
1290 ] |
1172 ] |
1291 ] |
1173 ]. |
1292 ]. |
|
1293 |
|
1294 (anApplicationOrViewOrMenuItem isKindOf:ItemInView) ifTrue:[ |
|
1295 anApplicationOrViewOrMenuItem isMenuItem ifTrue:[ |
|
1296 ^ self findComponent:componentNameOrPath in:anApplicationOrViewOrMenuItem item submenu |
|
1297 ]. |
|
1298 ]. |
|
1299 |
1174 (componentNameOrPath startsWith:'item[') ifTrue:[ |
1300 (componentNameOrPath startsWith:'item[') ifTrue:[ |
1175 anApplicationOrViewOrMenuItem isMenu ifFalse:[ |
1301 anApplicationOrViewOrMenuItem isMenu ifFalse:[ |
1176 self assert:false message:'container is not a menu'. |
1302 self assert:false message:'container is not a menu'. |
1177 ]. |
1303 ]. |
1178 idxString := (componentNameOrPath withoutPrefix:'item[') withoutSuffix:']'. |
1304 idxString := (componentNameOrPath withoutPrefix:'item[') withoutSuffix:']'. |
1179 (idxString conform:#isDigit) ifTrue:[ |
1305 (idxString conform:#isDigit) ifTrue:[ |
1180 idx := Integer readFrom:idxString. |
1306 idx := Integer readFrom:idxString. |
1181 item := anApplicationOrViewOrMenuItem itemAtIndex:idx. |
1307 item := anApplicationOrViewOrMenuItem itemAtIndex:idx. |
1182 ] ifFalse:[ |
1308 ] ifFalse:[ |
1183 item := anApplicationOrViewOrMenuItem itemAt:idxString. |
1309 idxString := idxString withoutQuotes. |
1184 ]. |
1310 idxString includesMatchCharacters ifTrue:[ |
1185 self assert:item notNil. |
1311 item := |
|
1312 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
|
1313 (item nameKey matches: idxString) |
|
1314 or:[ (item textLabel matches: idxString) |
|
1315 or:[ (item value isSymbol and:[item value matches: idxString])]] |
|
1316 ] |
|
1317 ] ifFalse:[ |
|
1318 item := |
|
1319 anApplicationOrViewOrMenuItem itemForWhich:[:item | |
|
1320 item nameKey = idxString |
|
1321 or:[ item textLabel = idxString |
|
1322 or:[ (item value isSymbol and:[ item value = idxString ])]] |
|
1323 ] |
|
1324 ]. |
|
1325 ]. |
|
1326 self assert:item notNil message:('no menu item named "%1"' bindWith:idxString). |
1186 ^ ItemInView new view:anApplicationOrViewOrMenuItem item:item boundsInView:(item layout) |
1327 ^ ItemInView new view:anApplicationOrViewOrMenuItem item:item boundsInView:(item layout) |
1187 ]. |
1328 ]. |
1188 (componentNameOrPath startsWith:'tab[') ifTrue:[ |
1329 (componentNameOrPath startsWith:'tab[') ifTrue:[ |
1189 (anApplicationOrViewOrMenuItem isKindOf:NoteBookView) ifFalse:[ |
1330 (anApplicationOrViewOrMenuItem isKindOf:NoteBookView) ifFalse:[ |
1190 self assert:false message:'container is not a notebook'. |
1331 self assert:false message:'container is not a notebook'. |
1192 idxString := (componentNameOrPath withoutPrefix:'tab[') withoutSuffix:']'. |
1333 idxString := (componentNameOrPath withoutPrefix:'tab[') withoutSuffix:']'. |
1193 (idxString conform:#isDigit) ifTrue:[ |
1334 (idxString conform:#isDigit) ifTrue:[ |
1194 idx := Integer readFrom:idxString. |
1335 idx := Integer readFrom:idxString. |
1195 item := anApplicationOrViewOrMenuItem tabAtIndex:idx. |
1336 item := anApplicationOrViewOrMenuItem tabAtIndex:idx. |
1196 ] ifFalse:[ |
1337 ] ifFalse:[ |
|
1338 idxString := idxString withoutQuotes. |
1197 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab tabItem rawLabel = idxString]. |
1339 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab tabItem rawLabel = idxString]. |
1198 item isNil ifTrue:[ |
1340 item isNil ifTrue:[ |
1199 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab printableLabel = idxString]. |
1341 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab printableLabel = idxString]. |
1200 item isNil ifTrue:[ |
1342 item isNil ifTrue:[ |
1201 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab activeHelpKey = idxString]. |
1343 item := anApplicationOrViewOrMenuItem tabForWhich:[:tab | tab activeHelpKey = idxString]. |
1396 (aWidgetOrMenuItemOrTab askFor:#isMenuItem) ifTrue:[ |
1538 (aWidgetOrMenuItemOrTab askFor:#isMenuItem) ifTrue:[ |
1397 |menuPanel menuBounds| |
1539 |menuPanel menuBounds| |
1398 |
1540 |
1399 aWidgetOrMenuItemOrTab isVisible ifTrue:[ |
1541 aWidgetOrMenuItemOrTab isVisible ifTrue:[ |
1400 (itemLayout := aWidgetOrMenuItemOrTab layout) notNil ifTrue:[ |
1542 (itemLayout := aWidgetOrMenuItemOrTab layout) notNil ifTrue:[ |
1401 menuPanel := aWidgetOrMenuItemOrTab menuPanel. |
1543 menuPanel := aWidgetOrMenuItemOrTab view. |
1402 menuPanel shown ifTrue:[ |
1544 menuPanel shown ifTrue:[ |
1403 menuBounds := menuPanel screenBounds. |
1545 menuBounds := menuPanel screenBounds. |
1404 ^ itemLayout + menuBounds origin |
1546 ^ itemLayout + menuBounds origin |
1405 ]. |
1547 ]. |
1406 ]. |
1548 ]. |
1442 |
1584 |
1443 click:buttonNr inComponent:viewOrMenuItem clickTime:clickTime |
1585 click:buttonNr inComponent:viewOrMenuItem clickTime:clickTime |
1444 "press-release in a component" |
1586 "press-release in a component" |
1445 |
1587 |
1446 self withViewAndPositionFor:viewOrMenuItem do:[:viewToClick :clickPos | |
1588 self withViewAndPositionFor:viewOrMenuItem do:[:viewToClick :clickPos | |
1447 viewToClick simulateButtonPress:buttonNr at:clickPos sendDisplayEvent:false. |
1589 Display activePointerGrab == Display rootView ifTrue:[ |
1448 Delay waitForSeconds:clickTime. |
1590 |pos| |
1449 viewToClick simulateButtonRelease:buttonNr at:clickPos sendDisplayEvent:false. |
1591 |
|
1592 pos := Display translatePoint:clickPos fromView:viewToClick toView:nil. |
|
1593 OperatingSystem isOSXlike ifTrue:[ |
|
1594 OperatingSystem |
|
1595 generateMouseMoveEventX:pos x y:pos y; |
|
1596 generateButtonEvent:buttonNr down:true x:pos x y:pos y; |
|
1597 generateButtonEvent:buttonNr down:false x:pos x y:pos y; |
|
1598 generateButtonEvent:buttonNr down:true x:pos x y:pos y; |
|
1599 generateButtonEvent:buttonNr down:false x:pos x y:pos y. |
|
1600 ^ self. |
|
1601 ]. |
|
1602 Display rootView simulateButtonPress:buttonNr at:pos sendDisplayEvent:true. |
|
1603 Delay waitForSeconds:clickTime. |
|
1604 Display rootView simulateButtonRelease:buttonNr at:pos sendDisplayEvent:true. |
|
1605 ] ifFalse:[ |
|
1606 viewToClick simulateButtonPress:buttonNr at:clickPos sendDisplayEvent:false. |
|
1607 Delay waitForSeconds:clickTime. |
|
1608 viewToClick simulateButtonRelease:buttonNr at:clickPos sendDisplayEvent:false. |
|
1609 ]. |
1450 ]. |
1610 ]. |
1451 ! |
1611 ! |
1452 |
1612 |
1453 press:buttonNr inComponent:viewOrMenuItem |
1613 press:buttonNr inComponent:viewOrMenuItem |
1454 "press in a component" |
1614 "press in a component" |
1472 |viewToClick clickPos| |
1632 |viewToClick clickPos| |
1473 |
1633 |
1474 self assert:viewOrMenuItem notNil. |
1634 self assert:viewOrMenuItem notNil. |
1475 verifying ifTrue:[^ self]. |
1635 verifying ifTrue:[^ self]. |
1476 |
1636 |
1477 ((viewOrMenuItem askFor:#isMenuItem) |
1637 (viewOrMenuItem isKindOf:ItemInView) ifTrue:[ |
1478 or:[ (viewOrMenuItem askFor:#isNoteBookTab) ]) ifTrue:[ |
|
1479 viewToClick := viewOrMenuItem view. |
1638 viewToClick := viewOrMenuItem view. |
1480 clickPos := viewOrMenuItem layout center. |
1639 clickPos := viewOrMenuItem layout center. |
1481 self assert:(clickPos notNil). |
1640 self assert:(clickPos notNil). |
1482 ] ifFalse:[ |
1641 ] ifFalse:[ |
1483 viewToClick := viewOrMenuItem. |
1642 viewToClick := viewOrMenuItem. |
1636 |
1795 |
1637 screen := Screen current. |
1796 screen := Screen current. |
1638 start := screen pointerPosition. |
1797 start := screen pointerPosition. |
1639 |
1798 |
1640 distance := start dist:newPosition. |
1799 distance := start dist:newPosition. |
|
1800 distance = 0 ifTrue:[ |
|
1801 "/ already there |
|
1802 screen setPointerPosition:newPosition. "/ do it anyway, in case of rounding errors |
|
1803 ^ self |
|
1804 ]. |
|
1805 |
1641 moveTime := (distance / pixelsPerSecond) seconds. "/ time to move |
1806 moveTime := (distance / pixelsPerSecond) seconds. "/ time to move |
1642 stepDelayTime := self pointerAnimationDelay. "/ update every 50ms |
1807 stepDelayTime := self pointerAnimationDelay. "/ update every 50ms |
1643 |
1808 |
1644 numSteps := moveTime / stepDelayTime. |
1809 numSteps := moveTime / stepDelayTime. |
1645 numSteps = 0 ifTrue:[ |
1810 numSteps = 0 ifTrue:[ |
1646 "/ already there |
1811 "/ already there |
|
1812 screen setPointerPosition:newPosition. "/ do it anyway, in case of rounding errors |
1647 ^ self |
1813 ^ self |
1648 ]. |
1814 ]. |
1649 |
1815 |
1650 delta := (newPosition - start) / numSteps. |
1816 delta := (newPosition - start) / numSteps. |
1651 1 to:numSteps do:[:step | |
1817 1 to:numSteps do:[:step | |