Help - Environment - Workspaces - 4

Previous - Workspaces.

4.1. Workspaces general commands
4.2. Workspaces and their variables
4.3. Getting text for Workspaces
4.4. Getting input

4.5. Using your own menus
4.6. Some fun bits
4.7. Addressing the OS with Squeak
4.8. Playing with morphs on screen

4.1. Workspaces general commands

To start with here is a bit of code to open your very own workspace. Do so, and we will use it in what follows:

(Workspace new contents: self) openLabel: 'Experimental workspace'. "Opens a new workspace with a title"

Next, it is nice to know what is possible in a workspace. Try this, and perhaps copy it to Experimental workspace:

Utilities openCommandKeyHelp.
"A workspace with a list of keys active in it".

To know these keys is very helpful. You can check them out in the workspace produced by the above.

Then there is a workspace available with some code-snippets you can try out:

Utilities openStandardWorkspace.
"A workspace with useful code-snippets to run"

4.2. Workspaces and their variables

A workspace in Squeak is a morphic object or morphs composed of several morphs. If you open a new Workspace; add the following in it (copy and paste is the easiest); and cmd-i the code, you'll have a workspace and an inspector on the OrderedCollection you made

-- begin of copy into a new Experimental workspace (see above)

coll := OrderedCollection new.
coll add: 'Gee, that is funny'.
coll add: 'Is that really true?'.
coll inspect.

var := 100.

and then click up the halos on the Workspace, and use from the debug halo inspect model to get an inspector on part of the Workspace that includes an item called bindings, in which you see the above two items you just made.

These are the variables of the Workspace. You can add more in the same way, such as

number1 := 2 raisedTo: 4.
number2 := 2.

after which you can do calculations in that Workspace like

(number1*number2) / var

As long as you keep the inspector on the model of the Workspace open you can see what variables the Workspace has, and what are their current values. Indeed, you can see them being added or changed as you add or change them! Other Workspaces you open have whatever variables you add to those other Workspaces, and none to start with.

Note that you also can combine what you have Experimental workspace:

coll add: (number1*number2) / var.

will make the calculation and add it to coll, as you can verify for yourself in the Inspector of the model of the Workspace.

Also, you can alter the contents of the OrderedCollection coll you made, like so

coll at: 1 put: 'Improved text'.

You can check all of coll at any time in this Workspace by

coll inspect.

And if you've set things up properly with the inspectors you can see the changes you make to the workspace you work in, including its current variables.

-- end of copy into a new Experimental workspace

4.3. Getting text for Workspaces

If you Cmd-d on the following, you get a Workspace with some stuff to try out - provided Squeak Help is attached to the directory the image you are using works in and is called 'Help'. (It works on Windows XP. I haven't tried other OS-s.)

(FileStream oldFileNamed: 'Help\WorkspaceExamples01.text') edit.

If you click up its debug halo and use inspect, you'll see this opened a SystemWindow, and if you click repeatedly to get its submorphs you'll see the text is edited by a PluggableText morph.

This can also run Squeak code, but doesn't store variables in a special dictionary called bindings as does a proper Workspace.

But this is a nice way to save and get snippets of code, also because you can save the text in a Workspace on disk, by its menu (next to the x that deletes it) with save contents to file.

4.4. Getting input

There are lots of ways to get input for the user (such as you, reader) in some more or less systematic form. Here are a few, starting with the simplest.

Use the following code in the Workspace in which is coll (see above)

input := FillInTheBlankMorph request: 'What is your favorite color?'.
coll add: input.

You will see in the inspector of the Workspace's model, if it is still open (you can open it anytime from the Workspace's debug halo) that the phrase you answered was added to coll.

Here is a somewhat subtle point. If you do Cmd-b on FillInTheBlankMorph you'll see that the line we used to get input is found on the class-side of the FillInTheBlankMorph. This means it is always available in a running Squeak, and no instance needs to be made to use this command. That's also why input wasn't registered as a variable in the Workspace.

You can also use this Morph with the Transcript

| answer |
answer := (FillInTheBlankMorph
request: 'What is your favorite color?'
initialAnswer: 'red').
Transcript show: answer.

