This tutorial takes you through the process of building several simple projects using Spin. Before you try this tutorial, you should have installed Spin (from the Download page, see also the Spin Installation Guide). You should also refer to the Spin User Manual.
To get maximum benefit from this tutorial, you should read through the introduction and the section on building applications, (e.g., even if you only plan on building servlets). We encourage you to actually build the tutorial projects, and play around with other components. After building the projects in the tutorial, a good next step is to examine and play with the example programs.
In the File menu of the project window, select "New Capsule". An outline view will appear containing a single empty capsule. In the outline window, go to the View menu and choose "Open Toybox". Another window will appear with the toybox view of the (still empty) capsule.
Summary of Steps: Creating a new capsule
From the toybox window, open the Insert menu, and move your mouse down to zat.demo, then move your mouse to the right and select Juggler. The juggler will appear in the toybox view and an icon for the juggler will appear in the outline view.
Note that this tutorial uses the new Juggler from Zat. If you do not have this juggler (or you only have the old Juggler from Sun), you should download a new copy of Spin.
In the outline view, the juggler appears as a child of the capsule, and is automatically given the name "Juggler2" by Spin. This name consists of the name of the bean, followed by a unique number (if you insert another juggler, it would be Juggler3). You can change this name to whatever you want by clicking on it.
In the toybox view the components are always active, so you can see the juggler juggling. Below the juggler is an editing handle containing the name of the juggler, Juggler2. The editing handle is normally white, but when you click on it it changes to blue, indicating that the actor it is attached to has been selected. You can change the name of the component in the toybox view by double-clicking on the name (changing the name in either view changes it in both views, of course). You can move the juggler around by dragging its editing handle, and you can resize the juggler using the triangular resize widget in the lower right corner.
When you select the juggler by clicking on its editing handle, the editing handle turns blue and a menu called "Actor" appears in your menu bar. The "Actor" menu is specific to this actor. A shortcut to get the "Actor" menu is by pressing the right mouse button (command-click on the Mac) while over the editing handle for an actor.
Summary of Steps: Adding a Juggler bean
The "Actor" menu contains three sections. The first section contains five choices:
Edit-Custom a JavaBean can have a custom editor associated with it. In the case of the juggler there is no custom editor, so this selection is grayed out.
Edit Generic brings up a generic dialog that lets you view and edit all properties of this actor.
Edit Name edits the name of the actor.
Get Object Info shows the public variables, properties, methods, and events for this actor. If this actor has any JavaDoc documentation in the docs subdirectory of the Spin installation directory, that information is also displayed.
Delete deletes this actor.
The second section contains the command "Edit Property". If you put your mouse cursor over this command, a sub-menu appears with all the properties of this bean.
The final section contains methods that you can execute on this bean. These are the methods on the bean that take no arguments.
The "Actor" menu also appears in the outline view, except that it does not contain the last section containing the methods you can execute (methods can only be executed in the active toybox view). As in the toybox view, you can also bring up this menu by right-clicking on the icon of the juggler (command-clicking on the Mac).
First, let us execute a couple of methods on the juggler. In the toybox view "Actor" menu, select the method "stopJuggling()" The juggler stops juggling. Repeat this, and select the method "startJuggling()" the juggler starts juggling again.
Most of the other methods in this section of the menu are internal methods that relate to how Java draws objects on the screen, and are not of particular interest.
Summary of Steps: Playing with the Juggler
There are several ways to edit the properties of the Juggler. These work in both the toybox view and the outline view.
The first way is with a generic editor. From the Actor menu, choose the "Edit-Generic" command. For the juggler the generic property editor has two tabs. The first tab is for the Juggler itself and contains only one property: "AnimationRate". Change the AnimationRate to 50, and press the "OK" button the juggler runs faster. You can also click the "Apply" button rather than the "OK" button to leave the dialog open so you can try various values.
Summary of Steps: Editing properties of the Juggler
Note that the meaning of the AnimationRate property was determined by the JavaBean author. In this case, the rate is actually a delay between frames of the animation.
The other property in the first tab sets whether or not the juggler is scalable. If you set this property to true, then when you resize the juggler the image will get larger and smaller.
The second tab of the property editor is for the properties of the Juggler's superclass, which in this case is Component (most visual JavaBeans are derived from class Component). A superclass is used to collect similar properties and functions together. In Java, visual JavaBeans are derived from Component so that the author of the JavaBean does not need to rewrite similar functionality for every visible bean.
Choose the tab for Component, and change both the x and y value for Location from 0 to 10. When you press the "Apply" button, the juggler moves. You can also make the juggler invisible with the "Visible" property, and change its size.
Some of the properties of Component do not apply to the juggler. For example, the juggler does not contain any text, so changing the Font property has no effect, nor does changing the foreground or background color.
The second way to change properties of an actor is with a custom editor. A custom editor is an editor that is supplied with a JavaBean. The juggler does not have a custom editor, so the "Edit-Custom" command is grayed out.
You can also select the juggler (in either view) and choose the "Edit Selected Object" command from the "View" menu. This brings up an edit dialog for the actor. If the actor has a custom editor, it is brought up, otherwise the generic editor is brought up.
Finally, you can edit a single property of an actor using the "Edit Property" sub-menu of the "Actor" menu. This is mainly useful for changing a single property quickly. Bring up the "Edit Property" sub-menu of the "Actor" menu and select "Cursor" (at the bottom of the list). Change the cursor from "Default" to something else (for example, to "Hand), and then click the "OK" button. Now notice that when the cursor is over the juggler, it changes to whatever cursor you selected.
In the toybox view, grab the juggler by its editing handle and move it to the center of the toybox view. Now, click anywhere inside the toybox view except on the juggler to deselect it. The editing handle for the juggler should change to white (from highlighted blue).
Now, from the Insert menu, go to "AWT Component" and select "Button". A button should appear in the toybox view. Look in the outline view -- there should be two objects as children of the capsule, the juggler and the button. Initially the button is rather small.
A common mistake is to leave some actor selected and insert a new actor as a child of another actor, rather than as a child of the capsule. There is nothing wrong with doing this, it is just not what we want in this example. If you make this mistake, you can simply drag and drop the component in the outline view to put it where you want it. For example, if you ended up with the button as a child of the juggler, you could drag the button and drop it onto the capsule, to make it become a child of the capsule.
Summary of Steps: Adding a button
In Java, there are two kinds of visible components, called lightweight and heavyweight components. A heavyweight component uses a separate window, supplied by the operating system. A lightweight component does not have a separate operating system window; it is drawn into the same window as its parent (in this case the window associated with the capsule).
Most of the time you will not care whether a component is lightweight or heavyweight, but occasionally it will matter. For example, if a window contains both heavyweight and lightweight children components, the lightweight components cannot appear in front of the heavyweight components, because they do not actually have their own window. Originally, all components in Java were heavyweight, but lightweight components were introduced because they have a number of advantages.
The juggler is a lightweight component, but the button is a heavyweight component (all AWT components are heavyweight). Spin indicates that a component is heavyweight by underlining its name in the toybox view.
Remember that there are several different ways to do this. First, let's resize the button to make it larger, using the resize widget on the edit handle. Notice that Spin displays the size of the object as you resize it. You could also resize the button by editing its Size or Bounds property. You can also move the button around using the edit handle, or by editing the Location or Bounds property.
Second, let's give the button a label. Change the "Label" property so that the button says "stop". You can also change the background color, font size, or other properties (note that due to a bug in MRJ, on the Macintosh editing the background color of a heavyweight component does not do anything).
Summary of Steps: Editing properties of the button
Now we want to actually make the button do something. In the toybox view, select the button by clicking on its editing handle (the editing handle turns blue to indicate it is selected).
We could add a behavior using the Insert menu, but we are going to use a palette instead. In the View menu, go to the Palettes command, pull right and select "Behaviors". A small window should pop up containing 6 icons, one for each of our built-in behaviors. When you move your mouse cursor over a behavior, the name of the behavior appears in the status line of the palette. Click on the first icon, which is the "Action" behavior.
Summary of Steps: Using a Palette to insert a behavior
An action behavior should appear as a child of the button. Look in the outline view to see that the behavior is a child of the button. In the toybox view, the action behavior appears as an icon in the edit handle for the button.
In either the outline or the toybox view, double-click on the icon for the action behavior. This brings up the editor for the action behavior. This editor has several fields. To the right of each field in the action behavior is a right-pointing triangular arrow. When you click on this arrow, a menu appears giving possible values for the field.
The "Activate On" field sets the stimulus for this behavior. Set the "Activate On" field to actor.Action.actionPerformed (using the menu brought up by the triangle arrow to the right of the field). Specifying "actor" means whatever actor this behavior is a descendent of, which, in this case is the button. We want this behavior to activate when the button is pressed, so we choose the "Action.actionPerformed" event, which is the Java user interface way to say "whenever this widget does what it is supposed to do".
In response to the stimulus, we want the juggler to stop juggling. Set the "Send To" field to "Juggler2" (if you changed the name of the juggler, set it to your changed name). Finally, set the message to "stopJuggling". The "stopJuggling" method takes no arguments (additional information), so we are finished specifying this action.
Now, in the toybox view, click on the stop button, and the juggler stops juggling. That's all there is to it. There is no need for a separate compile step or anything else; it just works immediately. You don't even have to close the window for the action behavior.
Summary of Steps: Specifying an Action Behavior
In our project so far we have two actors (the juggler and a button) and a single behavior. Note that the behavior's parent does not actually have to be the button. The behavior's parent could be the juggler, or even the capsule. The only thing that is affected by a behavior's parentage is what the aliases "actor" and "parent" refer to.
When the behavior is a child of the button, we can refer to the button using the alias "actor" this is what we did when we had the behavior activate on actor.Action.actionPerformed. If the action behavior were a child of the juggler, then the actor alias would refer to the juggler. In this case, the action could send the message "stopJuggling" to the "actor" alias, but the button would have to be named explicitly. If the action behavior were a child of the capsule, then "actor" would refer to the capsule. In this case, we would have to name both the button and the juggler explicitly.
The advantage of making the action behavior be a child of the button is that it makes it easy to reuse behaviors. We will demonstrate this by creating a second button, a start button. Go to the outline view. Select the button by clicking on its icon. From the edit menu, choose "Copy", then select the capsule by clicking on its icon, then choose "Paste". You now have two copies of the button, with the same name (you can change the names to be different, but it is not necessary).
A short-cut for making a copy of an object in the outline view is to hold down the control key (option key on the Mac) and drag a copy of the object's icon to a new position. You can also move objects in the outline view by dragging their icons and dropping them onto the icon of their new parent.
In the outline view, both of our buttons have a yellow right pointing arrow to the left of their icons, indicating that they have children. Click on both of these arrows to see the children (the arrow changes to a down pointing arrow).
Summary of Steps: Making a copy of the button
We now change the second button to be a start button. This can be done in either the outline or the toybox view, but we will do it in the outline view. Double click on the icon for the first "Button3", which brings up the object editor dialog. Change the label from "stop" to "start" and click the "OK" button. Now, double click on the icon for the first "Action4" behavior, which brings up the editor for the action behavior. Change the Message field from "stopJuggling" to "startJuggling". and close the dialog.
We now have a start and a stop button, but they have the same position in the toybox view. Go to the toybox view, and drag the top button to a new position (by dragging on its edit handle). Arrange the two buttons as you wish.
Finally, click on the start and stop buttons to verify that the juggler starts and stops juggling.
Summary of Steps: Changing one button to be a start button
Note that both behaviors activate on actor.Action.actionPerformed, but since they have different parents, the alias "actor" refers to the proper place.
You might want to see what your project looks like without the stuff that is not actually part of the project (such as the editing handles and the background grid). From the View menu in the toybox view, choose "Hide/Show Editor". You can still click on the start and stop buttons to make the juggler start and stop, but you cannot edit anything in the toybox view.
Alternatively, from either the toybox or outline view, choose "Run" from the File menu. A new window is created with your running project. There are a couple of differences between this window and the toybox. Most noticeably, the window is automatically sized to include just the objects in your project and the origin. There are a few other differences, mainly having to do with compilation.
Summary of Steps: Viewing your project
We are now going to add a scrollbar (also called a slider) to control the juggling speed. Go back to the toybox view, make sure editing is back on (by choosing "Hide/Show Editor" from the View menu), and click on the background to make sure that no actors are selected. From the Insert menu, go to "AWT Component" and select "Scrollbar". A new scrollbar is inserted into your project.
Using the editing handle, move the scrollbar, and using the resize widget at the right end of the editing handle, resize the scrollbar to make it about the same height as the two buttons.
Summary of Steps: Adding a scrollbar
Now, make sure the scrollbar is selected (its editing handle is highlighted), and from the Insert menu (or from the palette containing the behaviors) insert a new action behavior. The action behavior appears in the editing handle for the scrollbar. Double click on the icon for the new action to bring up its edit dialog.
Set the "Activate On" field to "actor.Adjustment.adjustmentValueChanged" so this behavior will activate when the value of the scrollbar is changed. Set the "Send To" field to "Juggler2" (or whatever your juggler is named) and set the "Message" field to "setAnimationRate". A data field appears to indicate that the setAnimationRate message takes an int (integer number) argument.
The button to the left of the last field shows "With:", which allows you to specify a constant value, but we want to pass the value from the scrollbar. Click on the "With:" button and it changes to "With=" and a black triangular arrow appears at the right end of the field. Click and hold the triangular arrow and select "getValue()" (which gets the value of the scrollbar).
Summary of Steps: Scripting in a behavior
Close the edit dialog for the action behavior. Go back to the toybox view, make sure the juggler is juggling (by pushing on the start button if necessary) and change the value of the scrollbar. The juggling speed should change.
Notice that when you first changed the value of the scrollbar, a window popped up and said "Grinding Beans". This shows that Spin is compiling the expression you typed into the "With=" field. In this case, this expression is very simple, just the value of the scrollbar, but it could be an arbitrary Java expression. For example, try changing the value to be "getValue() * 2" so that the animationRate property of the juggler is set to twice the value of the scrollbar. Or you can use "getValue() + 50" or any desired expression.
There are several properties of the scrollbar that you can change. For example, you can change the minimum and maximum values of the scrollbar, or how much the value changes when you click in various parts of the scrollbar. Notice that while you are making these changes, the toybox view merrily continues to work, so you can immediately see the effects of your changes.
This is a good time to save your work. From the File menu, choose "Save". A file dialog comes up. A good place to save your project is in the "examples" subdirectory of the Spin installation directory, but you can save it anywhere you want. By convention, capsules are saved with a ".zac" suffix. As in any tool, you should save your work often.
Because you can type an arbitrary expression into the "With=" field of a behavior, it is possible to type an incorrect expression and cause an error. Spin can help you find and correct errors like this.
Double click on the action behavior for the scrollbar to bring up its edit dialog. Go to the "With=" field, and change the first letter so that the expressions is "petValue()" rather than "getValue()". Go to the toybox view and move the adjustment button of the scrollbar. The "Grinding Beans" message appears, indicating that Spin is recompiling an expression, but in this case an error occurs and the following window appears.
Summary of Steps: Finding an error
Double click on the first message in this window, and Spin pops up the behavior where the error occurred, in this case the action behavior for the scrollbar. Change the "With=" field from "petValue()" back to "getValue()". You can leave the edit dialog open. Drag the adjustment value of the scrollbar. Spin puts up the "Grinding Beans" message briefly to recompile the expression, and then everything should run properly.
A rollover is a visual object that changes appearance when the mouse cursor moves over it. We can create a rollover in Spin with two simple action behaviors. In the toybox view, select the start button (so that its editing handle is highlighted) and insert two action behaviors. This leaves the start button with three behaviors (the original behavior that starts the juggler juggling, and the two you just added). Change the names of these two behaviors to "enter" and "exit".
Double click on the "enter" behavior to open its edit dialog. Set the "Activate On" field to "actor.Mouse.mouseEntered". Leave the "Send To" field as "actor". Change the "Message" field to "setLabel" and in the "With:" field enter the string "push me" (without the double quotes). Now move the mouse over the start button in the toybox, and observe that the button label changes to "push me".
Now, double click on the "exit" behavior to open its edit dialog. Set the "Activate On" field to "actor.Mouse.mouseExited". Leave the "Send To" field as "actor". Change the "Message" field to "setLabel" and set its "With:" field to "start". Close the behaviors.
In the toybox view, when the mouse moves over the start button the button label changes to "push me", and when it moves away from the start button the label changes back to "start". You've created a rollover!
You can make the stop button do the same thing by copying the two new behaviors to the actor for the start button. This can be done in either the outline or the toybox view. You can copy behaviors either using Copy and Paste from the Edit menu, or by "control-dragging" the icons (option-dragging on the Mac). Note that you will have to change the "exit" behavior on the stop button so that it sets the button label to "stop" instead of "start".
You can use a rollover to change any property of an actor, not just the label of a button. Note, however, that heavyweight components (like an AWT button) may behave differently on different platforms. For example, on the Macintosh you cannot change the background color of an AWT component, due to a limitation of MRJ (Macintosh Runtime for Java). This is one of the reasons why lightweight components are preferable. You can use third-party lightweight components, or you can create your own. The slideshow example program contains a button that uses images instead of text.
In the outline view, select the "start" button, and insert an ActionGroup behavior. Change the name of the ActionGroup to "Rollover". Edit the ActionGroup behavior, and set its "Activate On" field to "actor.Mouse.mouseEntered".
As children of the Rollover ActionGroup, insert a regular action behavior and a string data item (from the "Data Item" submenu of the Insert menu). Change the name of the action behavior to "save" and the name of the string to "label".
Double click on on the "save" behavior to edit it. Set the "Activate On" field to "parent.Behavior.activated" (this activates the "save" behavior when the "Rollover" group behavior is activated). Set the "Send To" field to "label", and the "Message" field to "set". Click on the "With:" button to change it to "With=" and set the field to "actor.getLabel()". This saves the label of the actor in the string variable.
Drag the "enter" and "exit" behaviors from the start button to make them children of the "Rollover" group behavior. Change the "enter" behavior so that it is activated on "parent.Behavior.activated". (Astute readers will notice that this is not actually necessary, but it is good form). Finally, edit the "exit" behavior and click on the "With:" button to change it to "With=" and set the field to "label". This will restore the saved label when the mouse exits the actor.
The Rollover behavior can be applied to any actor that has a "label" property, and it will set the label to "push me" whenever the mouse is over the button. For example, you can copy the "Rollover" behavior onto the stop button. But there is a better way to apply behaviors like rollovers to new actors.
Go to the outline view, and click on the rollover behavior to select it. Choose "Save Behavior" from the File menu. This saves the "Rollover" behavior so you can reuse it.
Now, go to the Insert menu and look in "User Behavior". You should have a new user behavior called "Rollover".
This new user behavior can be used like any behavior, and will work for any component that has a label. You can also modify the behavior to change other properties.
Note that when you insert a User Behavior, a copy of the behavior is made. This allows you to edit one instance of the behavior without changing other instances of the behavior. For example, you can change one of the Rollover behaviors so that it says something other than "push me".
There are other User Behaviors already in the Insert menu, called Spiral, Drag, and Jump. Feel free to play with these and see what they do. The user behavior named "ServletGet" is for use with servlets; you will see an example of its use later.
So far we have only used action and group behaviors. We are now going to add functionality that uses an IfTest behavior and a Boolean variable to make the juggler start and stop juggling when you click on it. Again, we will do this in the outline view because we are going to create a multi-level behavior (an ActionGroup behavior with children behaviors), and the toybox view only shows one level of behaviors.
In the outline view, select the icon for the juggler and insert an ActionGroup behavior (either from the Insert menu, or from the palette). Now double click the new ActionGroup behavior to bring up its edit dialog, which only contains a single field. Set "Activate On" to "actor.Mouse.mouseClicked" and close the edit dialog. This creates an ActionGroup behavior that activates when the juggler is clicked on.
Make sure the action group behavior is still selected and insert a Boolean data item. A Boolean variable can be either true or false. Change the name of this Boolean variable to "juggling".
Now we need something to toggle this variable (switch it from true to false and back). Select the action group behavior again and insert a regular action behavior. Change the name of this action behavior to "toggle". Double click on "toggle" to open its edit dialog. Set "Activate On" to "parent.Behavior.activated" so that this behavior will be activated when its parent behavior (the action group) is activated. Set "Send To" to "juggling" (the Boolean variable) and set "Message" to "set" (to set the value of the variable). Click on the "With:" button to change it to a "With=" button, to allow you to enter an expression for the value. You should enter the expression by typing "! juggling". The exclamation point is the "not" Boolean operator in Java, so this behavior sets the value of "juggling" to true if it was previously false, and to false if it was previously true.
Select the action group behavior again and insert an IfTest behavior. Double click on the IfTest behavior to open its edit dialog. Set the "Activate On" field to "parent.Behavior.activated" and the "If Test" field to "juggling". The IfTest behavior is activated when the action group behavior is activated, and then it tests to see if "juggling" is true or false.
Select the IfTest behavior and insert two regular action behaviors under it. Change the names of these behaviors to "ifTrue" and "ifFalse" (these names are only for convenience). Edit the "ifTrue" behavior by double clicking on its icon. Set it to activate on "parent.Test.ifTrue" and to send to the juggler the message "startJuggling". Close this behavior and edit the "ifFalse" behavior. Set it to activate on "parent.Test.ifFalse" and to send to the juggler the message "stopJuggling".
Either run the project, or go back to the toybox view. You can now start and stop the juggler by clicking on it. The hierarchy in the outline view should look like this:
You can save your capsule as a finished application by choosing "Save As Jar" from the File menu. Name your application, for example, "myapp.jar" (you should always use the ".jar" extension so that this application can be correctly loaded by other Java tools). When you click OK, the file myapp.jar should be generated. In it will be the class "myapp", which can be executed. Check the console for any errors. If your capsule fails to compile it will not save as an application.
To run the generated application you need to start it from a Java interpreter. To do this you must gather together the .jar files needed by the beans used in the application, and also any media files that you have used. In this example, these are:
myapp.jar (your application)
juggler.jar (from the beans directory)
These must be in your java CLASSPATH in order to run the application. In addition any Spin project will need the two class library files zat.jar and zatlib.jar. A typical command to run this application, on Windows, is:
jre -classpath %classpath%;myapp.jar;juggler.jar myapp
This command assumes that the files myapp.jar and juggler.jar are in the current directory, and that your CLASSPATH contains the full pathnames to the files zat.jar and zatlib.jar. You can also specify these files in the command, for example:
jre -classpath %classpath%;myapp.jar;juggler.jar;zat.jar;zatapp.jar myapp
Remember to specify the full pathname for any file that is not in the current directory. See the manual Deploying Spin Projects for full information about saving and deploying applications.
Note: we have just found a bug that prevents any application that contains the juggler bean from running on a PC. We have fixed this bug, and the fix will be included in the next release of Spin, due out soon.
Spin can use any valid JavaBean. You can find JavaBean components to use in Spin in the Zat components page. This section goes through the process of downloading a JavaBean from an external source, and using it in a Spin project.
We are going to use an HTML browser bean from ICEsoft. Note that this bean is free only for noncommercial use. If you want to use this bean in a product, you have to license it from ICESoft.
First, download the
ICE Browser 4
(for this example, don't use any of their other browser components).
We only need the JavaBean, which is the file
icebrowserbean.jar in the zip archive (the only .jar file in the archive).
Extract this file from the zip archive, and place it into the beans subdirectory
of the Spin installation directory.
Optionally, you can place the JavaDoc documentation for the ICE browser into the
docs subdirectory of the Spin installation directory, so that the Spin GetObjectInfo
command can display it.
Now start Spin and open a new capsule. In the Insert menu, you will notice a new entry for ice.htmlbrowser, which contains three JavaBeans: Browser, Document, and ICEBrowser.
The Document bean is simply a widget that can display HTML. The Browser bean builds on the Document bean by adding history, caching, and simple commands to go forward and back in the history. Finally, the ICEBrowser bean is essentially a full browser with buttons and other controls.
For this example we are going to use the Browser bean (because we want caching). Insert an instance of the Browser bean into the outline view. With the Browser bean still selected, choose "Edit-Generic" from the Actor menu (or from the right mouse button menu, or just simply double-click on the icon for the Browser in the outline view).
Recall that the Browser bean is built on the Document bean. This is reflected in the property editor, which has three tabs, for Browser, Document, and Component (the Document bean is based on the Java Component bean, since it is a visible component). Click on the tab for the Document bean.
Type any URL into the CurrentLocation property, and click OK to close the property editor. Now (from the View menu) open up a toybox view. The toybox should contain the Browser bean, which should (soon, assuming you are online) display the web page for the URL you entered into the property editor. For example, if you entered the URL http://www.yahoo.com, the Browser bean should display the home page for Yahoo! You probably want to resize the Browser bean so you can see the page.
We want some way to display the URL we are currently viewing, so go back to the outline view. Select the capsule, and insert the TextField AWT component. In the toybox view, position it just below the Browser bean and make it the same width. Now (in either view) click on the Browser bean, and insert an action behavior.
Fill in the fields of the action behavior as follows. Activate on "actor.PropertyChange.propertyChange (so the action will fire whenever any property of the Browser bean changes). Send to "TextField3" (or whatever you named the TextField) the message "setText". This message takes a single string argument. Click on the "With:" button to change it to "With=" and set the expression to "actor.getCurrentLocation()".
Now edit the CurrentLocation property of the Browser bean again, and set it to a different URL. In the toybox view, the Browser displays the new web page, and the TextField displays the new URL. Click on any link in the web page. Again, the browser displays the new web page, and the TextField displays the new URL.
Using the PropertyChange event is a common way to display information about a bean that updates automatically. In this case we updated the TextField when any property changed, but you can also examine the PropertyChange event to see which property changed.
At this point, you are probably tempted to add a "GOTO" button that takes the value in the TextField, and calls the setCurrentLocation method of the browser bean. This would allow you to type in any URL and go to it, just like in a real browser. But we are going to build something slightly different, instead.
Start with the project you built in the last section, containing an HTML Browser bean, a TextField bean, and a single action behavior. Close the toybox view and go to the outline view. Select the capsule and insert a timeline behavior. A timeline behavior allows you to build time-based animations, as in authoring tools like Director, except that in Spin, you can have as many timelines as you want, and they can control any property of any component.
Double-click on the timeline to open its editor. From the Timeline menu, move over "Add Object" and then move right to select "Browser2" (or whatever you have named the Browser bean). A new row appears in the timeline. In this row, right after the name of the Browser bean, is a black triangular arrow. Click on this and select CurrentLocation. Finally, there is another triangular arrow after the name CurrentLocation. Click on it and choose "No Tweening".
This timeline will be used to control the CurrentLocation property of the Browser. Note that a timeline can control multiple properties of multiple actors. For numeric properties, the timeline can do "tweening" (also called interpolation).
Click on the row for CurrentLocation so it is highlighted blue. The first column of the timeline (corresponding to the first frame of the animation) is colored yellow, and where these two highlights intersect it is colored green, and there is a circle, indicating a data point.
Spin automatically stores the current value of the property into this data point. Now, click on the intersection for the CurrentLocation row and the column for frame 15, so that the column for frame 15 is highlighted yellow. In the outline view, edit the CurrentLocation property for the browser, and set it to a different URL. When you are done, go back to the timeline editor, and in the timeline menu, choose "Capture Data" (or press Ctrl+K). Notice that the open circle fills in green, indicating that a data point has been captured.
Do the same thing for frame 30 and 45 edit the CurrentLocation property for the Browser, then capture the value as a data point in the timeline editor. When you are done, open up the toybox view again.
There are some controls in the timeline editor, just to the right of the word "Preview". Click on the black triangular right pointing arrow to play the animation. You can also manually move the blue pointer to any frame you want to play.
Finally, we want to make this animation play automatically, once every minute. Go back to the outline view, select the capsule, and insert the bean named "Clock" from zat.misc.
Go back to the timeline editor. Just above the word "Preview" is a funny looking widget that looks like it has little dimples on it. Click on this widget and the timeline editor opens up:
Set the "Activate On" field to "Clock6.Minute.timeChanged". This sets the timeline so it activates once per minute. Also, change the Frames/sec field to 1, so each frame is one second long and each HTML page shows for 15 seconds.
That's it! You now have a slide show that cycles through
four HTML pages, starting once a minute.
Instead of running the juggler as an application, we can save it
so that it can be run as an applet in a browser.
Saving an applet is similar to saving an application, except that you change the kind of capsule that is saved.
In the outline view, select the capsule. A "Capsule" menu is added to the menu bar. From the Capsule menu, choose "Edit Properties". In the dialog that comes up, change the type of the capsule from "Application" to "Applet". Close the Capsule Properties dialog.
Now, choose "Save As Jar" from the File menu, as before. You can give your applet the same name, or a different name, but be sure to use the ".jar" suffix.
The files needed to view this applet are the same as for your application (myapp.jar, juggler.jar, zat.jar, and zatlib.jar), except you will also need an HTML file in which to view the applet. It will look like the following (if you saved your applet in the file myapplet.jar):
<HTML> <HEAD> <TITLE>Applet test</TITLE> </HEAD> <BODY> <H1>My Applet</H1> <P> <HR> <APPLET CODE="myapplet.class" WIDTH=200 HEIGHT=100 ALIGN=bottom archive="myapplet.jar,zat.jar,zatlib.jar,juggler.jar"> </APPLET> <HR> </BODY> </HTML>
After installing the .jar and the .html files (don't forget the Zat class libraries zat.jar, and zatlib.jar) on your web server you should be able to view the applet in a browser.
Because JavaBeans are relatively new, we have found that only newer
versions of the popular browsers can view applets containing JavaBeans
properly (and all Spin applets contain JavaBeans).
If your browser does not handle JavaBeans correctly,
refer to the manual "Deploying Spin Projects"
for information on things you can do to make your applet run on older browsers.
Servlets are like CGI scripts, but with a number of significant advantages.
In Spin you can build servlets without programming.
Servlets are covered in the manual "Building Servlets with Spin".
This section walks you through the process of building and testing a servlet.
This document assumes that you already understand HTML (including basic CGI).
Servlets are different from other projects you build in Spin, because a servlet does not directly interact with the user. Instead, a servlet runs on a Web server, and uses HTML and CGI to communicate with a web browser. The user interacts with the browser, which interacts with the server, which interacts with the servlet. Not surprisingly, writing servlets is not like writing applications or applets, but does have the advantage that anyone with a browser can interact remotely with a servlet. Even a browser that does not understand Java can interact with a Java servlet, because the servlet runs on the server.
Because servlets do not interact with the user, they have no visual interface and do not normally contain any visual actors, such as buttons or jugglers. Consequently, the toybox or layout views are not normally used when you are building a servlet. Instead, you use a browser to interact with your servlet. You can use any browser to interact with your servlet. Spin contains a built-in web application server (a web server that can execute middleware applications) that runs your servlet and communicates with a browser.
Notice that the ServerPort is set to 80. By convention, browsers communicate with Web servers over port 80. If you already have a Web server on your computer, you will have to use a different port for Spin's debug Web server. A typical value is port 90 (except on UNIX, where low-numbered port numbers are restricted; use 8080 instead).
Close this window.
Summary of Steps: Enabling the Debug Server
Open a new capsule (choose "New Capsule" from the File menu). In the outline view, the capsule should be selected. If not, click on it to select it. In the Capsule menu, select "Edit Properties" (you can also do this from the right mouse button menu). This brings up a dialog for the properties of the capsule. Change the capsule from an Application to a Java Servlet. Close this window.
Summary of Steps: Set Capsule type to Java Servlet
Now we need to create an HTML document to send to the browser. In the outline view, make sure the capsule is still selected, and from the Insert menu, go down to "zat.html" and select "HTMLDocument". Double click on the icon for the (newly inserted) HTMLDocument, to bring up its editor.
You can set various properties of the HTML document. Many of these are equivalent to options in the HTML <BODY> tag. At the very least, set the Title (equivalent to the HTML <TITLE> tag) to "hello". You can also set the background color, or the color of various kinds of links. When you are done, click "OK" to close this window.
Summary of Steps: HTML Document
Next, insert an HTMLText actor as the child of the HTMLDocument. Double click on its icon, and change its "Text" property to "hello, world!".
Summary of Steps: HTML Text Component
Your capsule should look like this:
As mentioned earlier, the browser interacts with the servlet using CGI and HTML. When our servlet receives a CGI "Get" request, we want to send the HTML document back to the browser. Since this is a common thing to do, we have a special user behavior for it. Select the HTML document, then from the insert menu under "User Behavior", select the "ServletGet" behavior. This inserts "ServletGet" as a child of the HTML document.
Summary of Steps: ServletGet behavior
Open up any web browser and type in the URL "http://localhost". If you changed the ServerPort from Spin's DebugServer preferences, then you will need to specify the port as part of the URL. The port number follows the machine name, separated by a colon. For example, if you are using port 90, then the URL should be "http://localhost:90"
The browser should put up a page that starts with "ZatServer Results". Near the bottom of the page will be a link with the name "Servlet: hello" (followed by a button). Click on this link (not the button), and you will get a web page that says "hello, world!".
You can also invoke the servlet directly, using the URL http://localhost/servlet/hello (assuming you have not changed any DebugServer preferences).
If you had not saved the capsule, the link would have appeared as "Servlet: Capsule" instead of "Servlet: hello". You can always run a servlet even if you have not saved it (but it is always a good idea to save your work frequently).
The ServletGet behavior activates on capsule.ServletRequest.doGet. This causes the action group to activate when the servlet receives a CGI "Get" request.
ServletGet is an ActionGroup with two children. Both of these children are action behaviors that activate on parent.behavior.activated (when its parent ActionGroup is activated).
The setContent behavior, when activated, sends to the capsule the message setResponseContentTypeToTextHTML. This tells the servlet that the response is going to be a text document in HTML format.
The sendDocument behavior, when activated, sends to its actor (which is an HTMLDocument), the message "print". You will find the "print" message in the zat.html.HTMLElement submenu. The "print" message takes a single argument, a PrintWriter. The argument is set to getWriter(), which gets the PrintWriter that was passed with the Get request. This PrintWriter prints to our browser.
When the servlet receives a GET request, the ServletGet behavior prints the HTML document and sends it to the browser.
You can also save your servlet as a jar file, and install it on a servlet-enabled web server. You will also need to install the files zat.jar, zatlib.jar, and zatservlet.jar in the CLASSPATH of the web server. Instructions on how to do this are in the manual "Deploying Spin Projects".
When you deploy your servlet as a jar file, you will usually remove the .jar suffix. Alternatively, some web servers allow you to assign aliases to servlets, so you can leave the .jar suffix on your servlet, and choose an arbitrary URL to invoke it.
Insert an HTMLHeading actor as a child of the HTMLDocument actor. Then drag the HTMLText bean to make it a child of the HTMLHeading (you can do this by just dropping the icon of the HTMLText actor onto the icon of the HTMLHeading actor, or you can use the "cut" and "paste" commands in the Edit menu).
Now click on "Reload" (or "Refresh") on your broswer, and the text "hello, world!" will appear in a larger font. You can change the size of the font by changing the heading level. Just double click on the HTMLHeading actor's icon to edit it.
The correspondence between Spin's HTML actor beans and HTML tags is documented in "Building Servlets with Spin". Spin's HTML components support all tags in HTML 3.2, but if you want to use any tag that is not directly supported, you can enter it into an HTMLText bean and set the HTML property to true.
Add a string variable (from the "Data Item" submenu of the Insert menu) as a child of the capsule, and change its name to "username". We are going to use this variable to hold the name of the user.
Change the name of the ActionGroup behavior from "ServletGet" to "ServletPost". Double click on it and edit it so that it is activated on capsule.ServletRequest.doPost (instead of doGet).
Add a new action behavior as a child of the ServletPost group. New children are always added to the end of the list of children, but we need we need this action to be executed first, so move it up so it is the first child of the postAction (use the "Move Up" command in the Outline menu, or the Ctrl-U keyboard shortcut).
Change the name of this action to "setName". Edit the behavior so it looks like this:
This behavior sets the value of the "username" string to be the parameter named "user" passed in with the CGI Post request. Note that you have to edit the "With=" field to set the argument to be the string "user". Also, note that in this behavior the alias "parent" refers to the postAction behavior (the immediate parent of setName).
Save your capsule.
From the Outline menu in the capsule outline view, select "Enable Debugging" from the Debug submenu. A new window, called the Debug Console, will appear. Back in the outline view, click on the string "username" to select it, and then choose "Add Watch Variable" from the Debug submenu of the Outline menu. The variable "username" will appear in the Debug Console.
Now we are ready to test our servlet. In your browser, enter the URL http://localhost:90. This time, instead of clicking on the link for the servlet hello.zat, instead click on the button labeled "Parameters...". This allows you to type in parameters to pass with a Post request. For the first parameter, enter "user" in the first field, and any name (say, "george") in the second field. Now click on the "Post and Run" button to post the information to the web server (running inside Spin).
Back in Spin's outline view, a red arrow will appear to the left of the setName behavior, indicating that execution has stopped just before executing the setName behavior.
Note that the watched variable in the Debug Console has not changed, because the value of the string "username" has not been set yet. However, the single step (right arrow with vertical bar) and play (right arrow) buttons have become enabled in the debug console. Click on the single step button, and the setName behavior will execute, moving the red arrow to the setContent behavior. In the Debug Console, the value of "username" will become "george". So we know that the value of "username" is being assigned properly.
Click on the single step button again to execute the setContent behavior, and a third time to execute the sendDocument behavior. Your browser should now display the message "hello, world!".
Note that debugging is a very new feature in Spin, and there are still a few kinks to work out. In particular, if you run with debugging on for a while, Spin will slow down because of all the garbage (allocated and deallocated variables) generated. Until the Java garbage collector is improved (supposedly due next month from Sun) it is probably best to restart Spin every once in a while when using debugging.
Also, debugging currently only works for servlet capsules, so it cannot be used for applications or applets. For now, you can use the toybox view to help debug those kinds of projects.
We are done debugging our servlet, so turn debugging off by clicking the "Close" button on the Debug Console. This also might be a good time to save your project and restart Spin (after all that debugging).
Now, insert an action behavior as a child of the HTMLuser actor. Set this behavior to activate on "actor.WhenOutput.whenOutput", which tells this behavior to execute just before the HTMLuser bean prints its output. When activated, this behavior will set the text in the HTMLuser bean to be the value of the "username" variable. Fill this behavior out as follows:
Finally, edit the actor named "hello" and change its text from "hello, world!" to "hello, " (include a space after the comma).
That's all there is to it! Go to your browser and run your servlet. Remember to enter the parameter "user" with an appropriate value, like "george". When you click on the "Post and Run" button, after a slight pause for Spin to recompile your servlet, you should see the web page containing "hello, george". Try it a second time with a different name, to see how fast your servlet runs when it doesn't have to be compiled.
Here is our project, showing all Activation events, but only the action target for the (selected) setName behavior.
You can use this feature in conjunction with debugging and single stepping, to show activation events and action targets for each action as it is executed.
First, this is a good time to save the "hello.zac" capsule. Leave open the "hello.zac" capsule we just created, and open a new capsule. Change this capsule to be a Java servlet.
First, insert an HTML document (from zat.html in the Insert menu). You can edit this actor to give it a title, if you wish.
Insert an HTMLForm as a child of the document actor and change its name to "entryForm". Double click on its icon to edit it. Set its action to "hello" and change its HttpMethod to Post. This sets it up so that when the form is submitted, it will make a Post request to the servlet named "hello".
Next, insert an HTMLText actor as a child of entryForm, and change its name to "text". Double click on it to edit it, and set its text to "Please enter your name: " (with a space after the colon).
Now insert two HTMLFormInput actors as children of entryForm, and name them "nameInput" and "button" respectively. The first of these actors, nameInput, will be a text input field. Double click on it to edit it. Set its type to "TEXT" (the default), and set its Name to "user" (recall that is the name that will be used in the Post request). If you want to enter a default name (like "george"), you can set it in the "Value" field.
Close the editor for this actor and double click on the icon for the button actor. Change its Type to "SUBMIT" and the Value to "Proceed" (which will be used by your browser as the label of the button).
Finally, select the HTML doument, and insert a ServletGet behavior as its child.
You're done. Save this servlet as "entry.zac".
Fill in your name and hit the "Proceed" button, and your browser will say hello to you.
This is a simple servlet, but basically all servlets are built this way, receiving CGI Get and Post requests and building HTML dynamically.
Note that entry.zac and hello.zac do not actually have to be two separate servlets. Since one responds to a Get request, and the other responds to a Post request, they could easily be combined into a single servlet.
Here are the two servlets merged into one:
The only required change is to the HTML form "entryForm". Its "Action" property must be changed so instead of invoking a separate servlet named "hello", it invokes itself. Set this property to the filename of the merged servlet (minus the ".zac").
There is one other change in this version of the servlet. Notice the IfText behavior at the end of the postAction group. This behavior tests to see if the user entered a name (by testing if name.length() == 0). If the length of the name is not zero, then the normal send behavior is executed. But if the length of the name is zero, then the entryForm is resent to the user, asking them to enter their name. This is one advantage of merging the two servlets.
6 March 2000 wm