Chapter 11

Using Shockwave for Data


CONTENTS

Data. It usually means boring information compiled into lists and columns with lots of numbers, letters, and codes for other numbers and letters that can be put together into other lists. It conjures up images of long printouts on continuous-form paper and tedious statements from the days of BASIC.

Actually, computers are used more for information than they are for graphics, games, presentations, and other functions that are more interesting to some of us. You'll see how Lingo can be used as a powerful programming language to sort and display data. This chapter shows you the following:

Linear and Property Lists

Despite the dry nature of data, many people actually kind of like lists-grocery lists, to-do lists, Christmas lists, any kind of list. It feels good to organize things. "Lists" in Lingo allow you to organize a series of items. You might be familiar with the term "array" in other programming languages. This is the same idea-having one variable name with multiple "slots" where you can put information.

Here's an example. Let's say you have 15 names to keep track of. You could store the names by creating lots of variables. You might call them name1, name2, name3, all the way up to name15. But this is like having 15 pieces of paper with one name written on each. Wouldn't it be more practical to have all 15 names written on one piece of paper (figure 11.1)? In Lingo, you can have one list variable that can store all of the names in different positions. They can be retrieved, deleted, added to, sorted, and so on.

Figure 11.1 : Lists help organize information.

Linear Lists

Linear lists consist of a series of single items. The syntax separates the items by commas and encloses them in brackets. The items may be numbers or strings; strings must be surrounded by quotes. For example, the following Lingo statement creates a linear list called shortlist:

set shortlist=[345, 12, "banana", 465.8]

There are four items in the above list (three numbers and a string). Later, to retrieve one of the items, you can identify it by its position in the list. If you want to put the third item into a text field called "screentext" you could use this statement:

put getat(shortlist,3) into field "screentext")

The getat statement requires the name of the list and the position number of the item. In this case, the previous statement would have retrieved item 3, which is "banana," and put it into the specified text field.

To change a specific value within a list, use the setat command. The syntax is:

setat listname, position, newvalue

So in our previous example, to change the second value from 12 to 45, we could use this statement:

setat shortlist, 2, 45

What if you have a list with only four items, but you want to add more to it? Easy. There are several ways of doing so. For now we'll show you the append command, which adds an item to the end of a list.

Append listname, newitem

If I wanted to add the string "blah" to my above shortlist, I would type:

append shortlist, "blah"

Other commands used with lists are "listed" (pardon the pun!) at the end of this chapter.

Property Lists

Property lists are similar to linear lists, but contain two pieces of information for each item: a property and a value for that property. For example, a list variable called "boxlist" contains a series of properties that you can later retrieve:

set boxlist=[height:80, width:125, color:34]

Then when you want to know a certain property of "boxlist," you can phrase this nice Lingo sentence:

set newvariable=the width of boxlist

The above statement sets a new local variable equal to 125, the value of the property "width" of the list "boxlist."

Changing a property is just as easy. To change the color from 34 to 80:

set the color of boxlist to 80

To add a new property to the list, you can use the addprop command.

Addprop listname,#newpropname,value

