1\section{The Main Menu View}
2
3The namespace inside the MainMenu view class is a concatenation
4of the general namespace and the name of the MainMenu view
5class.
6<<MainMenuVNameSpace>>=
7<<NameSpace>>::MainMenuView
8@
9
10The main menu defines all of the games selectable from the main
11menu.  This ordering is used in the arrays of images and bounding
12boxes below.  The ordering is also used by the main menu controller
13to tell the main loop when to switch to a different game mode.
14<<MainMenu Games>>=
15    enum {
16	FLIPFLOP = 0,
17	BOMBSQUAD,
18	MAZERUNNER,
19	PEGJUMPER,
20	TILESLIDER,
21	MAX_GAME
22    };
23@
24
25The Main Menu stores pointers to the images of the sidebar,
26the backdrop, and the button overlay.
27<<MainMenu Images>>=
28    SDL_Surface* sidebar;
29    SDL_Surface* backdrop;
30    SDL_Surface* overlay;
31@
32
33The Main Menu stores pointers to the images of the game logos
34to use.
35<<MainMenu Images>>=
36    SDL_Surface* logos[ MAX_GAME ];
37@
38
39The Main Menu view class also stores the images used as a backdrop
40for the quit button.
41<<MainMenu Images>>=
42    SDL_Surface* quitButton[2];
43@
44
45In addition to that, it also keeps track of where the quit button
46is on the screen and whether it is pressed or not.
47<<MainMenu Box Declarations>>=
48    static SDL_Rect quitBox;
49@
50<<MainMenu Box Definitions>>=
51    SDL_Rect <<MainMenuVNameSpace>>::quitBox = {
52	<<ViewNameSpace>>::SIDEBAR_X + 2,
53	<<ViewNameSpace>>::SIDEBAR_Y + 534,
54	196, 64
55    };
56@
57<<MainMenu Quit State>>=
58    bool quitPressed;
59@
60
61The Main Menu also caches a pointer to the screen.
62<<MainMenu Screen>>=
63    SDL_Surface* screen;
64@
65
66The Main Menu also tracks the bounding boxes of each of
67the above logos.
68<<MainMenu Box Declarations>>=
69    static SDL_Rect boxes[ MAX_GAME ];
70@
71<<MainMenu Box Definitions>>=
72    SDL_Rect <<MainMenuVNameSpace>>::boxes[ MAX_GAME ] = {
73	{   0,   0, 300, 200 },
74	{ 300,   0, 300, 200 },
75	{ 150, 200, 300, 200 },
76	{   0, 400, 300, 200 },
77	{ 300, 400, 300, 200 },
78    };
79@
80
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82\subsection{The Constructor}
83
84The constructor for the MainMenu view class takes one argument---a
85pointer to the screen.
86<<MainMenuV Constructor Declaration>>=
87    MainMenuView( SDL_Surface* _screen );
88@
89
90The constructor for the MainMenu view class loads the images for
91the sidebar and quit button and for each of the games.
92<<MainMenuV Constructor Implementation>>=
93    <<MainMenuVNameSpace>>::MainMenuView(
94	    SDL_Surface* _screen
95	) : quitPressed( false ), screen( _screen )
96    {
97	<<MainMenuV Load Base Images>>
98	<<MainMenuV Load Logo Images>>
99    }
100@
101
102There are images for the backdrop of the sidebar, the
103backdrop of the game, the overlay over the sidebar buttons,
104and the quit button in the up and down states.
105<<MainMenuV Load Base Images>>=
106    this->sidebar = ::IMG_Load( "../../data/panel.png" );
107    this->backdrop = ::IMG_Load( "../../data/backdrop.png" );
108    this->overlay = ::IMG_Load( "../../data/moverlay.png" );
109    this->quitButton[ 0 ] = ::IMG_Load( "../../data/helpOff.png" );
110    this->quitButton[ 1 ] = ::IMG_Load( "../../data/helpOn.png" );
111@
112
113There are also logos for each of the games available from
114the main menu.
115<<MainMenuV Load Logo Images>>=
116    this->logos[ FLIPFLOP ]
117	= ::IMG_Load( "../../data/flogo.png" );
118    this->logos[ BOMBSQUAD ]
119	= ::IMG_Load( "../../data/blogo.png" );
120    this->logos[ MAZERUNNER ]
121	= ::IMG_Load( "../../data/mlogo.png" );
122    this->logos[ PEGJUMPER ]
123	= ::IMG_Load( "../../data/plogo.png" );
124    this->logos[ TILESLIDER ]
125	= ::IMG_Load( "../../data/tlogo.png" );
126@
127
128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129\subsection{The Destructor}
130
131The destructor for the MainMenu view class simply release
132the images loaded above in the constructor.
133<<MainMenuV Destructor Declaration>>=
134    ~MainMenuView( void );
135@
136<<MainMenuV Destructor Implementation>>=
137    <<MainMenuVNameSpace>>::~MainMenuView( void )
138    {
139	<<MainMenuV Release Logo Images>>
140	<<MainMenuV Release Base Images>>
141    }
142@
143
144Releasing the logo images is easy.  We can just loop
145through each of the logos and release them.
146<<MainMenuV Release Logo Images>>=
147    for ( unsigned int ii=0; ii < MAX_GAME; ++ii ) {
148	::SDL_FreeSurface( this->logos[ ii ] );
149    }
150@
151
152Releasing the base images takes a little more effort.  We have to
153release each image one by one.
154<<MainMenuV Release Base Images>>=
155    ::SDL_FreeSurface( this->quitButton[ 1 ] );
156    ::SDL_FreeSurface( this->quitButton[ 0 ] );
157    ::SDL_FreeSurface( this->overlay );
158    ::SDL_FreeSurface( this->backdrop );
159    ::SDL_FreeSurface( this->sidebar );
160@
161
162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163\subsection{The Redraw Methods}
164
165The MainMenu view class has a method which allows one to update
166the entire display area for the game.
167<<MainMenuV Redraw Declarations>>=
168    void redraw( void ) const;
169@
170
171The redraw function here simply redraws the backdrop and the
172sidebar and each of the game logos.
173<<MainMenuV Redraw Implementations>>=
174    void
175    <<MainMenuVNameSpace>>::redraw( void ) const
176    {
177	SDL_Rect rr;
178	<<MainMenu Redraw Backdrop>>
179	<<MainMenu Redraw Logos>>
180	<<MainMenu Redraw Sidebar>>
181	::SDL_UpdateRect( this->screen, 0, 0, 0, 0 );
182    }
183@
184
185Redrawing the backdrop is simple.  We simply have to copy
186the backdrop onto the screen.
187<<MainMenu Redraw Backdrop>>=
188    ::SDL_BlitSurface( this->backdrop, 0, this->screen, 0 );
189@
190
191To draw the logos for the games onto the screen, we have to
192copy each of them into their appropriate rectangle.
193<<MainMenu Redraw Logos>>=
194    for ( unsigned int ii=0; ii < MAX_GAME; ++ii ) {
195	rr = boxes[ ii ];
196	::SDL_BlitSurface( this->logos[ ii ], 0, this->screen, &rr );
197    }
198@
199
200To draw the sidebar, we first draw the backdrop of the sidebar.
201<<MainMenu Redraw Sidebar>>=
202    rr.x = <<ViewNameSpace>>::SIDEBAR_X;
203    rr.y = <<ViewNameSpace>>::SIDEBAR_Y;
204    ::SDL_BlitSurface( this->sidebar, 0, this->screen, &rr );
205@
206
207After that, we draw the overlay atop the sidebar.
208<<MainMenu Redraw Sidebar>>=
209    rr.x = <<ViewNameSpace>>::SIDEBAR_X;
210    rr.y = <<ViewNameSpace>>::SIDEBAR_Y;
211    ::SDL_BlitSurface( this->overlay, 0, this->screen, &rr );
212@
213
214Then, we redraw the quit button on top of the sidebar.
215<<MainMenu Redraw Sidebar>>=
216    this->redrawQuit( false );
217@
218
219The above draw method and the handler for mouse events both need
220to draw the quit button.  Rather than duplicating code, we have
221broken it out into its own method.
222<<MainMenuV Redraw Declarations>>=
223    void redrawQuit( bool refresh = true ) const;
224@
225
226The method simply picks the appropriate bitmap for the current
227state of the button.  Then, it draws the button.  Then, it copies
228the portion of the overlay that would otherwise have been atop
229the button.  Then, if it is supposed to refresh, it updates the
230appropriate rectangle of the screen.
231<<MainMenuV Redraw Implementations>>=
232    void
233    <<MainMenuVNameSpace>>::redrawQuit( bool refresh ) const
234    {
235	unsigned int index = ( ! this->quitPressed ) ? 0 : 1 ;
236	SDL_Surface* button = this->quitButton[ index ];
237	::SDL_BlitSurface( button, 0, this->screen, &quitBox );
238
239	<<MainMenuV Redraw Quit Show Overlay>>
240
241	if ( refresh ) {
242	    ::SDL_UpdateRect(
243		    this->screen,
244		    quitBox.x, quitBox.y,
245		    quitBox.w, quitBox.h
246		);
247	}
248    }
249@
250
251Because the overlay is the same size as the sidebar, we have to
252take extra care to make sure that we're copying the right portion
253of it onto the button.
254<<MainMenuV Redraw Quit Show Overlay>>=
255    SDL_Rect rr = quitBox;
256    rr.x -= <<ViewNameSpace>>::SIDEBAR_X;
257    rr.y -= <<ViewNameSpace>>::SIDEBAR_Y;
258    ::SDL_BlitSurface( this->overlay, &rr, this->screen, &quitBox );
259@
260
261
262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263\subsection{Handling Mouse Clicks}
264
265When the Main Menu controller receives a mouse click, it passes it
266on to the [[MainMenuView]] class.  The view class is responsible
267for determining if the quit button was clicked.  If it was, then
268the quit event is sent out.
269<<MainMenuV Mouse Click Declaration>>=
270    virtual bool handleMouseClick(
271	    Controller* controller,
272	    bool isMouseUp,
273	    unsigned int xx,
274	    unsigned int yy,
275	    unsigned int buttonNumber
276	);
277@
278
279This method checks to see if the event happened inside the quit
280button.  If we hit the quit button with a mouse down event, then
281we put the quit button into the ``pressed'' state.  Otherwise,
282if the quit button had already been pressed, we put it back
283into the ``unpressed'' state if the event is a mouse up event
284and we actually quit if the mouse up event happened inside of
285the pressed quit button.
286<<MainMenuV Mouse Click Implementation>>=
287    bool
288    <<MainMenuVNameSpace>>::handleMouseClick(
289	    Controller* control,
290	    bool isMouseUp,
291	    unsigned int xx,
292	    unsigned int yy,
293	    unsigned int buttonNumber
294	)
295    {
296	<<MainMenuV MouseClick Check Quit Button>>
297
298	if ( hitQuit && ! isMouseUp ) {
299	    <<MainMenuV MouseClick Press Quit>>
300	} else if ( this->quitPressed )  {
301	    if ( isMouseUp ) {
302		<<MainMenuV MouseClick Unpress Quit>>
303	    }
304	    if ( hitQuit ) {
305		<<MainMenuV MouseClick Perform Quit>>
306	    }
307	}
308
309	return hitQuit;
310    }
311@
312
313Checking to see if the mouse event happened inside the quit button
314is a straightforward check of the coordinates with the bounds of
315the quit button.
316<<MainMenuV MouseClick Check Quit Button>>=
317    bool hitQuit = (
318	       xx >= quitBox.x && xx < quitBox.x + quitBox.w
319	    && yy >= quitBox.y && yy < quitBox.y + quitBox.h
320	);
321@
322
323To set the button into the pressed mode, we mark it as
324pressed and redraw it.
325<<MainMenuV MouseClick Press Quit>>=
326    this->quitPressed = true;
327    this->redrawQuit();
328@
329
330To set the button into the unpressed mode, we mark it as
331unpressed and redraw it.
332<<MainMenuV MouseClick Unpress Quit>>=
333    this->quitPressed = false;
334    this->redrawQuit();
335@
336
337If someone pressed and then released the mouse within the
338quit button, then we actually send off the SDL event to
339signal a quit.
340<<MainMenuV MouseClick Perform Quit>>=
341    SDL_Event quit;
342    quit.type = SDL_QUIT;
343    ::SDL_PushEvent( &quit );
344@
345
346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347\subsection{The Point in Box Method}
348
349The controller uses this method to see if the given point is
350inside a particular game's bounding box.
351<<MainMenu Point In Box Declaration>>=
352    bool pointInBox(
353	    unsigned int xx, unsigned int yy,
354	    unsigned int game
355	) const;
356@
357
358The method itself simply compares the coordinates with those of
359the box in question.
360<<MainMenu Point In Box Implementation>>=
361    bool
362    <<MainMenuVNameSpace>>::pointInBox(
363	    unsigned int xx, unsigned int yy,
364	    unsigned int game
365	) const
366    {
367	assert( game < MAX_GAME );
368	return xx >= boxes[ game ].x
369	    && xx <  boxes[ game ].x + boxes[ game ].w
370	    && yy >= boxes[ game ].y
371	    && yy <  boxes[ game ].y + boxes[ game ].h;
372    }
373@
374
375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376\subsection{The [[MainMenuView]] class}
377
378In this section, we assemble the [[MainMenuView]] class from
379the pieces in the sections above.
380
381We start off the [[MainMenuView]] class with the declaration
382of which games are supported.
383<<MainMenuV Class Definition>>=
384    public:
385	<<MainMenu Games>>
386@
387
388We include, in the [[MainMenuView]] class, the constructor,
389the destructor, and the redraw methods.
390<<MainMenuV Class Definition>>=
391    public:
392	<<MainMenuV Constructor Declaration>>
393	<<MainMenuV Destructor Declaration>>
394	<<MainMenuV Redraw Declarations>>
395@
396
397The [[MainMenuView]] class then includes the declaration
398of the method used to see if a particular button was clicked
399and the declaration of the method used to field clicks on the
400quit button.
401<<MainMenuV Class Definition>>=
402    public:
403	<<MainMenu Point In Box Declaration>>
404	<<MainMenuV Mouse Click Declaration>>
405@
406
407We include the variables that are used in the main menu view class.
408<<MainMenuV Class Definition>>=
409    private:
410	<<MainMenu Images>>
411	<<MainMenu Screen>>
412	<<MainMenu Quit State>>
413	<<MainMenu Box Declarations>>
414@
415
416Once these declarations are all done, we throw all of these together
417into the class declaration itself.
418<<MainMenuV Class Declaration>>=
419    class MainMenuView {
420	<<MainMenuV Class Definition>>
421    };
422@ %def MainMenuView
423
424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425\subsection{The [[mainmenuView.h]] file}
426
427In this section, we assemble the header file for the [[MainMenuView]]
428class.  It is really straightforward since we assembled the class
429declaration in the previous section.  The only thing that we add
430to the class declaration is that we tuck it into our own name space
431so that we can keep the global namespace squeaky clean.
432<<mainmenuView.h>>=
433    namespace <<NameSpace>> {
434	<<MainMenuV Class Declaration>>
435    };
436@
437
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439\subsection{The [[mainmenuView.cpp]] file}
440
441In this section, we assemble the MainMenu view source file.  It
442requires the [[SDL]] headers for dealing with surfaces, the screen,
443blitting, and loading images.  It requires the header files for
444the [[Cube]] class, the [[SoundDev]] class, the [[View]] class for
445its constants, and the [[MainMenuView]] class itself.
446<<mainmenuView.cpp>>=
447    #include <assert.h>
448    #include <SDL.h>
449    #include <SDL_image.h>
450    #include "cube.h"
451    #include "soundDev.h"
452    #include "view.h"
453    #include "mainmenuView.h"
454@
455
456After the header files, we include the implementations of the
457constructor, the destructor, and the redraw methods.
458<<mainmenuView.cpp>>=
459    <<MainMenuV Constructor Implementation>>
460    <<MainMenuV Destructor Implementation>>
461    <<MainMenuV Redraw Implementations>>
462@
463
464The main menu source file then goes on to include the
465implementation of the method used to check to see if
466a particular box has been clicked and the implementation
467of the method used to check to see if the quit button
468has been clicked.
469<<mainmenuView.cpp>>=
470    <<MainMenu Point In Box Implementation>>
471    <<MainMenuV Mouse Click Implementation>>
472@
473
474Then, the source file includes the definition of the bounding
475boxes.
476<<mainmenuView.cpp>>=
477    <<MainMenu Box Definitions>>
478@
479