i
i
i
i
i
i
i
i
492 19. Building Interactive Graphics Applications
ple, CreateHeroBall, DragHeroBall, and InsertHeroToWorld implement the
nite state diagram of Figure 19.9.
3. Application state changes from application (timer) events. This is a
function that updates the application state resulting from purposeful and
usually synchronous application timer events. For the ball shooting pro-
gram, we update all of the velocities, displace the balls’ positions by the
updated velocities and compute ball-to-ball collisions, as well as remove
off-screen balls.
4. Application state visualization. This is a function that knows how to draw
the application state (e.g., drawing the necessary number of circles at the
corresponding positions). It is expected that a view component will initial-
ize appropriate regions on the application window, set up transformations,
and invoke this function to draw into the initialized region.
It is important to recognize that the user’s asynchronous events are arriving in
between synchronous application timer events. In practice, a user observes an
instantaneous application state (the graphics in the application window) and gen-
erates asynchronous events to alter the application state for the next round of
simulation. For example, a user sees that the HeroBall is about to collide with
another ball and decides to change the HeroBall’s velocity to avoid the collision
that would have happened in the next round of simulation. This means, before
synchronous timer update, we must ensure all existing asynchronous user events
are processed. In addition, the application should provide continuous feedback to
ensure that users are observing an up-to-date application state. This subtle han-
dling of event arrival and processing order is not an issue for simple, single-user
applications like our ball shooting program. On large scale multi-user networked
interactive systems, where input event and output display latencies may be signif-
icant, the UpdateSimulation() function is often divided into pre-update, update,
and post-update.
The View
Figure 19.12 shows the ApplicationView class supporting the two main func-
tionalities of a view component: coordinate space transformation and initializa-
tion for redraw. As discussed earlier, the controller is responsible for calling the
DeviceToWorldXform() to communicate user input points to the model compo-
nent. The viewport class is introduced to encapsulate the highly API-dependent
device initialization and transformation procedures.
i
i
i
i
i
i
i
i
19.3. The Modelview-Controller Architecture 493
class Viewport {
private:
// An area on application window for drawing.
// Actual implemenation of the viewport is GraphicsAPI dependent.
public:
void EraseViewport()
// Erase the area on the application window
void ActivateViewportForDrawing()
// All subsequent Graphics API draw commands
// will show up on this viewport
}
class ApplicationView {
private:
// a view’s private state information
Viewport TargetDrawArea
// An area of the application main window that
// this view will be drawing to
public:
void DeviceToWorldXform( inputDevicePoint, outputModelPoint)
// transform the input device coordinate point to
// output point in a coordinate system that the model understands
void DrawView( ApplicationModel TheModel)
// Erase and activate the TargetDrawArea and then
// Sets up transformation for TheModel
// calls TheModel.DrawApplicationState() to draw all the balls.
}
Figure 19.12. The view component of the ball shooting program.
The Controllers
We can improve the solution of Figure 19.8 to better support the specied func-
tionality of the ball shooting program. Recall that the application window de-
picted in Figure 19.2 has two distinct regions for interpreting events: the upper
application drawing area where mouse button events are associated with den-
ing/selecting the HeroBall and the lower GUI element area where mouse button
events on the GUI elements have different meanings (e.g., mouse button events
on the slider bars generate SliderBarChange events, etc.). We also notice that the
upper application drawing area is the exact same area where the ApplicationView
must direct the drawings of the ApplicationModel state.
Figure 19.13 introduces two types of controller classes: a ViewController and
a GenericController. Each controller class is dedicated to receiving input events
from the corresponding region on the application window. The ViewController
creates an ApplicationView during initialization such that the view can be tightly
paired for drawing of the ApplicationModel state in the same area. In addition,
the ViewController class also denes the appropriatemouse event service routines
to support the interaction with the HeroBall. The GenericController is meant to
contain GUI elements for interacting with the application state.
i
i
i
i
i
i
i
i
494 19. Building Interactive Graphics Applications
class ViewController {
private:
ApplicationModel TheModel = null // Reference to the application state
ApplicationView TheView = null // for drawing to the desirable region
public:
void InitializeController(ApplicationMode aModel, anArea) {
// Define and initialize the Application State
TheModel = aModel
TheView = new ApplicationView( anArea )
// Register Event Service Routines
GUISystem::RegisterServiceRoutine(GUISystem:: LMBDown, LMBDownRoutine)
GUISystem::RegisterServiceRoutine(GUISystem:: LMBDrag, LMBDragRoutine)
GUISystem::RegisterServiceRoutine(GUISystem:: LMBUp, LMBUpRoutine)
GUISystem::RegisterServiceRoutine(GUISystem:: RMBDown, RMBDownRoutine)
GUISystem::RegisterServiceRoutine(GUISystem:: RedrawEvent, RedrawRoutine)
}
// Event Service Routines
// … define the 5 event routines similar to the ones in Figure 8 …
}
class GenericController {
private:
ApplicationModel TheModel = null // Reference to the application state
public:
void InitializeController(ApplicationModel aModel, anArea) {
TheModel = aModel
// Register Event Service Routines
GUISystem::RegisterServiceRoutine(GUISystem:: SliderBar, SliderBarRoutine)
GUISystem::DefineTimerPeriod(SimulationUpdateInterval)
GUISystem::RegisterServiceRoutine(GUISystem:: TimerEvent, ServiceTimer)
}
// Event Service Routines
// … define the 2 event routines similar to the ones in Figure 8 …
}
// _______________________________________
// GUI API: MainEventLoop will call this function to initialize our applicaiton
SystemInitialization() {
ApplicationModel
aModel = new ApplicationModel();
ViewController aViewController = new ViewController()
GenericController aGenericController = new GenericController()
aViewController.InitializeController(aModel, drawingAreaOf
Window)
aGenericController.InitializeController(aModel, uiAreaOfWindow)
}
Creates a new
View for the
s
p
ecified area
Application
initialization
An area on the
application
windo
w
Controller with a
View and
Application State
Controller with
no View
Figure 19.13. The controller component of the ball shooting program.
The bottom of Figure 19.13 illustrates that the GUI API MainEventLoop will
still call the SystemInitialization() function to initialize the application. In this
case, we create one instance each of ViewController and GenericController. The
ViewController is initialized to monitor mouse button events in the drawing area
of the application window (e.g., LMB click to dene HeroBall), while the Gener-
icController is initialized to monitor the GUI element state changes (e.g., LMB
dragging of a slider bar). Notice that the service of the timer event is global to the
entire application and should be dened in only one of the controllers (either one
will do).
In practice, the GUI API MainEventLoop dispatches events to the controllers
based on the context of the event. The context of an event is typically dened by
i
i
i
i
i
i
i
i
19.3. The Modelview-Controller Architecture 495
the location of the mouse pointer or the current focus of the GUI element (i.e.,
which element is active). The application is responsible for creating a controller
for any region on the window that it will receive events directly from the GUI
API.
19.3.3 Using the MVC to Expand the Ball Shooting Program
One interesting characteristic of the MVC solution presented in Section 19.3.2
is that the model component does not have any knowledge of the view or the
controller components. This clean interface allows us to expand our solution by
inserting additional view/controller pairs.
For example, Figure 19.14 shows an extension to the ball shooting program
given in Figure 19.2. It has an additional small view in the UI (user interface) area
next to the quit button. The small view is exactly the same as the original large
view, except that it covers a smaller area on the application window.
Figure 19.15 shows that, with our MVC solution design, we can implement
the small view by creating a new instance of ViewController (an additional Ap-
plicaitonView will be created by the ViewController) for the desired application
window area. Notice that the GenericController’s window area actually contains
Ball Shooting Simulation Program
Velocit
y
(X)
12.48 (Pixel/Sec)
Velocit
y
(Y)
9.12 (Pixel/Sec)
Q
UIT
Status:
Small View
window area
Currently there are 5 balls on screen.
Small
View
Original
Large View
Figure 19.14. The ball shooting program with large and small views.
i
i
i
i
i
i
i
i
496 19. Building Interactive Graphics Applications
//
_______________________________________
// GUI API: MainEventLoop will call this function to initialize our applicaiton
SystemInitialization() {
ApplicationModel aModel = new ApplicationModel();
ViewController aLargeViewController = new ViewController()
GenericController aGenericController = new GenericController()
aLargeViewController.InitializeController(aModel, drawingAreaOfWindow)
aGenericController.InitializeController(aModel, uiAreaOfWindow)
ViewController aSmallViewController = new ViewController()
aSmallViewController.InitializeController(aModel, smallViewDrawingArea)
}
New instance of
ViewController (and
ApplicationView)
Figure 19.15. Implementing the small view for the ball shooting program.
the area of the small ViewController. When a user event is triggered in this area,
the “top-layer” controller (the visible one) will receive the event. After the initial-
ization, the new small view will behave in exactly the same manner as the original
large view.
For simplicity, Figure 19.14 shows two identical view/controller pairs. In gen-
eral, a new view/controller pair is created to present a different visualization of the
application state. For example, with slight modications to the view component’s
transformation functionality, the large view of Figure 19.14 can be congured
into a zoom view and the small view can be congured into a work view,where
the zoom view can zoom into different regions (e.g., around the HeroBall) and the
work view can present the entire application space (e.g., all the free falling balls).
Figure 19.16 shows the components of the solution in Figure 19.15 and how
these components interact. We see that the model component supports the op-
erations of all the view and controller components and yet it does not have any
knowledge of these components. This distinct and simple interface has the fol-
lowing advantages:
1. simplicity. The model component is the core of the application and usually
is the most complicated component. By keeping the design of this compo-
nent independent from any particular controller (user input/events) or view
(specic drawing area), we can avoid unnecessary complexity.
2. po rtability. The controller component typically performs the translation
of user actions to model-specic function calls. The implementation of this
translation is usually simple and specic to the underlying GUI API. Keep-
ing the model clean from the highly API-dependent controller facilitates
portability of a solution to other GUI platforms.
3. expandability. The model component supports changing of its internal
state and understands how to draw its contents. As we have seen (Fig-
..................Content has been hidden....................

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