So, in our example, to add a property called "spblend" to "boxlist," you could use the following Lingo statement. Note that you must have a pound sign (#) before the property name or Lingo thinks you are specifying a variable.
If there is no such variable, a void entry is added to the list.

Addprop boxlist,#spblend,50

Graphing Information

This section will offer an example using a list to graph information. Open the file graph.dir from the CD-ROM. The movie accepts a series of values and puts them into a list. The user can add and change up to 30 values that will be plotted as a line graph.

The basic structure uses a linear list. You enter a value into an editable text field (figure 11.2). You may step forward or backward in the list and view your entries. Every time you step forward, if there is no entry already in the list, a new one is created.

Figure 11.2 : Accepting values in a list for a line graph.

When you have finished entering values, a script processes the information and turns the values into positions on a graph and connects segments between them.

Setting Up the Stage

There are a variety of parts that need to be set up for this graphing movie. Some parts are visible, some are invisible.

Two text fields are placed on the stage-one that's editable for the user to enter values, and one that specifies the number of the entry in the list. Two buttons are available to move forward or backward in the list of entries. If the user wants to enter eight values to be graphed, he or she can move up and down from one to eight in the list to view or change the values.

At the bottom of the screen are horizontal and vertical axes. Labels on the vertical side show 0, 50, and 100. This is only temporary. The text fields are titled "high," "low," and "mid." When the program graphs the information, it puts the highest value in the "high" field, the lowest value in the "low" field, and the median value in the "mid" field. This way the user can enter any values and the graph will be scaled appropriately.

Puppets

To have an actual line for each value in the list, you need to use puppet-sprites. The cast member used is a segment created with Director's line tool. To set up the score for puppets, I put the same cast member in the same position for sprites 10 through 40; this allows for 30 possible entries in the list. The position is off the stage so that they are not seen before they are plotted. Your Lingo script will later move each one into its proper position.

Entering Values in the List

The list is initiated in a movie script. It starts out with only one value, zero. There are two global variables-the list itself and a second variable that keeps track of the position in the list. The movie script looks like this:

on startmovie
  global graphlist, gnum
  set graphlist=[0]
  set gnum=1
  put gnum into field "valnum"
  put getat(graphlist,gnum) into field "amount"
end

The two fields are called "valnum" and "amount." The position number (gnum) is always displayed in "valnum" and the actual value is displayed in the field "amount."

A frame script loops while the user enters a value into the "amount" field. The value is not added until one of the buttons is pressed. So, to enter a value and move to the next position in the list, a cast member script looks like this:

on mouseUp
  global graphlist, gnum
  setat graphlist,gnum, integer(field "amount")
  set gnum=gnum+1
  if gnum=31 then set gnum=30
  if gnum>count(graphlist) then setat graphlist,gnum,0
  put getat(graphlist,gnum) into field "amount"
  put gnum into field "valnum"
end

The setat command takes the number from "amount" and puts it into the list at the position specified by "gnum," which is the current position in the list. Then "gnum" is incremented by one, but it can't go past 30 because that is the maximum number of puppets prepared. The fifth line in the script checks the number of entries in the list. If this is a new entry ("gnum" is greater than the total number of entries), it creates a position and sets the value to zero until the user enters a new one. If the position already exists ("gnum" is not greater than the total number of entries), a new entry is not made. Finally the amount and position number are updated in their appropriate fields on the stage.

The "back" button works the same way, but decreases "gnum" by one and doesn't check for a new entry, because the user would be backtracking over values already entered. You can view the script on your own to see how it's written. Figure 11.3 shows the screen where the user enters values.

Figure 11.3 : Moving forwards and backwards in the list of values.

The "graph" button contains the following script:

on mouseUp
  global graphlist, gnum
  setat graphlist,gnum,integer(field"amount")
  if count(graphlist)<>1 then go "graph"
  else 
    put "Cannot graph only 1 item." into field "message"
    starttimer
    repeat while the timer<60*2
      nothing
    end repeat
    put "" into field "message"
  end if
end

The script sets the last value entered in the list at the current position. It checks to make sure there is more than one value in the list, then jumps to the frame marked "graph" where the information is processed and plotted. If only one value is in the list, a message alerts the user and the frame stays the same.

Graphing the Data

The first frame in the graphing section sets up the correct number of puppets. Here is the frame script:

on exitFrame
  global graphlist
  set x=count(graphlist)
  repeat with n=10 to (10+x)
    puppetsprite n, true
  end repeat
end

Using the function "count(graphlist)" you put the total number of entries into a local variable, x. Set up a repeat loop to puppet the correct number of sprites, starting at 10, because that is the channel number in which you began putting segment cast members.

The next frame contains the real monster script that plots the information. It looks like this:

on exitFrame
  global graphlist
  set x=count(graphlist)
  --determine how wide each segment should be on horizontal scale
  set width=integer(325/x)
  --determine max value and pixel percentage for vertical scale
  set vmax=max(graphlist)
  set vmin=min(graphlist)
  set pixpercent=175.0/(vmax-vmin)
  set offset=integer(vmin*pixpercent)
  put vmax into field "high"
  put vmin into field "low"
  put (vmax+vmin)/2 into field "mid"
  --set each segment to the proper position
  set leftpos=65
  repeat with n=1 to count(graphlist)-1
    set rightpos=leftpos+width
    --checks if the line should go up
    if getat(graphlist,n+1)>getat(graphlist,n) then
      set the castnum of sprite n+10 to 14
      set botpos=275-integer(getat(graphlist,n)*pixpercent)+offset
      set toppos=275-integer(getat(graphlist,n+1)*pixpercent)+offset
    else  --the line must go down
      set the castnum of sprite n+10 to 15
      set toppos=275-integer(getat(graphlist,n)*pixpercent)+offset
      set botpos=275-integer(getat(graphlist,n+1)*pixpercent)+offset
    end if
    --in case the line is perfectly horizontal
    if getat(graphlist,n)=getat(graphlist,n+1) then
      set the castnum of sprite n+10 to 16
      set botpos=276-integer(getat(graphlist,n)*pixpercent)+offset
      set toppos=botpos-3
    end if
    --moves the puppetsprite into the proper position
    set the rect of sprite n+10 to rect(leftpos,toppos,rightpos,botpos)
    updatestage
    set leftpos=leftpos+width
  end repeat
end

Looks like a big mess, huh? I'm always impressed with how fancy a big script looks when its finished, although when you take it apart it's very logical in construction.

The first thing is to determine how wide each segment should be. If the user entered three values, the segments should be very wide; with 25 values, the segments need to be narrower. I decided ahead of time to make the total width of the graph 325 pixels. So, the width of each segment should be 325 divided by the number of segments, which is our variable x.

Next, you have to set the vertical scale. The max command will return the highest value in a list. Likewise, the min command returns the lowest value. I put the highest value in the field called "high," the lowest value in the field "low," and a median value in the field called "mid."

I created a variable called pixpercent that gives the proper percentage to scale the data to the graph. The height of the graph area would be 175 pixels. So by dividing 175 by the maximum value, you get a number to use later in scaling the data.

Note
If you want to know where this equation comes from, get out your algebra book. 175 is the highest pixel height of the graph. Vmax is the maximum value in the list, which you want to be the highest point on the graph. So what value can you multiply vmax by to get it to be 175 pixels?
Vmax * x=175
Solving for x gives the equation: x=175/vmax
Once you know this value, you can use it to multiply with any item in the list to get the correct scaled value.

The offset variable is the pixel amount that each plotted point doesn't need. Because you're starting the vertical axis at the lowest value in the list instead of at zero, you have to offset each item by this amount.

Now you're ready to set the locations of each segment. You have to specify the left, top, right, and bottom positions in pixel coordinates. Left and right are easy. I started the left value at pixel 65. The right value just adds the width variable to the left value.

Top and bottom values are trickier. One value will be the height of the current number in the list, the other value will be the height of the next number in the list so that the segments connect. But depending on whether the next number is higher or lower, you need to use a different cast member. One member is a segment that goes upward, one is a segment that goes downward, a third cast member is a rectangle in case the numbers stay identical.

If the next item in the list is higher than the current one, then the line goes up, the bottom value is the current item and the top value is the next item.If the next item in the list is lower than the current one, then the line goes down, the top value is the current item and the bottom value is the next item.

The item is multiplied by the pixpercent variable and subtracted from 275, which is the vertical location of the bottom of the graph (pixels count with zero at the top of the screen and increase as they go down). Then the offset amount is readded to this value to take into consideration that the graph doesn't start at zero.

If this is confusing you, don't worry about it-it's a bit tough to hack through this programming situation. The more experience you have, the easier it is to understand.

Once the left, right, top, and bottom values are found, a puppetsprite is modified to show up on the graph. Then the left value is incremented and the loop repeats with the next item in the list.

The next frame waits for the user to change the data or reset the graph and start over with an empty list.

That's the end of the graphing movie. Fairly simple to look at, but it uses some tricky Lingo. The usefulness of this as a Shockwave movie may be limited, but what if you used a getnettext command to retrieve a text file from the Internet that contains graph data? Every day the information could change and a new graph could be displayed. Stock prices, sales information, just about anything could be graphed (see figure 11.4: URL isn't real). And this is just a small example. The power of Lingo as a programming language continues.

