One of our customers asked us how she could cascade VA Smalltalk windows. Our crack gui guy Lee whipped up this answer.
Add the method below to OSShell, then execute the workspace code. If you decide to create a method from the workspace code, be sure to remove the references to Transcript.
----------------------------------------------METHOD
TO
ADD---------------------------------------------------------------------------------------------------------------------
OSShell>>moveTo: anXY ifOffscreen: aBlock
"Private - Move the receiver on the display using the
current width and height and including the window
trimmings.
If moving the window to anXY location makes any portion
of the window go offscreen, then the 1-arg block @aBlock
is activated.
Arguments:
anXY - <Point> requested x,y upper-left location to move the shell to
aBlock - <Block> 1-arg block with anXY <Point> argument which is the
proposed x,y upper-left location that makes the window go offscreen
The block should answer a new x,y <Point> which is assummed to be
a better alternative xy location. Note that the block is only activated once"
| rect nX nY nWidth nHeight adjustedXY displayRectangle xyRectangle |
handle getWindowRect: (rect := OSRect new).
nWidth := rect right - rect left.
nHeight := rect bottom - rect top.
nX := anXY x max: 0.
nY := anXY y max: 0.
displayRectangle := Rectangle origin: [hidden email] corner: DisplayWidth @ DisplayHeight.
xyRectangle := Rectangle origin: anXY extent: nWidth @ nHeight.
(xyRectangle areasOutside: displayRectangle) notEmpty
ifTrue: [
adjustedXY := aBlock value: anXY copy.
nX := adjustedXY x max: 0.
nY := adjustedXY y max: 0].
handle moveWindow: nX nTop: nY nWidth: nWidth nHeight: nHeight fRepaint: true.
self updateRect
--------------------------------------WORKSPACE---------------------------------------------------------------------------------------------
"Cascading windows script"
| x y shellsToCascade xSlide xIncrement yIncrement xSlideIncrement |
"Initial Cascade Location - Top-Left"
x := 0.
y := 0.
"Slide takes effect when the lower-right of cascading windows begin to go offscreen, then we reset to 0,0
but 'slide' the x left by the slide increment * the number of slides"
xSlide := 0.
xSlideIncrement := 50.
"Controls the new x,y increment when cascading a window."
xIncrement := 10.
yIncrement := 10.
"All VA Shells"
shellsToCascade := CwShell allShells.
"Choose only top-level shells that are visible - Skip the transcript as we add that to the front afterwards"
shellsToCascade := shellsToCascade select: [:cwShell | cwShell
isTopLevelShell and: [cwShell isMapped and: [cwShell ~~ Transcript
shell]]].
"Prefer larger windows to start cascading as far left as possible to avoid xSlides"
shellsToCascade sort: [:shellA :shellB | shellA preferredExtent > shellB preferredExtent].
"Add the transcript to the front so it will be at the top-left of the screen"
shellsToCascade addFirst: Transcript shell.
"Cascade the windows.
Each window is cascaded using the computed xy values that increment for each cascade
A cascade may force some part of the window to be offscreen, in this case we reset the xy
positions, but slide the x to the right by some increment. This will provide 'columns' of cascaded
windows in there are a sufficiently large number of windows"
shellsToCascade do: [:cwShell |
(cwShell isTopLevelShell and: [cwShell isMapped]) ifTrue: [
cwShell osWidget
moveTo: x @ y ifOffscreen: [:anXY |
"Supplied cascade position made the window go offscreen.
Increment the slide amount, and reset
Answer the new adjusted xy"
xSlide := xSlide + 1.
x := xSlide * xSlideIncrement.
y := 0.
x @ y];
bringToTop.
x := x + xIncrement.
y := y + yIncrement.
]]