Chapter 16. GraphPaper: A Multithreaded Application with a Display List

In this chapter, we’ll use the Evaluator back end that we built in Chapter 10 as the basis for an application that graphs single-valued functions. By the end of the chapter, the menu bar and main window of the application will look like those shown in Figure 16-1.

The GraphPaper application

Figure 16-1. The GraphPaper application

In the process of developing this program, we’ll learn more about the drawRect: method, see how to construct a complicated image out of many individual pieces, and learn a little bit about threads.

GraphPaper’s Design

Conceptually, our program to graph a function will contain four main parts, as described in the list that follows.

Interface

Lets the user specify the function and graph parameters, and start and stop the graphing process

Pair generator

Takes the graph parameters set by the user and generates pairs of (x,y) points to be plotted

Graph builder

Takes the pairs from the pair generator and builds the graph’s data structure

Graph displayer

Takes the data structure and displays it on the screen

The Interface

We’ll build GraphPaper’s interface with Interface Builder (of course!). The interface will consist of a Cocoa NSForm object containing several text fields (“xmin”, “ymax”, etc., as shown in Figure 16-1), a button (labeled “Graph”) to start the graphing process, and a custom NSView called the GraphView. The GraphView object will be the overall controller of the GraphPaper application.

Connecting to the Back End

When GraphPaper starts up, a GraphView object will be instantiated. The GraphView object will then start up a single copy of the Evaluator program (as MathPaper did in Chapter 11). When the user clicks the Graph button in GraphPaper’s main window, the GraphView object will first check to make sure that all of the graph parameters make sense. It will then start up a second task (called a thread ) that will send pairs of numeric algebraic expressions to Evaluator for processing. Each of these numeric algebraic pairs corresponds to an (x,y) pair.

Because Evaluator doesn’t know how to process variables, GraphView will substitute the value of the variable x for the letter “x” for every point that it graphs before it sends it to Evaluator. That’s what we mean when we say “numeric” algebraic pairs. For example, suppose the user wants to graph the following equation:

y(x) = 2*x + 1

over the range of 0 to 10 with a step of 1. GraphView’s subsidiary thread will send the following sequence of 11 pairs to Evaluator:

0, 2*0+1
1, 2*1+1
2, 2*2+1
...
10, 2*10+1

Evaluator, in turn, will evaluate each of these expressions and send them back in a format like this:

0, 1
1, 3
2, 5
...
10, 21

The GraphView object will also “watch” for the results from Evaluator and incorporate them into a data structure called a display list . The display list that GraphView will use is a Cocoa NSMutableArray object, which will contain an array (list) of objects. Each object in this list will know how to respond to two methods: bounds and stroke . We will have to implement these methods for each class whose members we want to put into the display list.

When an object in the display list receives the bounds message, the object returns a pointer to an NSRect structure that describes the object’s size and position. When an object in the display list receives a stroke message, it generates the appropriate Quartz calls to draw itself.

Initially, we’ll have only one kind of object that can be put into the display list, a Segment object. Each Segment object will be used to represent a line segment of the final plot, from one (x,y) pair to another. In addition to responding to the bounds and stroke messages, the Segment class that we’ll create will have a special initFrom:to: method for initialization.

Why Use a Display List?

The advantage of using a display list of objects, rather than simply an array of (x,y) structures, is the following: we can easily add new kinds of objects to be drawn in the on-screen GraphView by simply creating new classes and inserting instances of those classes into the display list. For example, we might want to add a title to the graph’s background. With the flexibility of the display list, all we have to do is to create a Title class that responds to the same bounds and stroke messages. After we create the new class, it’s easy to integrate its instances into the existing display list.

The GraphView class will manage the display list. When a new object is added to the display list, the GraphView class will indicate that the region occupied by that object needs to be redrawn. Additional methods that we’ll add to the GraphView class will take care of scaling the GraphView’s coordinate system when the view is resized.

The GraphView object also does the actual drawing of the graph, using the drawRect: method. The drawRect: method will look at the rectangle where it has been requested to perform drawing and will send a message to the objects in the display list that intersect that region.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.108.112