Use the Warehouse again to create Motion. Motion is an Interactor which allows objects to experience linear motion. Like any Interactor, Motion applies only to those object which are enrolled in it. Our next step is to enroll the sphere in Motion.
Drag the sphere on top of Motion, and drag the enroll button on top of the sphere. Shift-click the enroll button to enroll it in Motion.
Now "throw" the sphere by dragging it (slowly) and releasing the mouse button before you stop moving the mouse. The sphere will begin moving at the same velocity as the mouse was moving when you released the button.
Now create Gravity (another Interactor) from the Warehouse, and enroll both spheres in it. The spheres will begin drifting towards each other under the influence of gravity. If you'd like the gravitational attraction to be stronger, try changing the mass of the spheres by sending them the editAttribute message (using either the ButtonMaker or the Shortcuts menu).
Now create a large sphere from the Warehouse. The sphere will automatically be enrolled in Bounded Motion, since we made the interactor into a universal law.
Try throwing the sphere, and you will notice that it remains within a rectangular area. To change the size of this area, you can send the editAttribute message to the Interactor.
Shift-click the ObjectMaker (labelled MakeObject), type a 1 in the field of the resulting window, and click Okay. The ObjectMaker creates a new object representing the Smalltalk integer 1. Create an object representing 4.7 in the same manner, and drag these objects into an empty part of the window.
Move the ButtonMaker onto the 1 object and shift-click it. A menu pops up displaying the value of the object (1), its class, and all of its superclasses. Each item is a submenu containing a list of all messages accepted by the corresponding class. From the arithmetic category of the Integer class, choose +. This creates a Button which sends the + message. Drag the ButtonMaker off the 1, and drag the + Button onto the 4.7 object.
Since + requires a parameter, this button has a small square attached. Drag this square to extend a line and another green box from it. Experiment with dragging the line and the box. Note that all drags are essentially drags of the green box. Try dragging the green box onto the white box. Drag the green box so that the end of the line rests on the 1 object.
Drag the ObjectMaker onto the + Button and shift-click the ObjectMaker. Shift-clicking the ObjectMaker creates a new object with the value of the object below the ObjectMaker. Since the object below the ObjectMaker is a Button, its value is computed by computing the value of its parameter (1) and sending the message (+) with that value to the receiver (the object under the +, or 4.7). The result, 5.7, is the value of the Button, and is created as a new object. (Hint: you can quickly check the value of an object or button without creating a new object by clicking the ButtonMaker on it-- the value of the object will appear in the menu. You can also easily display any value in a separate window using the Displayer).
Move the the ButtonMaker to an empty space and shift-click it to bring up a window which allows you to input any method name. Enter "add:" and click Okay.
Drag the add: Button on top of the List new object. Drag the square from add: to the 5.7 object and click add: to add 5.7 to the List. Change the add: parameter to the 4.7 object and add it to the List. Add the 1 object to the List. The list should now be of length 3. Create a new size Button and place it on the List. The value of this button is now 3, because sending size to the list returns 3. Make this size button the parameter to the add: button (by dragging the green square from the add: button and dropping it on the size button), and click add: to add 3 to the List. Finally, create a new string object 'hello' and add it to the List.
Move the ObjectMaker to an empty space and shift-click it to create a new object. Type "[ :each | Transcript cr; show: each printString ]" and click Okay to create a new Block. Note that the Block has a square for its parameter-- this square works the same as the squares on a Button. This block prints its parameter on the Transcript. Experiment with printing various objects on the Transcript by connecting them to the :each parameter of the Block and shift-clicking the Block. Now drag the green box from the :each to the white box to remove the green box. Create a new button to send the do: message, by typing it in the ButtonMaker window. Drag the do: button to the List, and drag the do: parameter square and drop it on the block. Click do:, and the block will be called for each item in the list, printing each in the Transcript.
You can upgrade the size button to an Interactor by selecting Upgrade To Interactor from the menu. Enrolling an object in one of these "upgraded" interactors has the same effect as placing the original button on top of the object and pressing it repeatedly.
Try enrolling one of the objects in the size interactor and then turn the interactor on. A new object will be created which shows the current size. This result will update dynamically as the original object's size changes.
Try adding new items to the list, and watch the size result change.
Objects in the World can represent any Smalltalk object. Some objects do not represent a specific Smalltalk object, but exist only as World objects. These objects (examples include Sphere and Chalk) generally come from the Warehouse, and are used with the physics simulation features of Quirk.
Every object has a value. For objects which represent Smalltalk objects, their value is the Smalltalk object itself. Other types of objects like Buttons and Blocks compute their values in as needed.
Quirk Objects are referred to internally as QActors, and this name may be used in some parts of Quirk.
When an interactor is turned on, all of the objects that are enrolled in the interactor will follow the behavior defined by the interactor.
For example, all objects that are enrolled in the Motion interactor can be thrown, and they will move according to the user-defined speed and direction.
Each interactor may add certain attributes to the object. These attributes (e.g., acceleration for Motion) can be edited by sending the object the editAttribute message. By altering the values of the attributes, the object's behavior (as dictated by the interactor) can be modified.
Each interactor also has an actionBlock which defines the behavior for all of the enrollees. The block is executed repeatedly for each enrolled object. This too can be edited by sending the Interactor the editActionBlock message.
Interactors can be made universal. When an interactor is made into a universal law, all objects are enrolled in the interactor. In addition, any objects created from the Warehouse or via the ButtonMaker will automatically be enrolled in the universal interactor upon creation. This option is especially convenient for Interactors which represent different physical laws (e.g., Motion, Gravity) that might apply to all objects in the world.
An interactor can also represent a Smalltalk message. To create such an interactor, the user must transform a button into an interactor by selecting the Upgrade To Interactor option from the menu. The effect on enrolled objects is analogous to placing the original button on top of the object and clicking it repeatedly.
This option can be convenient when viewing a value of a given message for an object that might change frequently. By enrolling the object in the interactor, the user can always see the current value that the method returns.
Buttons which represent multi-parameter messages have one small square for each parameter of the message. This square can be dragged to specify which object should be used as the parameter. Dragging the square creates an elastic line; dropping the end of the line on another object specifies that object as the value of the parameter.
A middle click of the mouse on any object will pop up a context sensitive shortcut menu. Copy, Cut, and Paste have their normal meaning for the object selected. ShortCut has a submenu which includes all of the zero-parameter messages that can be sent to the object. For example, all objects can respond the the growDouble message which doubles the image size for the object. Selecting a message from this ShortCut menu will send the selected message to the object. makeButton will popup a menu of all messages understood by the object. Any selected message will be made into a button in the World. Upgrade to Interactor creates an Interactor from the object.
The ShortCut and makeButton menus are composed as follows: The main menu is a list submenus. The first element is a menu of messages that all objects can handle. If the object represents some Smalltalk object, then the Smalltalk object will be displayed second on the main menu. This submenu contains the catagories and messages of the Smalltalk object's class. The rest of the main menu contains the ancestors of the Smalltalk object with each submenu having the categories and messages that each superclass implements.
The value of a button (used when the the ObjectMaker or the ButtonMaker is clicked on top of a button, or when a button is provided as a parameter to another button or a Block) is computed by sending the Button's message to the object beneath it, and using the resulting returned value.
You can create new Buttons using the ButtonMaker.
Objects can be brought out of the Warehouse by shift-clicking on the Warehouse image in the World window, and selecting the object from the resulting menu.
Objects can be added to the Warehouse by sending the addToWarehouse message to the object.
Drag the ButtonMaker (labeled makeButton) onto an object and shift-click to bring up a menu of all messages that object accepts. Select an item from the menu to create a button which sends that message.
Alternately, shift-click the ButtonMaker while it is not on top of any object to bring up a window where you can type any message name (ex. 'at:put') and create a button for that message.
Drag the ObjectMaker (labeled MakeObject) onto an object and shift-click to create a new object with the same value as that object. This is particularly useful for Buttons, since the value of a Button is computed by sending its message. Thus the ObjectMaker can be used together with one or more Buttons to create an Object in the World which is the result of one or more Smalltalk message sends.
Alternately, shift-click the ObjectMaker while it is not on top of any object to bring up a window where you can type any Smalltalk expression (ex. 'Array new: 5') and create a new Object whose value is the value of the expression.
The value of a block (used when the the ObjectMaker or the ButtonMaker is clicked on top of a block, or when a block is provided as a parameter to another block or a Button) is computed by evaluating the Block with the specified parameters and using the resulting value, unless no parameters are specified. If no parameter are specified (if there are no lines leading from the squares on the Block), the value of the Block is instead the value of the underlying Smalltalk block. This duality allows Blocks to serve two purposes-- they can provide easy computations when parameters are provided, and they can serve as normal Smalltalk blocks when parameters are not provided. The latter purpose might be used to supply a block as a parameter to a do: button, for instance.