//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include GLWWindowManager *GLWWindowManager::instance_ = 0; GLWWindowManager *GLWWindowManager::instance() { if (!instance_) { instance_ = new GLWWindowManager; } return instance_; } GLWWindowManager::GLWWindowManager() : GameStateI("GLWWindowManager"), currentStateEntry_(0) { setCurrentEntry(UINT_MAX); GLBitmap *map = new GLBitmap( formatString(getDataFile("data/windows/screen.bmp")), formatString(getDataFile("data/windows/screena.bmp")), false); DIALOG_ASSERT(map->getBits()); MainMenuDialog::instance()-> addMenu("Windows", 32.0f, 0, this, map); } GLWWindowManager::~GLWWindowManager() { } void GLWWindowManager::clear() { currentStateEntry_ = 0; setCurrentEntry(UINT_MAX); stateEntrys_.clear(); idToWindow_.clear(); windowVisibility_.clear(); } void GLWWindowManager::setCurrentEntry(const unsigned state) { // Store the currently visible windows std::set shownWindows; std::deque windowsCopy; std::deque::iterator qitor; if (currentStateEntry_) { windowsCopy = currentStateEntry_->windows_; for (qitor = windowsCopy.begin(); qitor != windowsCopy.end(); qitor++) { GLWWindow *window = *qitor; if (windowVisible(window->getId())) { shownWindows.insert(window->getId()); } } } // Find the next state static StateEntry defaultStateEntry; defaultStateEntry.state_ = UINT_MAX; std::map::iterator itor = stateEntrys_.find(state); if (itor == stateEntrys_.end()) { currentStateEntry_ = &defaultStateEntry; } else { currentStateEntry_ = &(*itor).second; } // Tell the windows that they have been hidden or shown windowsCopy = currentStateEntry_->windows_; for (qitor = windowsCopy.begin(); qitor != windowsCopy.end(); qitor++) { GLWWindow *window = *qitor; window->windowInit(state); // This window should be visible if (windowVisible(window->getId())) { // Only call window display on windows that have not // been shown in the last state std::set::iterator shownPrev = shownWindows.find(window->getId()); if (shownPrev == shownWindows.end()) { window->display(); } } else { // Only call window hide on windows that have // been shown in the last state std::set::iterator shownPrev = shownWindows.find(window->getId()); if (shownPrev != shownWindows.end()) { window->hide(); } } } sortWindowLevels(); } void GLWWindowManager::addWindow(const unsigned state, GLWWindow *window, KeyboardKey *key, bool visible) { windowVisibility_[window->getId()] = visible; idToWindow_[window->getId()] = window; stateEntrys_[state].windows_.push_back(window); stateEntrys_[state].state_ = state; stateEntrys_[state].windowKeys_.push_back( std::pair(key, window)); } bool GLWWindowManager::showWindow(unsigned id) { std::map::iterator itor = windowVisibility_.find(id); if (itor != windowVisibility_.end()) { if (!(*itor).second) { GLWWindow *window = idToWindow_[id]; (*itor).second = true; window->display(); moveToFront(id); return true; } } return false; } bool GLWWindowManager::moveToFront(unsigned id) { GLWWindow *found = 0; std::deque tmpList; while (!currentStateEntry_->windows_.empty()) { GLWWindow *window = currentStateEntry_->windows_.front(); currentStateEntry_->windows_.pop_front(); if (window->getId() == id) found = window; else tmpList.push_back(window); } currentStateEntry_->windows_ = tmpList; if (found) { currentStateEntry_->windows_.push_back(found); sortWindowLevels(); } return (found != 0); } void GLWWindowManager::sortWindowLevels() { if (!currentStateEntry_) return; std::deque &windows = currentStateEntry_->windows_; bool changed = true; while (changed) { changed = false; for (int i=0; igetWindowLevel() < second->getWindowLevel()) { windows[i] = second; windows[i+1] = first; changed = true; } } } } bool GLWWindowManager::windowVisible(unsigned id) { std::map::iterator itor = windowVisibility_.find(id); if (itor != windowVisibility_.end()) { return ((*itor).second); } return false; } bool GLWWindowManager::hideWindow(unsigned id) { std::map::iterator itor = windowVisibility_.find(id); if (itor != windowVisibility_.end()) { if ((*itor).second) { GLWWindow *window = idToWindow_[id]; window->hide(); (*itor).second = false; return true; } } return false; } bool GLWWindowManager::windowInCurrentState(unsigned id) { if (!currentStateEntry_) return false; std::deque::iterator itor; for (itor = currentStateEntry_->windows_.begin(); itor != currentStateEntry_->windows_.end(); itor++) { GLWWindow *window = (*itor); if (window->getId() == id) { return true; } } return false; } void GLWWindowManager::enterState(const unsigned state) { if (currentStateEntry_ && currentStateEntry_->state_ != UINT_MAX && currentStateEntry_->state_ != state) setCurrentEntry(state); } void GLWWindowManager::draw(const unsigned state) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::iterator itor; for (itor = currentStateEntry_->windows_.begin(); itor != currentStateEntry_->windows_.end(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->draw(); } } } GLWWindow *GLWWindowManager::getWindowByName(const char *name) { if (!currentStateEntry_) return 0; std::deque::iterator itor; for (itor = currentStateEntry_->windows_.begin(); itor != currentStateEntry_->windows_.end(); itor++) { GLWWindow *window = (*itor); if (0 == strcmp(window->getName(), name)) return window; } return 0; } unsigned int GLWWindowManager::getFocus(int x, int y) { std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { if (GLWidget::inBox( (float) x, (float) y, window->getX(), window->getY(), window->getW(), window->getH())) { return window->getId(); } } } return 0; } void GLWWindowManager::simulate(const unsigned state, float simTime) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::iterator itor; for (itor = currentStateEntry_->windows_.begin(); itor != currentStateEntry_->windows_.end(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->simulate(simTime); } } } void GLWWindowManager::keyboardCheck(const unsigned state, float frameTime, char *buffer, unsigned int keyState, KeyboardHistory::HistoryElement *history, int hisCount, bool &skipRest) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->keyDown(buffer, keyState, history, hisCount, skipRest); if (skipRest) break; } } if (skipRest) return; for (int i=0; i >::iterator keyItor; std::list >::iterator endKeyItor = currentStateEntry_->windowKeys_.end(); for (keyItor = currentStateEntry_->windowKeys_.begin(); keyItor != endKeyItor; keyItor++) { KeyboardKey *key = (*keyItor).first; if (key && key->keyDown(buffer, keyState)) { GLWWindow *window = (*keyItor).second; if (windowVisible(window->getId())) { hideWindow(window->getId()); } else { showWindow(window->getId()); } } } } } void GLWWindowManager::mouseDown(const unsigned state, GameState::MouseButton button, int x, int y, bool &skipRest) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->mouseDown((int) button, (float) x, (float) y, skipRest); if (skipRest) break; } } } void GLWWindowManager::mouseUp(const unsigned state, GameState::MouseButton button, int x, int y, bool &skipRest) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->mouseUp((int) button, (float) x, (float) y, skipRest); if (skipRest) break; } } } void GLWWindowManager::mouseDrag(const unsigned state, GameState::MouseButton button, int x, int y, int dx, int dy, bool &skipRest) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->mouseDrag((int) button, (float) x, (float) y, (float) dx, (float) dy, skipRest); if (skipRest) break; } } } void GLWWindowManager::mouseWheel(const unsigned state, int x, int y, int z, bool &skipRest) { if (currentStateEntry_->state_ != state) setCurrentEntry(state); std::deque::reverse_iterator itor; for (itor = currentStateEntry_->windows_.rbegin(); itor != currentStateEntry_->windows_.rend(); itor++) { GLWWindow *window = (*itor); if (windowVisible(window->getId())) { window->mouseWheel((float) x, (float) y, (float) z, skipRest); if (skipRest) break; } } } bool GLWWindowManager::getMenuItems(const char* menuName, std::list &items) { if (currentStateEntry_) { std::map::iterator itor; for (itor = idToWindow_.begin(); itor != idToWindow_.end(); itor++) { unsigned id = (*itor).first; GLWWindow *window = (*itor).second; if (window->getName()[0] != '\0' && windowInCurrentState(id)) { items.push_back( GLMenuItem( window->getName(), &window->getToolTip(), windowVisible(window->getId()))); } } } return true; } void GLWWindowManager::menuSelection(const char* menuName, const int position, GLMenuItem &item) { if (currentStateEntry_) { int pos = 0; std::map::iterator itor; for (itor = idToWindow_.begin(); itor != idToWindow_.end(); itor++) { unsigned id = (*itor).first; GLWWindow *window = (*itor).second; if (window->getName()[0] != '\0' && windowInCurrentState(id)) { if (pos++ == position) { if (windowVisible(window->getId())) { hideWindow(window->getId()); } else { showWindow(window->getId()); } return; } } } } } void GLWWindowManager::loadPositions() { XMLFile file; const char *fileName = getSettingsFile("windowpositions.xml"); if (!file.readFile(fileName)) { dialogMessage("GLWWindowSkinManager", formatString( "Failed to parse \"%s\"\n%s", fileName, file.getParserError())); return; } if (!file.getRootNode()) return; // Get root nodes XMLNode *display = 0, *positions = 0; if (!file.getRootNode()->getNamedChild("display", display)) return; if (!file.getRootNode()->getNamedChild("positions", positions)) return; // Get display size int width, height; if (!display->getNamedChild("width", width)) return; if (!display->getNamedChild("height", height)) return; // Check display size is the same as the current size // if not then discard the windows size changes if (width != GLViewPort::getWidth() || height != GLViewPort::getHeight()) { return; } // Itterate all of the positions in the file std::list::iterator childrenItor; std::list &children = positions->getChildren(); for (childrenItor = children.begin(); childrenItor != children.end(); childrenItor++) { XMLNode *node = (*childrenItor); // Get the window position std::string window; if (!node->getNamedChild("window", window)) return; // Set the new position std::map::iterator winitor; for (winitor = idToWindow_.begin(); winitor != idToWindow_.end(); winitor++) { GLWWindow *w = (*winitor).second; if (0 == strcmp(w->getName(), window.c_str())) { w->loadPosition(node); break; } } } } void GLWWindowManager::savePositions() { XMLNode node("positions"); XMLNode *display = new XMLNode("display"); XMLNode *positions = new XMLNode("positions"); node.addChild(display); node.addChild(positions); // Add display display->addChild(new XMLNode("width", GLViewPort::getWidth())); display->addChild(new XMLNode("height", GLViewPort::getHeight())); if (OptionsDisplay::instance()->getSaveWindowPositions()) { // Add positions std::map::iterator winitor; for (winitor = idToWindow_.begin(); winitor != idToWindow_.end(); winitor++) { GLWWindow *w = (*winitor).second; if ((w->getWindowState() & GLWWindow::eSavePosition) && w->getX() >= 0 && w->getY() >= 0) { XMLNode *position = new XMLNode("position"); positions->addChild(position); position->addChild(new XMLNode("window", w->getName())); w->savePosition(position); } } } const char *fileName = getSettingsFile("windowpositions.xml"); node.writeToFile(fileName); }