--- a/ShowMeHowItWorks.st Thu Feb 20 15:49:39 2020 +0100
+++ b/ShowMeHowItWorks.st Fri Feb 21 18:31:56 2020 +0100
@@ -104,6 +104,11 @@
)
!
+example3
+ ShowMeHowItWorks new
+ doShowFile:'../../../exept/expecco/resources/shows/Browser_overview_en' asFilename
+!
+
scriptFormat
"
@@ -289,12 +294,6 @@
!ShowMeHowItWorks methodsFor:'commands'!
-closeApplication
- <action>
-
- application closeRequest.
-!
-
freezePin:pinName ofStep:stepName with:freezeString
<action>
@@ -318,6 +317,32 @@
self key:#Return.
!
+goto:nameOfLabel
+ <action>
+
+ "/ leaves opStream positioned after label: nameOfLabel
+ |savedPosition found|
+
+ savedPosition := opStream position.
+ opStream position:0.
+
+ "/ skip for that label
+ found := false.
+ [ found ] whileFalse:[
+ |cmd|
+
+ cmd := opStream nextOrNil.
+ cmd isNil ifTrue:[
+ opStream position:savedPosition.
+ self proceedableError:'label not found: ',nameOfLabel.
+ ^ self.
+ ].
+ (cmd = 'label:') ifTrue:[
+ found := (opStream next = nameOfLabel)
+ ].
+ ].
+!
+
intro
<action>
@@ -354,22 +379,6 @@
"Created: / 23-07-2019 / 10:27:02 / Claus Gittinger"
!
-open:applicationClassName
- <action>
-
- |appClass|
-
- (appClass := Smalltalk classNamed:applicationClassName) isNil ifTrue:[
- self error:'no such application class'
- ].
- verifying ifFalse:[
- application := appClass new openAndWaitUntilVisible.
- closeApplicationWhenFinished := true.
- ].
-
- "Created: / 19-07-2019 / 15:09:45 / Claus Gittinger"
-!
-
pause
<action>
@@ -380,14 +389,6 @@
"Modified: / 19-07-2019 / 16:13:33 / Claus Gittinger"
!
-popApplication
- <action>
-
- "go back to the previous app"
-
- application := applicationStack removeLast.
-!
-
pronounce:word as:pronunciation
<action>
@@ -397,27 +398,6 @@
pronunciations at:word put:pronunciation
!
-pushApplication:newApplicationOrName
- <action>
-
- "goto another app, remembering where we were before"
-
- |newApplication|
-
- (newApplication := newApplicationOrName) isString ifTrue:[
- newApplication := self findApplication:newApplicationOrName ifMultiple:nil.
- newApplication isNil ifTrue:[
- self error:('Could not find an application named "%1" (to switch to)' bindWith:newApplicationOrName).
- ].
- "/ self assert: newApplication notNil.
- ].
-
- applicationStack isNil ifTrue:[applicationStack := OrderedCollection new].
-
- applicationStack add:application.
- self application:newApplication.
-!
-
raise:what
<action>
@@ -656,6 +636,73 @@
] loop
! !
+!ShowMeHowItWorks methodsFor:'commands - application'!
+
+closeApplication
+ <action>
+
+ application closeRequest.
+!
+
+open:applicationClassName
+ <action>
+
+ |appClass|
+
+ (appClass := Smalltalk classNamed:applicationClassName) isNil ifTrue:[
+ self error:'no such application class'
+ ].
+ verifying ifFalse:[
+ application := appClass new openAndWaitUntilVisible.
+ closeApplicationWhenFinished := true.
+ ].
+
+ "Created: / 19-07-2019 / 15:09:45 / Claus Gittinger"
+!
+
+popApplication
+ <action>
+
+ "go back to the previous app"
+
+ application := applicationStack removeLast.
+!
+
+pushApplication:newApplicationOrName
+ <action>
+
+ "goto another app, remembering where we were before"
+
+ |newApplication|
+
+ (newApplication := newApplicationOrName) isString ifTrue:[
+ newApplication := self findApplication:newApplicationOrName ifMultiple:nil.
+ newApplication isNil ifTrue:[
+ self error:('Could not find an application named "%1" (to switch to)' bindWith:newApplicationOrName).
+ ].
+ "/ self assert: newApplication notNil.
+ ].
+
+ applicationStack isNil ifTrue:[applicationStack := OrderedCollection new].
+
+ applicationStack add:application.
+ self application:newApplication.
+!
+
+useApplication:classNameOrWindowTitle
+ <action>
+
+ "find an application by name and return it (useful as arg to application)"
+
+ application :=
+ self
+ findApplication:classNameOrWindowTitle
+ ifMultiple:[
+ self error:('multiple applications named "%1"' bindWith:classNameOrWindowTitle).
+ nil
+ ]
+! !
+
!ShowMeHowItWorks methodsFor:'commands - checking'!
isEmpty:componentName
@@ -738,6 +785,10 @@
<action>
+ (self componentNamed:componentName) == lastComponent ifFalse:[
+ self fastMoveTo:componentName.
+ self wait:0.25.
+ ].
^ self click:1 inComponent:(self componentNamed:componentName)
"Created: / 19-07-2019 / 16:09:58 / Claus Gittinger"
@@ -874,6 +925,21 @@
"Modified (format): / 19-07-2019 / 14:55:34 / Claus Gittinger"
!
+fastMoveAbsolute:pos
+ "move the mouse to a new position within the current component"
+
+ <action>
+
+ |screen newPos currentPos|
+
+ verifying ifTrue:[^ self].
+
+ screen := Screen current.
+ currentPos := screen pointerPosition.
+ newPos := currentPos + pos.
+ self fastMovePointerToScreenPosition:newPos
+!
+
fastMoveRelativeX:dX y:dY
"move the mouse to a new relative position"
@@ -890,7 +956,7 @@
!
fastMoveTo:componentName
- "move the mouse to componentName without circling.
+ "move the mouse to the center of componentName without circling.
Leaves component in lastComponent"
<action>
@@ -910,6 +976,20 @@
"Modified (comment): / 23-07-2019 / 09:33:31 / Claus Gittinger"
!
+fastMoveTo:componentName at:positionOrSymbol
+ "move the mouse to a new position within the current component"
+
+ <action>
+
+ |newPos component|
+
+ component := self componentNamed:componentName.
+ (newPos := positionOrSymbol) isSymbol ifTrue:[
+ newPos := self where:positionOrSymbol inComponent:component.
+ ].
+ self fastMovePointerToComponent:component at:newPos
+!
+
key:aKeySymbol
"press/release a key in last component"
@@ -1490,7 +1570,7 @@
!
findApplication:classNameOrWindowTitle ifMultiple:exceptionalValue
- "find an application by name"
+ "find an application by name and return it (useful as arg to application)"
|candidates|
@@ -1927,9 +2007,11 @@
|t|
t := self shortClickTime.
+
+ "/ longer click time for Buttons and Menus, to allow redraw to be seen
((component isKindOf:Button)
or:[(component askFor:#isMenuItem)]
- )ifTrue:[
+ ) ifTrue:[
t := self longClickTime
].
self click:buttonNr inComponent:component clickTime:t
@@ -1944,12 +2026,15 @@
self withViewAndPositionFor:viewOrMenuItem do:[:viewToClick :clickPos |
|clickDone|
+ Transcript showCR:'click pos is %1' with:clickPos.
+
clickDone := false.
Display activePointerGrab == Display rootView ifTrue:[
|pos|
pos := Display translatePoint:clickPos fromView:viewToClick toView:nil.
Error handle:[:ex |
+ Transcript showCR:'failed to click (unupported in OS?)'
] do:[
OperatingSystem isOSXlike ifTrue:[
OperatingSystem
@@ -1964,12 +2049,16 @@
yourself.
^ self.
].
+ ].
+ Display ungrabPointer.
+ false ifFalse:[
Display rootView simulateButtonPress:buttonNr at:pos sendDisplayEvent:true.
Delay waitForSeconds:clickTime.
Display rootView simulateButtonRelease:buttonNr at:pos sendDisplayEvent:true.
clickDone := true.
].
].
+
clickDone ifFalse:[
viewToClick simulateButtonPress:buttonNr at:clickPos sendDisplayEvent:false.
Delay waitForSeconds:clickTime.
@@ -2073,6 +2162,27 @@
"Created: / 23-07-2019 / 09:37:46 / Claus Gittinger"
!
+fastMovePointerToComponent:aWidgetOrMenuItem
+ "move the mouse to a widget's center"
+
+ |bounds|
+
+ bounds := self screenBoundsOfComponent:aWidgetOrMenuItem.
+ self fastMovePointerToScreenPosition:(bounds center rounded).
+
+ "Created: / 19-07-2019 / 13:11:33 / Claus Gittinger"
+ "Modified: / 23-07-2019 / 09:37:01 / Claus Gittinger"
+!
+
+fastMovePointerToComponent:aWidgetOrMenuItem at:offset
+ "move the mouse to a widget's center"
+
+ |bounds|
+
+ bounds := self screenBoundsOfComponent:aWidgetOrMenuItem.
+ self fastMovePointerToScreenPosition:(bounds origin + offset).
+!
+
fastMovePointerToScreenPosition:position
self movePointerToScreenPosition:position speed:(self pointerMoveSpeedFast).
@@ -2080,7 +2190,7 @@
!
movePointerToComponent:aWidgetOrMenuItem
- "move the mouse to aWidget's center"
+ "move the mouse to a widget's center"
|bounds|
@@ -2091,8 +2201,33 @@
"Modified: / 23-07-2019 / 09:37:01 / Claus Gittinger"
!
+movePointerToComponent:aWidgetOrMenuItem at:offset
+ "move the mouse to a widget's center"
+
+ |bounds|
+
+ bounds := self screenBoundsOfComponent:aWidgetOrMenuItem.
+ self movePointerToScreenPosition:(bounds origin + offset).
+!
+
+movePointerToComponent:aWidgetOrMenuItemOrTab at:offset speed:pixelsPerSecond
+ "move the mouse to a position within a widget"
+
+ |bounds position|
+
+ bounds := self screenBoundsOfComponent:aWidgetOrMenuItemOrTab.
+ bounds isNil ifTrue:[
+ self error:('no bounds found for: %1 (%2)' bindWith:lastComponentName with:aWidgetOrMenuItemOrTab printString).
+ ].
+ position := bounds origin + offset.
+ self movePointerToScreenPosition:position speed:pixelsPerSecond.
+
+ "Created: / 20-07-2019 / 08:12:49 / Claus Gittinger"
+ "Modified: / 23-07-2019 / 09:37:27 / Claus Gittinger"
+!
+
movePointerToComponent:aWidgetOrMenuItem offset:offset
- "move the mouse to position inside aWidget's"
+ "move the mouse to position inside a widget"
|bounds|
@@ -2104,7 +2239,7 @@
!
movePointerToComponent:aWidgetOrMenuItem rightBottomOffset:offset
- "move the mouse to position inside aWidget's.
+ "move the mouse to position inside a widget.
Offset is from the rightBottom"
|bounds|
@@ -2117,7 +2252,7 @@
!
movePointerToComponent:aWidgetOrMenuItem rightOffset:offset
- "move the mouse to position inside aWidget's.
+ "move the mouse to position inside a widget.
Offset is from the rightTop (i.e. x is subtracted, y is added)"
|bounds pos|
@@ -2131,7 +2266,7 @@
!
movePointerToComponent:aWidgetOrMenuItemOrTab speed:pixelsPerSecond
- "move the mouse to aWidget's center"
+ "move the mouse to a widget's center"
|bounds position|
@@ -2147,7 +2282,7 @@
!
movePointerToScreenPosition:newPosition
- "move the mouse to newPosition"
+ "move the mouse to a new screenPosition"
self movePointerToScreenPosition:newPosition speed:(self pointerMoveSpeed)
@@ -2165,7 +2300,7 @@
start := screen pointerPosition.
distance := start dist:newPosition.
- distance = 0 ifTrue:[
+ distance < 10 ifTrue:[
"/ already there
screen setPointerPosition:newPosition. "/ do it anyway, in case of rounding errors
^ self
@@ -2196,32 +2331,35 @@
!
where:where inComponent:aComponent
+ |bounds|
+
+ bounds := aComponent bounds.
where == #center ifTrue:[
- ^ aComponent center
+ ^ bounds center rounded
].
where == #leftCenter ifTrue:[
- ^ aComponent leftCenter + (5@0).
+ ^ bounds leftCenter rounded + (5@0).
].
where == #rightCenter ifTrue:[
- ^ aComponent rightCenter - (5@0).
+ ^ bounds rightCenter rounded - (5@0).
].
where == #topLeft ifTrue:[
- ^ aComponent topLeft + (5@5).
+ ^ bounds topLeft + (5@5).
].
where == #topCenter ifTrue:[
- ^ aComponent topCenter + (0@5).
+ ^ bounds topCenter rounded + (0@5).
].
where == #topRight ifTrue:[
- ^ aComponent topRight - (5@5).
+ ^ bounds topRight - (5@5).
].
where == #bottomCenter ifTrue:[
- ^ aComponent bottomCenter - (0 @ 5)
+ ^ bounds bottomCenter rounded - (0 @ 5)
].
where == #bottomLeft ifTrue:[
- ^ aComponent bottomLeft + (5 @ -5)
+ ^ bounds bottomLeft + (5 @ -5)
].
where == #bottomRight ifTrue:[
- ^ aComponent bottomLeft - (5 @ 5)
+ ^ bounds bottomLeft - (5 @ 5)
].
self error:'where is this'
! !
@@ -2323,18 +2461,27 @@
"Modified: / 25-07-2019 / 11:48:53 / Claus Gittinger"
!
-doShowFile:aFilename
- "the file from which the show was loaded"
-
- |spec|
-
- theShowFile := aFilename.
- aFilename readingFileWithEncoding:#utf8 do:[:s |
+doShowFile:aFilenameOrDirectory
+ "the file from which the show was loaded.
+ aFilenameOrDirectory must be either a show file,
+ or a folder containing start.show"
+
+ |spec startFile|
+
+ aFilenameOrDirectory isDirectory ifTrue:[
+ "/ look for a start.show in there
+ (startFile := aFilenameOrDirectory / 'start.show') exists ifTrue:[
+ self doShowFile:startFile.
+ ^ self.
+ ].
+ self error:'no "startFile" in show''s folder'.
+ ].
+
+ theShowFile := aFilenameOrDirectory.
+ aFilenameOrDirectory readingFileWithEncoding:#utf8 do:[:s |
spec := Array readFrom:s.
].
self do:spec.
-
-
!
prepare
@@ -2525,22 +2672,7 @@
opStream := specStream.
startLabelOrNil notNil ifTrue:[
- |found|
-
- "/ skip for that label
- found := false.
- [ found ] whileFalse:[
- |cmd|
-
- cmd := opStream nextOrNil.
- cmd isNil ifTrue:[
- self proceedableError:'label not found: ',startLabelOrNil.
- ^ self.
- ].
- (cmd = 'label:') ifTrue:[
- found := (opStream next = startLabelOrNil)
- ].
- ].
+ self goto:startLabelOrNil
].
[opStream atEnd] whileFalse:[