Figure 11.4 : Using Shockwave to graph stock information.

Other List Commands

There are many ways you can manipulate linear and property lists. Table 11.1 describes some of the basic commands used with lists.

Table 11.1  Commands Used with Lists

Lingo CommandDescription
append listname, value Adds an item to the end of a list
add listname, value Adds an item in proper sorted position
addprop list, prop, value Adds an item to a property list
addat list, position, value Adds an item in a particular position
count(listname) Returns total number of items in list
deleteat list, position Deletes an item from a linear list
deleteprop list, prop Deletes an item from a property list
getat(list, position) Returns an item from the list
getprop(list,position) Returns value of a property in a list
getpropat(list,position) Returns property name of position
min(listname) Returns minimum value in list
max(listname) Returns maximum value in list
sort(listname) Sorts list in alphanumeric order
setat list,pos,value Changes an item in a linear list
setprop list,prop,value Changes an item in a property list

See the Lingo Dictionary and users guide for more about working with lists.

Further Ideas

Once you begin to work with advanced Lingo functions, you will see many opportunities to incorporate Shockwave movies to your Web site.

Perhaps you could have a large corporate telephone directory that lets the user search by name or department and displays phone, fax, e-mail, and other information (figure 11.5). Instead of using CGI scripts for searches and filling up Web pages with lists of information, you can create a Shockwave movie that stores and organizes it.

Figure 11.5 : Using Shockwave to store and display a company directory.

Another business application could be ordering products online. A Shock-wave movie could display images of the products along with descriptions of each. The user could select items and the movie could add their total bill and compute the sales tax. When the whole shopping list is completed a CGI script could be used to actually transmit the order to your company (figure 11.6).

Figure 11.6 : Using Shockwave to order products online.

These suggestions are business oriented, since data functions tend to be related to business. But you could use Shockwave for just about any application. Your own imagination will be the limit of what Shockwave can do for you.

From Here…

Programming in Lingo allows you to use Shockwave for some very advanced data processing functions, if you are willing to learn to use it. Hopefully, you can think of a variety of other functional purposes for Shockwave movies involving data. The next few chapters focus more on Lingo, including some basics for beginners as well as new network Lingo for Shockwave.