uti_pointerarray m_subwins;
uti_rectangle m_position;
// active and inactive colorsets
gui_wincolor m_activecolor;
gui_wincolor m_inactivecolor;
// window caption
uti_string m_caption;
};
First of all, notice the virtual destructor on the window class. This may not seem like it’s needed just yet, but we’ll eventually be deriving controls from this class, so it’s important that it have a virtual destructor.
As you peruse the functions we’ll be talking about, keep in mind that recursion is everywhere. For example, our game will be drawing the entire GUI system by making a call to the renderall() method of the root window, which will in turn call the renderall() methods of its subwindows, which will call renderall() for their subwindows, and so on. Most of the functions follow this recursive pattern.
The whole GUI system will be contained within one global static variable - the root window. To be on the safe side, I encapsulated this variable within a global GetDesktop() function.
Also, notice that the class definition is rife with virtual keywords. This is where C++’s polymorphism is working for us. Need to change how certain types of windows (or controls - say, buttons) deal with a “left mouse button has just been pushed down” event? Simple, derive a class from the base window and override its wm_lbuttondown() method. The system will automatically call the derived class’s method where appropriate; behold the power of C++.
Now that we’ve got the header, let’s start filling in some functions, starting with the Window Management code…
Window Management Code
/****************************************************************************
addwindow: adds a window to this window's subwin array
****************************************************************************/
int gui_window::addwindow(gui_window *w) {
if (!w) return(-1);
// only add it if it isn't already in our window list.
if (m_subwins.find(w) == -1) m_subwins.add(w);
w-›setparent(this);
return(0);
}
/****************************************************************************
removewindow: removes a window from this window's subwin array
****************************************************************************/
int gui_window::removewindow(gui_window *w) {
w-›setparent(NULL);
return (m_subwins.findandremove(w));
}
/****************************************************************************
bringtotop: bring this window to the top of the z-order. the top of the
z-order is the HIGHEST index in the subwin array.
****************************************************************************/
void gui_window::bringtotop(void) {
if (m_parent) {
// we gotta save the old parent so we know who to add back to
gui_window *p = m_parent;
p-›removewindow(this);
p-›addwindow(this);
}
}
/****************************************************************************
isactive: returns true if this window is the active one (the one with input focus).
****************************************************************************/
bool gui_window::isactive(void) {
if (!m_parent) return(1);
if (!m_parent-›isactive()) return(0);
return(this == m_parent-›m_subwins.getat(m_parent-›m_subwins.getsize()-1));
}