4 // Graphical User Interface support
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 02/03/2006 Created this file
12 // JLH 03/13/2006 Added functions to allow shutting down GUI externally
17 // - Memory leak on quitting with a window active
18 // - Multiple window handling
22 #include "menu.h" // Element class methods are pulled in here...
28 //#define DEBUG_MAIN_LOOP
30 #ifdef DEBUG_MAIN_LOOP
35 GUI::GUI(SDL_Surface * mainSurface): mainMenu(new Menu()), menuItem(new MenuItems())
37 Element::SetScreen(mainSurface);
49 void GUI::AddMenuTitle(const char * title)
51 menuItem->title = title;
52 menuItem->item.clear();
55 void GUI::AddMenuItem(const char * item, Element * (* a)(void)/*= NULL*/, SDLKey k/*= SDLK_UNKNOWN*/)
57 menuItem->item.push_back(NameAction(item, a, k));
60 void GUI::CommitItemsToMenu(void)
62 mainMenu->Add(*menuItem);
70 bool showMouse = true;
71 int mouseX = 0, mouseY = 0;
72 int oldMouseX = 0, oldMouseY = 0;
73 Element * mainWindow = NULL;
76 SDL_EnableKeyRepeat(150, 75);
78 //Shouldn't we save the state of the GUI instead of doing things this way?
79 //We have a memory leak whenever a mainWindow is active and we quit... !!! FIX !!!
86 if (SDL_PollEvent(&event))
88 #ifdef DEBUG_MAIN_LOOP
89 WriteLog("An event was found!");
91 if (event.type == SDL_USEREVENT)
93 #ifdef DEBUG_MAIN_LOOP
94 WriteLog(" -- SDL_USEREVENT\n");
96 //Mebbe add another user event for screen refresh? Why not!
97 if (event.user.code == WINDOW_CLOSE)
102 else if (event.user.code == MENU_ITEM_CHOSEN)
104 // Confused? Let me enlighten... What we're doing here is casting
105 // data1 as a pointer to a function which returns a Window pointer and
106 // which takes no parameters (the "(Window *(*)(void))" part), then
107 // derefencing it (the "*" in front of that) in order to call the
108 // function that it points to. Clear as mud? Yeah, I hate function
109 // pointers too, but what else are you gonna do?
110 mainWindow = (*(Element *(*)(void))event.user.data1)();
112 while (SDL_PollEvent(&event)); // Flush the event queue...
113 event.type = SDL_MOUSEMOTION;
115 SDL_GetMouseState(&mx, &my);
116 event.motion.x = mx, event.motion.y = my;
117 SDL_PushEvent(&event); // & update mouse position...!
119 oldMouseX = mouseX, oldMouseY = mouseY;
120 mouseX = mx, mouseY = my; // This prevents "mouse flash"...
122 //There's a *small* problem with this approach--if a window and a bunch of child
123 //widgets send this message, we'll get a bunch of unnecessary refresh events...
124 //This could be controlled by having the main window refresh itself intelligently...
126 //What we could do instead is set a variable in Element and check it after the fact
127 //to see whether or not a refresh is needed.
129 //Dirty rectangle is also possible...
130 else if (event.user.code == SCREEN_REFRESH_NEEDED)
131 RenderScreenBuffer();
133 else if (event.type == SDL_ACTIVEEVENT)
135 if (event.active.state == SDL_APPMOUSEFOCUS)
136 showMouse = (event.active.gain ? true : false);
138 else if (event.type == SDL_KEYDOWN)
140 #ifdef DEBUG_MAIN_LOOP
141 WriteLog(" -- SDL_KEYDOWN\n");
143 if (event.key.keysym.sym == SDLK_F5)
147 mainWindow->HandleKey(event.key.keysym.sym);
149 mainMenu->HandleKey(event.key.keysym.sym);
151 else if (event.type == SDL_MOUSEMOTION)
153 #ifdef DEBUG_MAIN_LOOP
154 WriteLog(" -- SDL_MOUSEMOTION\n");
156 oldMouseX = mouseX, oldMouseY = mouseY;
157 mouseX = event.motion.x, mouseY = event.motion.y;
160 mainWindow->HandleMouseMove(mouseX, mouseY);
162 mainMenu->HandleMouseMove(mouseX, mouseY);
164 else if (event.type == SDL_MOUSEBUTTONDOWN)
166 #ifdef DEBUG_MAIN_LOOP
167 WriteLog(" -- SDL_MOSEBUTTONDOWN\n");
169 uint32 mx = event.button.x, my = event.button.y;
172 mainWindow->HandleMouseButton(mx, my, true);
174 mainMenu->HandleMouseButton(mx, my, true);
176 else if (event.type == SDL_MOUSEBUTTONUP)
178 #ifdef DEBUG_MAIN_LOOP
179 WriteLog(" -- SDL_MOUSEBUTTONUP\n");
181 uint32 mx = event.button.x, my = event.button.y;
184 mainWindow->HandleMouseButton(mx, my, false);
186 mainMenu->HandleMouseButton(mx, my, false);
188 #ifdef DEBUG_MAIN_LOOP
190 WriteLog(" -- Unknown event\n");
193 if (Element::ScreenNeedsRefreshing())
195 #ifdef DEBUG_MAIN_LOOP
196 WriteLog("Screen refresh called!\n");
198 RenderScreenBuffer();
199 Element::ScreenWasRefreshed();
204 SDL_EnableKeyRepeat(0, 0);