Check out the cheap trick I used in the bringtotop() function. Since I know that the window doesn’t own the pointers, I can just clobber the window and then immediate re-add him, effectively repositioning him at the top of the array. I did this solely because my pointer class, uti_pointerarray, already had code that would delete an element and slide all higher elements backwards one slot.
So that’s window management. Now, onto the joy of coordinate systems…
Coordinate Systems
/****************************************************************************
virtual coordinate system to graphics card resolution converters
****************************************************************************/
const double GUI_SCALEX = 10000.0;
const double GUI_SCALEY = 10000.0;
int gui_window::virtxtopixels(int virtx) {
int width = (m_parent) ? m_parent-›getpos().getwidth() : getscreendims().getwidth();
return((int)((double)virtx*(double)width/GUI_SCALEX));
}
int gui_window::virtytopixels(int virty) {
int height = (m_parent) ? m_parent-›getpos().getheight() : getscreendims().getheight();
return((int)((double)virty*(double)height/GUI_SCALEY));
}
/****************************************************************************
findchildatcoord: returns the top-most child window at coord (x,y); recursive.
****************************************************************************/
gui_window *gui_window::findchildatcoord(coord x, coord y, int flags) {
for (int q = m_subwins.getsize()-1; q ›= 0; q--) {
gui_window *ww = (gui_window *)m_subwins.getat(q);
if (ww) {
gui_window *found = ww-›findchildatcoord(x-m_position.getx1(), y-m_position.gety1(), flags);
if (found) return(found);
}
}
// check to see if this window itself is at the coord - this breaks the recursion
if (!getinvisible() && m_position.ispointin(x,y)) return(this);
return(NULL);
}
One of the top priorities for my GUI was resolution independence, and what I call “stretchy dialog boxes.” Basically, I wanted my windows and dialog boxes to scale themselves larger or smaller, depending on the screen resolution of the system they were running on. On systems with higher resolutions, I wanted the windows, controls, etc. to expand; on 640×480, I wanted things to shrink.
What this really meant was that I needed to implement a virtual coordinate system. I based my virtual coordinate system around an arbitrary number - I effectively said, “Henceforth, I will assume that every window is 10,000×10,000 units, regardless of the actual size of that window,” and then let my GUI do the work of scaling the coordinates. For the desktop window, the coordinates are scaled to the physical resolution of the monitor.
I accomplished this through four functions: virtxtopixels(), virtytopixels(), pixelstovirtx(), and pixelstovirty(). (Note: only two are listed in the code; I figured you got the idea). These functions are responsible for converting between the virtual 10,000×10,000 unit coordinates and either the actual dimensions of the parent window, or the physical coordinates of the monitor. Obviously, the rendering functions of the windows use these functions heavily.
The screentoclient() function is responsible for taking an absolute screen position and converting it into relative virtual coordinates. Relative coordinates have their origin at the upper-left of a window; it’s the same idea as world space and object space, in 3D. Relative coordinates are indispensable for dialog boxes.