To precook the answers from the user in a hopefully useful way, by telling the user what's expected, one has for example (use with Cmd-p to print out the answer):

SelectionMenu confirm: 'Are you hungry?' "Shows a menu with the string as a title, and choices of 'Yes' and 'No'.  Answers true or false".

Or one can use the slightly fancier

SelectionMenu confirm: 'Are you hungry?'
trueChoice: 'yes, I''m famished'
falseChoice: 'no, I just ate'
"Like the previous example but lets you change the names of the Yes/No options."

4.5. Using your own menus

Often it makes sense to offer the user some choices in a menu. There are many possibilities in Squeak to do so. Here are a few.

If you do Cmd-p the choice is printed:

(PopUpMenu labelArray: #('Abel' 'route 66' 'Cain') lines: #( ) ) startUp

"Popup a menu with the given labels; answer the number of the menu item. "
('Abel' is 1, ...)

If this numerical output is too simple you can try with Cmd-p:

(CustomMenu fromArray:
#( ('Abel' #('legendary' 'Biblical person') )
('route66' #('real' 'also mentioned by Bob Dylan') )
-
-
('Cain' #('legendary' 'Biblical person') )
-
('possibilities' #('one' 'two' 'three') )
-))
startUp: #route66

Presents a menu of the first items in the parenthesized list;
answers the second object in the corresponding list. For example,
the above code puts up a menu with 'Abel', 'route66', 'Cain', 'possibilities'.
If Cain is selected then the array #('legendary' 'Biblical person') is answered.

There are lots of possibilities with menus, such as the following.

EmphasizedMenu does textual emphasis on the menu items.

(EmphasizedMenu
selections: #('bold' 'plain' 'italic' 'struckout' 'plain' 'nice menu!')
emphases: #(bold plain italic struckOut plain bold))
startUp

This returns the string chose in selections:.

Here is something to learn a bit about the many choices there are in life.
Highlight the following paragraph and Cmd-d.
Good simple starters are 10 10 1 and 100 50 5.

| strFrom strTo strBy from to by count |
strFrom := FillInTheBlank request: 'From?'.
"Getting user-input"
strTo := FillInTheBlank request: 'To?'.
strBy := FillInTheBlank request: 'By?'.
from := strFrom asInteger.
"Converting an input-string"
to := strTo asInteger + 1.
"Converting an input-string and adding 1 to use as limit below"
by := strBy asInteger.
Transcript cr; show: 'From = '; show: strFrom; show: ' To = '; show: strTo; show: ' By = '; show: strBy.
"Informing the user about the parameters chosen"
count := 0.
[count < to] whileTrue:
[Transcript cr; show: count; tab; tab; show: (from take: count). count := count+by.]
"Calculate and display. The work is done by from take: count. If you select take: and Cmd-m you learn a bit more."

4.6. Some fun bits

Now for two fun bits. Here is code to put a rotating form from screen:

| a f |
f := Form fromDisplay: (100@100 extent: 600@600).
a := 0.
[Sensor anyButtonPressed] whileFalse:
[((Form fromDisplay: (Sensor cursorPoint extent: 200@200))
rotateBy: (a := a+5))
display].
f display.

It is interesting to play with the extent: and with the rotateBy: and alter the numbers and see what happens.

Here is a regular shape to put on your screen:

World addMorph: (PolygonMorph
shapeFromPen: [:p | p hilbert: 4 side: 7. p go: 7.
p hilbert: 4 side: 7. p go: 7]
color: Color red borderWidth: 2 borderColor: Color yellow)

Again, you can twiddle the code and see what happens.

If things take time there is this to consider:

'Now here''s some Real Progress'
displayProgressAt: Sensor cursorPoint
from: 0 to: 10
during: [:bar |
1 to: 10 do: [:x |
bar value: x.
(Delay forMilliseconds: 500) wait]].
"Display a message and a progress bar. The progress bar stays up during
the execution of the block. Note that the range (from:to:) must be known
ahead of time and must match the number of steps inside the block.
(There are many examples in the image.)"

4.7 Addressing the OS with Squeak

So you want Windows or an other OS running with Squeak?! Entirely possible!

If you do Cmd-b on Win32Shell, you get code for running this OS from Squeak. There is similar code for other OS-s. Obviously, it only works on Windows (or on a Linux that's running Windows, but I haven't tried this) and obviously you can't start what isn't on the Windows OS you try this out in.

But supposing you are running Squeak in M$-Windows:

Win32Window getFocus messageBox:'Hello World' title:'News from Squeak:'.
"Yes indeed"
Win32Shell new shellExplore: 'c:\'. "Explore a directory with Windows"
Win32Shell new shellFind: 'c:\' "Initiate a search with Windows"

The last two are very useful to have with your own current Squeak-directory. (Edit the string to achieve this.)

And you can also run programs from Squeak

Win32Shell new shellOpen: 'c:\Python23\Pythonwin.exe'. "Open source scripting."

Of course, to run Python it must be on your drive. It is on mine.
Python is nice and simple, but is no Squeak. One difference is that it is simpler.

4.8 Playing with morphs on screen

(This is a Morphic version of Joe-the-box, that first appeared in Smalltalk-72.
This example does not anthropomorphize code. Code does not know or desire: Human users do.)

Copy the following to the Experimental workspace you made above and Cmd-d the next six magenta lines

-- begin copy to Workspace

Opening two morphs in the world with inspectors:

Cmd-d
the following six lines:

morphy := Morph new openInWorld.
morphy position: 100@100.
morphy inspect.
murphy := Morph new openInWorld.
murphy position: 400@100.
murphy inspect.

This will put to blue morphs on screen with an inspector for each. If you put the cursor in the inspectors on the second line all inst var and put the inspectors at some convenient place on the screen, grabbing morphy or murphy and putting them anywhere else will show this in the inspector for the morph.

Coloring a morph:

The following lines color the morphs. (There are many other colorterms that work: green, red, lightGrey, white ..)

murphy color: Color lightYellow.
morphy color: Color lightBlue.

Resizing morphs:

The following lines each increase or decrease the extent (size) of the morphs

murphy extent: (murphy extent*1.2)
"More"
murphy extent: (murphy extent*0.8)
"Less"

morphy extent: (morphy extent*1.5)
morphy extent: (morphy extent*0.5)

Obviously you can use other numbers to increase or decrease it by different amounts. And you can use the extent of another morph (murphy for morphy, say) to resize it.

Adding a morph to a morph:

One can add morphs to morphs. Here is a simple example. First create an EllipseMorph

ellipse := EllipseMorph new.
"Assign it"
ellipse color: Color red.
"Color it red"
ellipse openInWorld.
"Open it"

Having made an EllipseMorph it can be added to a morph:

murphy addMorphCentered: ellipse.
"Add it to murphy"
ellipse delete
"Delete it. This is here: make invisible. You can add it again"

Do it again for Morphy (first open an ellipse as per above):

morphy addMorphCentered: ellipse. "Add it to morphy"

Moving a morph horizontally and vertically:

The following snippets of code, with Cmd-d on a line or on several lines, will move the morphs:

morphy position: (morphy position + (10@0)).
morphy position: (morphy position + (0@10)).
morphy position: (morphy position - (10@0)).
morphy position: (morphy position - (0@10)).

morphy position: (murphy position - (10@10)).
"Morphy jumping to murphy"

murphy position: (murphy position + (10@0)).
murphy position: (murphy position + (0@10)).
murphy position: (murphy position - (10@0)).
murphy position: (murphy position - (0@10)).

murphy position: (morphy position - (10@10)).
"Murphy jumping to morphy"

murphy position
"Cmd-p for info where it is now on screen"
morphy position

As noted before, you also see the current position in a morph's inspector.

Putting it back on the screen (if you lost it outside the screen):

The following lines are there to help you reposition morphs

morphy position: 1@1
murphy position: 10@10

If you want to get rid of a morph, click up the halos on it and x.

By now you should have understood why Workspaces are such a powerful tool, and why I normally have at least one Squeak open when I am running my none-foo-favourite OS Windows.

-- end copy to Workspace

Previous - Workspaces.