GLWWindowManager.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <GLW/GLWWindowManager.h>
00022 #include <GLEXT/GLViewPort.h>
00023 #include <image/ImageFactory.h>
00024 #include <dialogs/MainMenuDialog.h>
00025 #include <graph/OptionsDisplay.h>
00026 #include <common/Defines.h>
00027 #include <lang/LangResource.h>
00028 #include <XML/XMLFile.h>
00029 #include <limits.h>
00030 #include <set>
00031 
00032 GLWWindowManager *GLWWindowManager::instance_ = 0;
00033 
00034 GLWWindowManager *GLWWindowManager::instance()
00035 {
00036         if (!instance_)
00037         {
00038                 instance_ = new GLWWindowManager;
00039         }
00040 
00041         return instance_;
00042 }
00043 
00044 GLWWindowManager::GLWWindowManager() : 
00045         GameStateI("GLWWindowManager"),
00046         currentStateEntry_(0),
00047         changeEpoc_(0)
00048 {
00049         setCurrentEntry(UINT_MAX);
00050 
00051         Image *map = ImageFactory::loadImage(
00052                 S3D::getDataFile("data/windows/screen.bmp"),
00053                 S3D::getDataFile("data/windows/screena.bmp"),
00054                 false);
00055         DIALOG_ASSERT(map->getBits());
00056         MainMenuDialog::instance()->
00057                 addMenu(LANG_RESOURCE("WINDOWS", "Windows"), 
00058                         "Windows",
00059                         LANG_RESOURCE("WINDOWS_WINDOW", "Hide and display aspects of the user interface"),
00060                         32.0f, 0, this, map);
00061 }
00062 
00063 GLWWindowManager::~GLWWindowManager()
00064 {
00065 
00066 }
00067 
00068 void GLWWindowManager::clear()
00069 {
00070         currentStateEntry_ = 0;
00071         setCurrentEntry(UINT_MAX);
00072         stateEntrys_.clear();
00073         idToWindow_.clear();
00074         windowVisibility_.clear();
00075 }
00076 
00077 void GLWWindowManager::setCurrentEntry(const unsigned state)
00078 {
00079         // Store the currently visible windows
00080         std::set<unsigned int> shownWindows;
00081     std::deque<GLWWindow *> windowsCopy;
00082         std::deque<GLWWindow *>::iterator qitor;
00083 
00084         if (currentStateEntry_)
00085         {
00086                 windowsCopy = currentStateEntry_->windows_;
00087                 for (qitor = windowsCopy.begin();
00088                         qitor != windowsCopy.end();
00089                         qitor++)
00090                 {
00091                         GLWWindow *window = *qitor;
00092                         if (windowVisible(window->getId()))
00093                         {
00094                                 shownWindows.insert(window->getId());
00095                         }
00096                 }
00097         }
00098 
00099         // Find the next state
00100         static StateEntry defaultStateEntry;
00101         defaultStateEntry.state_ = UINT_MAX;
00102 
00103         std::map<unsigned, StateEntry>::iterator itor =
00104                 stateEntrys_.find(state);
00105         if (itor == stateEntrys_.end())
00106         {
00107                 currentStateEntry_ = &defaultStateEntry;
00108         }
00109         else
00110         {
00111                 currentStateEntry_ = &(*itor).second;
00112         }
00113 
00114         // Tell the windows that they have been hidden or shown
00115         windowsCopy = currentStateEntry_->windows_;
00116         for (qitor = windowsCopy.begin();
00117                 qitor != windowsCopy.end();
00118                 qitor++)
00119         {
00120                 GLWWindow *window = *qitor;
00121                 window->windowInit(state);
00122 
00123                 // This window should be visible
00124                 if (windowVisible(window->getId()))
00125                 {
00126                         // Only call window display on windows that have not
00127                         // been shown in the last state
00128                         std::set<unsigned int>::iterator shownPrev = 
00129                                 shownWindows.find(window->getId());
00130                         if (shownPrev == shownWindows.end())
00131                         {
00132                                 window->display();
00133                         }
00134                 }
00135                 else
00136                 {
00137                         // Only call window hide on windows that have
00138                         // been shown in the last state
00139                         std::set<unsigned int>::iterator shownPrev = 
00140                                 shownWindows.find(window->getId());
00141                         if (shownPrev != shownWindows.end())
00142                         {
00143                                 window->hide();
00144                         }
00145                 }
00146         }
00147 
00148         sortWindowLevels();
00149 }
00150 
00151 void GLWWindowManager::addWindow(const unsigned state, GLWWindow *window, KeyboardKey *key, bool visible)
00152 {
00153         windowVisibility_[window->getId()] = visible;
00154         idToWindow_[window->getId()] = window;
00155 
00156         stateEntrys_[state].windows_.push_back(window);
00157         stateEntrys_[state].state_ = state;
00158         stateEntrys_[state].windowKeys_.push_back(
00159                 std::pair<KeyboardKey *, GLWWindow *>(key, window));
00160 }
00161 
00162 bool GLWWindowManager::showWindow(unsigned id)
00163 {
00164         std::map<unsigned, bool>::iterator itor =
00165                 windowVisibility_.find(id);
00166         if (itor != windowVisibility_.end())
00167         {
00168                 if (!(*itor).second)
00169                 {
00170                         GLWWindow *window = idToWindow_[id];
00171                         (*itor).second = true;
00172                         window->display();
00173                         moveToFront(id);
00174 
00175                         changeEpoc_++;
00176                         return true;
00177                 }
00178         }
00179 
00180         return false;
00181 }
00182 
00183 bool GLWWindowManager::moveToFront(unsigned id)
00184 {
00185         GLWWindow *found = 0;
00186         std::deque<GLWWindow *> tmpList;
00187 
00188         while (!currentStateEntry_->windows_.empty())
00189         {
00190                 GLWWindow *window = currentStateEntry_->windows_.front();
00191                 currentStateEntry_->windows_.pop_front();
00192                 if (window->getId() == id) found = window;
00193                 else tmpList.push_back(window);
00194         }
00195 
00196         currentStateEntry_->windows_ = tmpList;
00197         if (found) 
00198         {
00199                 changeEpoc_++;
00200                 currentStateEntry_->windows_.push_back(found);
00201                 sortWindowLevels();
00202         }
00203 
00204         return (found != 0);
00205 }
00206 
00207 void GLWWindowManager::sortWindowLevels()
00208 {
00209         if (!currentStateEntry_) return;
00210 
00211         std::deque<GLWWindow *> &windows = currentStateEntry_->windows_;
00212 
00213         bool changed = true;
00214         while (changed)
00215         {
00216                 changed = false;
00217                 for (int i=0; i<int(windows.size())-1; i++)
00218                 {
00219                         GLWWindow *first = windows[i];
00220                         GLWWindow *second = windows[i+1];
00221                         if (first->getWindowLevel() < second->getWindowLevel())
00222                         {
00223                                 windows[i] = second;
00224                                 windows[i+1] = first;
00225                                 changed = true;
00226                                 changeEpoc_++;
00227                         }
00228                 }
00229         }
00230 }
00231 
00232 bool GLWWindowManager::windowVisible(unsigned id)
00233 {
00234         std::map<unsigned, bool>::iterator itor =
00235                 windowVisibility_.find(id);
00236         if (itor != windowVisibility_.end())
00237         {
00238                 return ((*itor).second);
00239         }
00240 
00241         return false;
00242 }
00243 
00244 bool GLWWindowManager::hideWindow(unsigned id)
00245 {
00246         std::map<unsigned, bool>::iterator itor =
00247                 windowVisibility_.find(id);
00248         if (itor != windowVisibility_.end())
00249         {
00250                 if ((*itor).second)
00251                 {
00252                         GLWWindow *window = idToWindow_[id];
00253                         window->hide();
00254 
00255                         (*itor).second = false;
00256                         changeEpoc_++;
00257                         return true;
00258                 }
00259         }
00260 
00261         return false;
00262 }
00263 
00264 bool GLWWindowManager::windowInCurrentState(unsigned id)
00265 {
00266         if (!currentStateEntry_) return false;
00267 
00268         std::deque<GLWWindow *>::iterator itor;
00269         for (itor = currentStateEntry_->windows_.begin();
00270                 itor != currentStateEntry_->windows_.end();
00271                 itor++)
00272         {
00273                 GLWWindow *window = (*itor);
00274                 if (window->getId() == id)
00275                 {
00276                         return true;
00277                 }
00278         }
00279         return false;
00280 }
00281 
00282 void GLWWindowManager::enterState(const unsigned state)
00283 {
00284         if (currentStateEntry_ &&
00285                 currentStateEntry_->state_ != UINT_MAX &&
00286                 currentStateEntry_->state_ != state) setCurrentEntry(state);
00287 }
00288 
00289 void GLWWindowManager::draw(const unsigned state)
00290 {
00291         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00292         unsigned int entryEpoc = changeEpoc_;
00293 
00294         std::deque<GLWWindow *>::iterator itor;
00295         for (itor = currentStateEntry_->windows_.begin();
00296                 itor != currentStateEntry_->windows_.end();
00297                 itor++)
00298         {
00299                 GLWWindow *window = (*itor);
00300                 if (windowVisible(window->getId()))
00301                 {
00302                         window->draw();
00303                         if (entryEpoc != changeEpoc_) break;
00304                 }
00305         }
00306 }
00307 
00308 GLWWindow *GLWWindowManager::getWindowByName(const char *name)
00309 {
00310         if (!currentStateEntry_) return 0;
00311 
00312         std::deque<GLWWindow *>::iterator itor;
00313         for (itor = currentStateEntry_->windows_.begin();
00314                 itor != currentStateEntry_->windows_.end();
00315                 itor++)
00316         {
00317                 GLWWindow *window = (*itor);
00318                 if (0 == strcmp(window->getName(), name)) return window;
00319         }
00320         return 0;
00321 }
00322 
00323 unsigned int GLWWindowManager::getFocus(int x, int y)
00324 {
00325         std::deque<GLWWindow *>::reverse_iterator itor;
00326         for (itor = currentStateEntry_->windows_.rbegin();
00327                 itor != currentStateEntry_->windows_.rend();
00328                 itor++)
00329         {
00330                 GLWWindow *window = (*itor);
00331                 if (windowVisible(window->getId()))
00332                 {
00333                         if (GLWidget::inBox(
00334                                 (float) x, (float) y,
00335                                 window->getX(), window->getY(),
00336                                 window->getW(), window->getH()))
00337                         {
00338                                 return window->getId();
00339                         }
00340                 }
00341         }
00342         return 0;
00343 }
00344 
00345 void GLWWindowManager::simulate(const unsigned state, float simTime)
00346 {
00347         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00348         unsigned int entryEpoc = changeEpoc_;
00349 
00350         std::deque<GLWWindow *>::iterator itor;
00351         for (itor = currentStateEntry_->windows_.begin();
00352                 itor != currentStateEntry_->windows_.end();
00353                 itor++)
00354         {
00355                 GLWWindow *window = (*itor);
00356                 if (windowVisible(window->getId()))
00357                 {
00358                         window->simulate(simTime);
00359                         if (entryEpoc != changeEpoc_) break;
00360                 }
00361         }       
00362 }
00363 
00364 void GLWWindowManager::keyboardCheck(const unsigned state, float frameTime, 
00365                                                            char *buffer, unsigned int keyState,
00366                                                            KeyboardHistory::HistoryElement *history, int hisCount, 
00367                                                            bool &skipRest)
00368 {
00369         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00370         unsigned int entryEpoc = changeEpoc_;
00371 
00372         std::deque<GLWWindow *>::reverse_iterator itor;
00373         for (itor = currentStateEntry_->windows_.rbegin();
00374                 itor != currentStateEntry_->windows_.rend();
00375                 itor++)
00376         {
00377                 GLWWindow *window = (*itor);
00378                 if (windowVisible(window->getId()))
00379                 {
00380                         window->keyDown(buffer, keyState,
00381                                                                 history, hisCount, 
00382                                                                 skipRest);
00383                         if (skipRest) break;
00384                         if (entryEpoc != changeEpoc_) break;
00385                 }
00386         }
00387 
00388         if (skipRest) return;
00389 
00390         for (int i=0; i<hisCount; i++)
00391         {
00392                 unsigned int dik = history[i].sdlKey;
00393 
00394                 std::list<std::pair<KeyboardKey *, GLWWindow *> >::iterator keyItor;
00395                 std::list<std::pair<KeyboardKey *, GLWWindow *> >::iterator endKeyItor = 
00396                         currentStateEntry_->windowKeys_.end();
00397                 for (keyItor = currentStateEntry_->windowKeys_.begin();
00398                         keyItor != endKeyItor;
00399                         keyItor++)
00400                 {
00401                         KeyboardKey *key = (*keyItor).first;
00402                         if (key && key->keyDown(buffer, keyState))
00403                         {
00404                                 GLWWindow *window = (*keyItor).second;
00405                                 if (windowVisible(window->getId()))
00406                                 {
00407                                         hideWindow(window->getId());
00408                                 }
00409                                 else
00410                                 {
00411                                         showWindow(window->getId());
00412                                 }
00413                         }
00414                 }
00415         }
00416 }
00417 
00418 void GLWWindowManager::mouseDown(const unsigned state, GameState::MouseButton button, int x, int y, bool &skipRest)
00419 {
00420         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00421         unsigned int entryEpoc = changeEpoc_;
00422 
00423         std::deque<GLWWindow *>::reverse_iterator itor;
00424         for (itor = currentStateEntry_->windows_.rbegin();
00425                 itor != currentStateEntry_->windows_.rend();
00426                 itor++)
00427         {
00428                 GLWWindow *window = (*itor);
00429                 if (windowVisible(window->getId()))
00430                 {
00431                         window->mouseDown((int) button, (float) x, (float) y, skipRest);
00432                         if (skipRest) break;
00433                         if (entryEpoc != changeEpoc_) break;
00434                 }
00435         }
00436 }
00437 
00438 void GLWWindowManager::mouseUp(const unsigned state, GameState::MouseButton button, int x, int y, bool &skipRest)
00439 {
00440         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00441         unsigned int entryEpoc = changeEpoc_;
00442 
00443         std::deque<GLWWindow *>::reverse_iterator itor;
00444         for (itor = currentStateEntry_->windows_.rbegin();
00445                 itor != currentStateEntry_->windows_.rend();
00446                 itor++)
00447         {
00448                 GLWWindow *window = (*itor);
00449                 if (windowVisible(window->getId()))
00450                 {
00451                         window->mouseUp((int) button, (float) x, (float) y, skipRest);
00452                         if (skipRest) break;
00453                         if (entryEpoc != changeEpoc_) break;
00454                 }
00455         }
00456 }
00457 
00458 void GLWWindowManager::mouseDrag(const unsigned state, GameState::MouseButton button, 
00459                                                           int x, int y, int dx, int dy, bool &skipRest)
00460 {
00461         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00462         unsigned int entryEpoc = changeEpoc_;
00463 
00464         std::deque<GLWWindow *>::reverse_iterator itor;
00465         for (itor = currentStateEntry_->windows_.rbegin();
00466                 itor != currentStateEntry_->windows_.rend();
00467                 itor++)
00468         {
00469                 GLWWindow *window = (*itor);
00470                 if (windowVisible(window->getId()))
00471                 {
00472                         window->mouseDrag((int) button, (float) x, (float) y, (float) dx, (float) dy, skipRest);
00473                         if (skipRest) break;
00474                         if (entryEpoc != changeEpoc_) break;
00475                 }
00476         }
00477 }
00478 
00479 void GLWWindowManager::mouseWheel(const unsigned state, 
00480         int x, int y, int z, bool &skipRest)
00481 {
00482         if (currentStateEntry_->state_ != state) setCurrentEntry(state);
00483         unsigned int entryEpoc = changeEpoc_;
00484 
00485         std::deque<GLWWindow *>::reverse_iterator itor;
00486         for (itor = currentStateEntry_->windows_.rbegin();
00487                 itor != currentStateEntry_->windows_.rend();
00488                 itor++)
00489         {
00490                 GLWWindow *window = (*itor);
00491                 if (windowVisible(window->getId()))
00492                 {
00493                         window->mouseWheel((float) x, (float) y, (float) z, skipRest);
00494                         if (skipRest) break;
00495                         if (entryEpoc != changeEpoc_) break;
00496                 }
00497         }
00498 }
00499 
00500 bool GLWWindowManager::getMenuItems(const char* menuName, 
00501                                                                  std::list<GLMenuItem> &items)
00502 {
00503         if (currentStateEntry_) 
00504         {
00505                 std::map<unsigned, GLWWindow *>::iterator itor;
00506                 for (itor = idToWindow_.begin();
00507                         itor != idToWindow_.end();
00508                         itor++)
00509                 {
00510                         unsigned id = (*itor).first;
00511                         GLWWindow *window = (*itor).second;
00512 
00513                         if (window->getName()[0] != '\0' &&
00514                                 windowInCurrentState(id))
00515                         {
00516                                 items.push_back(
00517                                         GLMenuItem(
00518                                                 LANG_RESOURCE(window->getName(), window->getName()), 
00519                                                 &window->getToolTip(), 
00520                                                 windowVisible(window->getId())));
00521                         }
00522                 }
00523         }
00524         return true;
00525 }
00526 
00527 void GLWWindowManager::menuSelection(const char* menuName, 
00528         const int position, GLMenuItem &item)
00529 {
00530         if (currentStateEntry_) 
00531         {
00532                 int pos = 0;
00533                 std::map<unsigned, GLWWindow *>::iterator itor;
00534                 for (itor = idToWindow_.begin();
00535                         itor != idToWindow_.end();
00536                         itor++)
00537                 {
00538                         unsigned id = (*itor).first;
00539                         GLWWindow *window = (*itor).second;
00540 
00541                         if (window->getName()[0] != '\0' &&
00542                                 windowInCurrentState(id))
00543                         {
00544                                 if (pos++ == position) 
00545                                 {
00546                                         if (windowVisible(window->getId()))
00547                                         {
00548                                                 hideWindow(window->getId());
00549                                         }
00550                                         else
00551                                         {
00552                                                 showWindow(window->getId());
00553                                         }
00554                                         return;
00555                                 }
00556                         }
00557                 }
00558         }
00559 }
00560 
00561 void GLWWindowManager::loadPositions()
00562 {
00563         XMLFile file;
00564         std::string fileName = S3D::getSettingsFile("windowpositions.xml");
00565         if (!file.readFile(fileName))
00566         {
00567                 S3D::dialogMessage("GLWWindowManager", S3D::formatStringBuffer(
00568                                           "Failed to parse \"%s\"\n%s", 
00569                                           fileName.c_str(),
00570                                           file.getParserError()));
00571                 return;
00572         }
00573         if (!file.getRootNode()) return;
00574 
00575         // Get root nodes
00576         XMLNode *display = 0, *positions = 0;
00577         if (!file.getRootNode()->getNamedChild("display", display)) return;
00578         if (!file.getRootNode()->getNamedChild("positions", positions)) return;
00579 
00580         // Get display size
00581         int width, height;
00582         if (!display->getNamedChild("width", width)) return;
00583         if (!display->getNamedChild("height", height)) return;
00584 
00585         // Check display size is the same as the current size
00586         // if not then discard the windows size changes
00587         if (width != GLViewPort::getWidth() ||
00588                 height != GLViewPort::getHeight())
00589         {
00590                 return;
00591         }
00592 
00593         // Itterate all of the positions in the file
00594     std::list<XMLNode *>::iterator childrenItor;
00595         std::list<XMLNode *> &children = positions->getChildren();
00596     for (childrenItor = children.begin();
00597         childrenItor != children.end();
00598         childrenItor++)
00599     {
00600                 XMLNode *node = (*childrenItor);
00601 
00602                 // Get the window position
00603                 std::string window;
00604                 if (!node->getNamedChild("window", window)) return;
00605 
00606                 // Set the new position
00607                 std::map<unsigned, GLWWindow *>::iterator winitor;
00608                 for (winitor = idToWindow_.begin();
00609                         winitor != idToWindow_.end();
00610                         winitor++)
00611                 {
00612                         GLWWindow *w = (*winitor).second;
00613                         if (0 == strcmp(w->getName(), window.c_str()))
00614                         {
00615                                 w->loadPosition(node);
00616                                 break;
00617                         }
00618                 }
00619         }
00620 }
00621 
00622 void GLWWindowManager::savePositions()
00623 {
00624         XMLNode node("positions");
00625 
00626         XMLNode *display = new XMLNode("display");
00627         XMLNode *positions = new XMLNode("positions");
00628         node.addChild(display);
00629         node.addChild(positions);
00630 
00631         // Add display
00632         display->addChild(new XMLNode("width", GLViewPort::getWidth()));
00633         display->addChild(new XMLNode("height", GLViewPort::getHeight()));
00634 
00635         if (OptionsDisplay::instance()->getSaveWindowPositions())
00636         {
00637                 // Add positions
00638                 std::map<unsigned, GLWWindow *>::iterator winitor;
00639                 for (winitor = idToWindow_.begin();
00640                         winitor != idToWindow_.end();
00641                         winitor++)
00642                 {
00643                         GLWWindow *w = (*winitor).second;
00644 
00645                         if ((w->getWindowState() & GLWWindow::eSavePosition) &&
00646                                 w->getX() >= 0 && w->getY() >= 0)
00647                         {
00648                                 XMLNode *position = new XMLNode("position");
00649                                 positions->addChild(position);
00650                                 position->addChild(new XMLNode("window", w->getName()));
00651                                 w->savePosition(position);
00652                         }
00653                 }
00654         }
00655 
00656         std::string fileName = S3D::getSettingsFile("windowpositions.xml");
00657         node.writeToFile(fileName);
00658 }

Generated on Mon Feb 16 15:14:46 2009 for Scorched3D by  doxygen 1.5.3