diff options
author | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
---|---|---|
committer | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
commit | 45285e8a9300cd754a760560640b75b09f98035e (patch) | |
tree | ad9f093885ad5c98e9dd4156674e7691c22ed0a2 /guilib/GUIWindowManager.cpp |
step 3/4: Move linuxport to trunk. How'd I get roped into this?
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23097 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'guilib/GUIWindowManager.cpp')
-rw-r--r-- | guilib/GUIWindowManager.cpp | 891 |
1 files changed, 891 insertions, 0 deletions
diff --git a/guilib/GUIWindowManager.cpp b/guilib/GUIWindowManager.cpp new file mode 100644 index 0000000000..e2ec0761d8 --- /dev/null +++ b/guilib/GUIWindowManager.cpp @@ -0,0 +1,891 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program 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, or (at your option) + * any later version. + * + * This Program 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIWindowManager.h" +#include "GUIAudioManager.h" +#include "GUIDialog.h" +#include "Application.h" +#include "GUIPassword.h" +#include "utils/GUIInfoManager.h" +#include "Util.h" +#include "GUISettings.h" +#include "Settings.h" + +using namespace std; + +CGUIWindowManager m_gWindowManager; + +CGUIWindowManager::CGUIWindowManager(void) +{ + InitializeCriticalSection(&m_critSection); + + m_pCallback = NULL; + m_bShowOverlay = true; +} + +CGUIWindowManager::~CGUIWindowManager(void) +{ + DeleteCriticalSection(&m_critSection); +} + +void CGUIWindowManager::Initialize() +{ + g_graphicsContext.setMessageSender(this); + LoadNotOnDemandWindows(); +} + +bool CGUIWindowManager::SendMessage(CGUIMessage& message) +{ + bool handled = false; +// CLog::Log(LOGDEBUG,"SendMessage: mess=%d send=%d control=%d param1=%d", message.GetMessage(), message.GetSenderId(), message.GetControlId(), message.GetParam1()); + // Send the message to all none window targets + for (int i = 0; i < (int) m_vecMsgTargets.size(); i++) + { + IMsgTargetCallback* pMsgTarget = m_vecMsgTargets[i]; + + if (pMsgTarget) + { + if (pMsgTarget->OnMessage( message )) handled = true; + } + } + + // A GUI_MSG_NOTIFY_ALL is send to any active modal dialog + // and all windows whether they are active or not + if (message.GetMessage()==GUI_MSG_NOTIFY_ALL) + { + for (rDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it) + { + CGUIWindow *dialog = *it; + dialog->OnMessage(message); + } + + for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++) + { + CGUIWindow *pWindow = (*it).second; + pWindow->OnMessage(message); + } + return true; + } + + // Normal messages are sent to: + // 1. All active modeless dialogs + // 2. The topmost dialog that accepts the message + // 3. The underlying window (only if it is the sender or receiver if a modal dialog is active) + + bool hasModalDialog(false); + bool modalAcceptedMessage(false); + // don't use an iterator for this loop, as some messages mean that m_activeDialogs is altered, + // which will invalidate any iterator + unsigned int topWindow = m_activeDialogs.size(); + while (topWindow) + { + CGUIWindow* dialog = m_activeDialogs[--topWindow]; + if (!modalAcceptedMessage && dialog->IsModalDialog()) + { // modal window + hasModalDialog = true; + if (!modalAcceptedMessage && dialog->OnMessage( message )) + { + modalAcceptedMessage = handled = true; + } + } + else if (!dialog->IsModalDialog()) + { // modeless + if (dialog->OnMessage( message )) + handled = true; + } + } + + // now send to the underlying window + CGUIWindow* window = GetWindow(GetActiveWindow()); + if (window) + { + if (hasModalDialog) + { + // only send the message to the underlying window if it's the recipient + // or sender (or we have no sender) + if (message.GetSenderId() == window->GetID() || + message.GetControlId() == window->GetID() || + message.GetSenderId() == 0 ) + { + if (window->OnMessage(message)) handled = true; + } + } + else + { + if (window->OnMessage(message)) handled = true; + } + } + return handled; +} + +bool CGUIWindowManager::SendMessage(CGUIMessage& message, int window) +{ + CGUIWindow* pWindow = GetWindow(window); + if(pWindow) + return pWindow->OnMessage(message); + else + return false; +} + +void CGUIWindowManager::AddUniqueInstance(CGUIWindow *window) +{ + // increment our instance (upper word of windowID) + // until we get a window we don't have + int instance = 0; + while (GetWindow(window->GetID())) + window->SetID(window->GetID() + (++instance << 16)); + Add(window); +} + +void CGUIWindowManager::Add(CGUIWindow* pWindow) +{ + if (!pWindow) + { + CLog::Log(LOGERROR, "Attempted to add a NULL window pointer to the window manager."); + return; + } + // push back all the windows if there are more than one covered by this class + for (int i = 0; i < pWindow->GetIDRange(); i++) + { + WindowMap::iterator it = m_mapWindows.find(pWindow->GetID() + i); + if (it != m_mapWindows.end()) + { + CLog::Log(LOGERROR, "Error, trying to add a second window with id %u " + "to the window manager", + pWindow->GetID()); + return; + } + m_mapWindows.insert(pair<int, CGUIWindow *>(pWindow->GetID() + i, pWindow)); + } +} + +void CGUIWindowManager::AddCustomWindow(CGUIWindow* pWindow) +{ + Add(pWindow); + m_vecCustomWindows.push_back(pWindow); +} + +void CGUIWindowManager::AddModeless(CGUIWindow* dialog) +{ + // only add the window if it's not already added + for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + if (*it == dialog) return; + m_activeDialogs.push_back(dialog); +} + +void CGUIWindowManager::Remove(int id) +{ + WindowMap::iterator it = m_mapWindows.find(id); + if (it != m_mapWindows.end()) + { + m_mapWindows.erase(it); + } + else + { + CLog::Log(LOGWARNING, "Attempted to remove window %u " + "from the window manager when it didn't exist", + id); + } +} + +// removes and deletes the window. Should only be called +// from the class that created the window using new. +void CGUIWindowManager::Delete(int id) +{ + CGUIWindow *pWindow = GetWindow(id); + if (pWindow) + { + Remove(id); + delete pWindow; + } +} + +void CGUIWindowManager::PreviousWindow() +{ + // deactivate any window + CLog::Log(LOGDEBUG,"CGUIWindowManager::PreviousWindow: Deactivate"); + int currentWindow = GetActiveWindow(); + CGUIWindow *pCurrentWindow = GetWindow(currentWindow); + if (!pCurrentWindow) + return; // no windows or window history yet + + // check to see whether our current window has a <previouswindow> tag + if (pCurrentWindow->GetPreviousWindow() != WINDOW_INVALID) + { + // TODO: we may need to test here for the + // whether our history should be changed + + // don't reactivate the previouswindow if it is ourselves. + if (currentWindow != pCurrentWindow->GetPreviousWindow()) + ActivateWindow(pCurrentWindow->GetPreviousWindow()); + return; + } + // get the previous window in our stack + if (m_windowHistory.size() < 2) + { // no previous window history yet - check if we should just activate home + if (GetActiveWindow() != WINDOW_INVALID && GetActiveWindow() != WINDOW_HOME) + { + ClearWindowHistory(); + ActivateWindow(WINDOW_HOME); + } + return; + } + m_windowHistory.pop(); + int previousWindow = GetActiveWindow(); + m_windowHistory.push(currentWindow); + + CGUIWindow *pNewWindow = GetWindow(previousWindow); + if (!pNewWindow) + { + CLog::Log(LOGERROR, "Unable to activate the previous window"); + ClearWindowHistory(); + ActivateWindow(WINDOW_HOME); + return; + } + + // ok to go to the previous window now + + // tell our info manager which window we are going to + g_infoManager.SetNextWindow(previousWindow); + + // set our overlay state (enables out animations on window change) + HideOverlay(pNewWindow->GetOverlayState()); + + // deinitialize our window + g_audioManager.PlayWindowSound(pCurrentWindow->GetID(), SOUND_DEINIT); + CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0); + pCurrentWindow->OnMessage(msg); + + g_infoManager.SetNextWindow(WINDOW_INVALID); + g_infoManager.SetPreviousWindow(currentWindow); + + // remove the current window off our window stack + m_windowHistory.pop(); + + // ok, initialize the new window + CLog::Log(LOGDEBUG,"CGUIWindowManager::PreviousWindow: Activate new"); + g_audioManager.PlayWindowSound(pNewWindow->GetID(), SOUND_INIT); + CGUIMessage msg2(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID, GetActiveWindow()); + pNewWindow->OnMessage(msg2); + + g_infoManager.SetPreviousWindow(WINDOW_INVALID); + return; +} + +void CGUIWindowManager::RefreshWindow() +{ + // deactivate the current window + CGUIWindow *pWindow = GetWindow(GetActiveWindow()); + if (!pWindow) + return; + + CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0); + pWindow->OnMessage(msg); + CGUIMessage msg2(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID); + pWindow->OnMessage(msg2); +} + +void CGUIWindowManager::ChangeActiveWindow(int newWindow, const CStdString& strPath) +{ + vector<CStdString> params; + if (!strPath.IsEmpty()) + params.push_back(strPath); + ActivateWindow(newWindow, params, true); +} + +void CGUIWindowManager::ActivateWindow(int iWindowID, const CStdString& strPath) +{ + vector<CStdString> params; + if (!strPath.IsEmpty()) + params.push_back(strPath); + ActivateWindow(iWindowID, params, false); +} + +void CGUIWindowManager::ActivateWindow(int iWindowID, const vector<CStdString>& params, bool swappingWindows) +{ + if (!g_application.IsCurrentThread()) + { + // make sure graphics lock is not held + int nCount = ExitCriticalSection(g_graphicsContext); + g_application.getApplicationMessenger().ActivateWindow(iWindowID, params, swappingWindows); + RestoreCriticalSection(g_graphicsContext, nCount); + } + else + ActivateWindow_Internal(iWindowID, params, swappingWindows); +} + +void CGUIWindowManager::ActivateWindow_Internal(int iWindowID, const vector<CStdString>& params, bool swappingWindows) +{ + bool passParams = true; + // translate virtual windows + // virtual music window which returns the last open music window (aka the music start window) + if (iWindowID == WINDOW_MUSIC) + { + iWindowID = g_stSettings.m_iMyMusicStartWindow; + // ensure the music virtual window only returns music files and music library windows + if (iWindowID != WINDOW_MUSIC_NAV) + iWindowID = WINDOW_MUSIC_FILES; + // destination path cannot be used with virtual window + passParams = false; + } + // virtual video window which returns the last open video window (aka the video start window) + if (iWindowID == WINDOW_VIDEOS) + { + iWindowID = g_stSettings.m_iVideoStartWindow; + // ensure the virtual video window only returns video windows + if (iWindowID != WINDOW_VIDEO_NAV) + iWindowID = WINDOW_VIDEO_FILES; + // destination path cannot be used with virtual window + passParams = false; + } + // Is the Library enabled? If not, go to Files view. + if (iWindowID == WINDOW_MUSIC_NAV && !g_guiSettings.GetBool("musiclibrary.enabled")) + { + iWindowID = WINDOW_MUSIC_FILES; + passParams = false; + CLog::Log(LOGDEBUG, "Trying to activate Music Library, but its disabled. Switching to Files instead."); + } + if (iWindowID == WINDOW_VIDEO_NAV && !g_guiSettings.GetBool("videolibrary.enabled")) + { + iWindowID = WINDOW_VIDEO_FILES; + passParams = false; + CLog::Log(LOGDEBUG, "Trying to activate Video Library, but its disabled. Switching to Files instead."); + } + + // debug + CLog::Log(LOGDEBUG, "Activating window ID: %i", iWindowID); + + if(!g_passwordManager.CheckMenuLock(iWindowID)) + { + CLog::Log(LOGERROR, "MasterCode is Wrong: Window with id %d will not be loaded! Enter a correct MasterCode!", iWindowID); + return; + } + + // first check existence of the window we wish to activate. + CGUIWindow *pNewWindow = GetWindow(iWindowID); + if (!pNewWindow) + { // nothing to see here - move along + CLog::Log(LOGERROR, "Unable to locate window with id %d. Check skin files", iWindowID - WINDOW_HOME); + return ; + } + else if (pNewWindow->IsDialog()) + { // if we have a dialog, we do a DoModal() rather than activate the window + if (!pNewWindow->IsDialogRunning()) + ((CGUIDialog *)pNewWindow)->DoModal(iWindowID, (passParams && params.size()) ? params[0] : ""); + return; + } + + g_infoManager.SetNextWindow(iWindowID); + + // set our overlay state + HideOverlay(pNewWindow->GetOverlayState()); + + // deactivate any window + int currentWindow = GetActiveWindow(); + CGUIWindow *pWindow = GetWindow(currentWindow); + if (pWindow) + { + // Play the window specific deinit sound + g_audioManager.PlayWindowSound(pWindow->GetID(), SOUND_DEINIT); + CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0, iWindowID); + pWindow->OnMessage(msg); + } + g_infoManager.SetNextWindow(WINDOW_INVALID); + + // Add window to the history list (we must do this before we activate it, + // as all messages done in WINDOW_INIT will want to be sent to the new + // topmost window). If we are swapping windows, we pop the old window + // off the history stack + if (swappingWindows && m_windowHistory.size()) + m_windowHistory.pop(); + AddToWindowHistory(iWindowID); + + g_infoManager.SetPreviousWindow(currentWindow); + g_audioManager.PlayWindowSound(pNewWindow->GetID(), SOUND_INIT); + // Send the init message + CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0, 0, currentWindow, iWindowID); + if (passParams) + msg.SetStringParams(params); + pNewWindow->OnMessage(msg); +// g_infoManager.SetPreviousWindow(WINDOW_INVALID); +} + +void CGUIWindowManager::CloseDialogs(bool forceClose) +{ + while (m_activeDialogs.size() > 0) + { + CGUIWindow* win = m_activeDialogs[0]; + win->Close(forceClose); + } +} + +bool CGUIWindowManager::OnAction(const CAction &action) +{ + for (rDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it) + { + CGUIWindow *dialog = *it; + if (dialog->IsModalDialog()) + { // we have the topmost modal dialog + if (!dialog->IsAnimating(ANIM_TYPE_WINDOW_CLOSE)) + { + if (dialog->OnAction(action)) + return true; + // dialog didn't want the action - we'd normally return true + // but for some dialogs we want to drop the actions through + if (dialog->GetID() == WINDOW_DIALOG_FULLSCREEN_INFO) + break; + return false; + } + return true; // do nothing with the action until the anim is finished + } + // music or video overlay are handled as a special case, as they're modeless, but we allow + // clicking on them with the mouse. + if (action.id == ACTION_MOUSE && (dialog->GetID() == WINDOW_VIDEO_OVERLAY || + dialog->GetID() == WINDOW_MUSIC_OVERLAY)) + { + if (dialog->OnAction(action)) + return true; + } + } + CGUIWindow* window = GetWindow(GetActiveWindow()); + if (window) + return window->OnAction(action); + return false; +} + +void CGUIWindowManager::Render() +{ + if (!g_application.IsCurrentThread()) + { + // make sure graphics lock is not held + int nCount = ExitCriticalSection(g_graphicsContext); + g_application.getApplicationMessenger().Render(); + RestoreCriticalSection(g_graphicsContext, nCount); + } + else + Render_Internal(); +} + +void CGUIWindowManager::Render_Internal() +{ + CGUIWindow* pWindow = GetWindow(GetActiveWindow()); + if (pWindow) + pWindow->Render(); +} + +bool RenderOrderSortFunction(CGUIWindow *first, CGUIWindow *second) +{ + return first->GetRenderOrder() < second->GetRenderOrder(); +} + +void CGUIWindowManager::RenderDialogs() +{ + // find the window with the lowest render order + vector<CGUIWindow *> renderList = m_activeDialogs; + stable_sort(renderList.begin(), renderList.end(), RenderOrderSortFunction); + + // iterate through and render if they're running + for (iDialog it = renderList.begin(); it != renderList.end(); ++it) + { + if ((*it)->IsDialogRunning()) + (*it)->Render(); + } +} + +CGUIWindow* CGUIWindowManager::GetWindow(int id) const +{ + if (id == WINDOW_INVALID) + { + return NULL; + } + + WindowMap::const_iterator it = m_mapWindows.find(id); + if (it != m_mapWindows.end()) + return (*it).second; + return NULL; +} + +// Shows and hides modeless dialogs as necessary. +void CGUIWindowManager::UpdateModelessVisibility() +{ + for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++) + { + CGUIWindow *pWindow = (*it).second; + if (pWindow && pWindow->IsDialog() && pWindow->GetVisibleCondition()) + { + if (g_infoManager.GetBool(pWindow->GetVisibleCondition(), GetActiveWindow())) + ((CGUIDialog *)pWindow)->Show(); + else + ((CGUIDialog *)pWindow)->Close(); + } + } +} + +void CGUIWindowManager::Process(bool renderOnly /*= false*/) +{ + if (!g_application.IsCurrentThread()) + { + // make sure graphics lock is not held + DWORD locks = ExitCriticalSection(g_graphicsContext); + g_application.getApplicationMessenger().WindowManagerProcess(renderOnly); + RestoreCriticalSection(g_graphicsContext, locks); + } + else + Process_Internal(renderOnly); +} + +void CGUIWindowManager::Process_Internal(bool renderOnly /*= false*/) +{ + if (m_pCallback) + { + if (!renderOnly) + { + m_pCallback->Process(); + m_pCallback->FrameMove(); + } + m_pCallback->Render(); + } +} + +void CGUIWindowManager::SetCallback(IWindowManagerCallback& callback) +{ + m_pCallback = &callback; +} + +void CGUIWindowManager::DeInitialize() +{ + for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++) + { + CGUIWindow* pWindow = (*it).second; + if (IsWindowActive(it->first)) + { + pWindow->DisableAnimations(); + CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0); + pWindow->OnMessage(msg); + } + pWindow->ResetControlStates(); + pWindow->FreeResources(true); + } + UnloadNotOnDemandWindows(); + + m_vecMsgTargets.erase( m_vecMsgTargets.begin(), m_vecMsgTargets.end() ); + + // destroy our custom windows... + for (int i = 0; i < (int)m_vecCustomWindows.size(); i++) + { + CGUIWindow *pWindow = m_vecCustomWindows[i]; + Remove(pWindow->GetID()); + delete pWindow; + } + + // clear our vectors of windows + m_vecCustomWindows.clear(); + m_activeDialogs.clear(); +} + +/// \brief Route to a window +/// \param pWindow Window to route to +void CGUIWindowManager::RouteToWindow(CGUIWindow* dialog) +{ + // Just to be sure: Unroute this window, + // #we may have routed to it before + RemoveDialog(dialog->GetID()); + + m_activeDialogs.push_back(dialog); +} + +/// \brief Unroute window +/// \param id ID of the window routed +void CGUIWindowManager::RemoveDialog(int id) +{ + for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + if ((*it)->GetID() == id) + { + m_activeDialogs.erase(it); + return; + } + } +} + +bool CGUIWindowManager::HasModalDialog() const +{ + for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + CGUIWindow *window = *it; + if (window->IsModalDialog()) + { // have a modal window + if (!window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE)) + return true; + } + } + return false; +} + +bool CGUIWindowManager::HasDialogOnScreen() const +{ + return (m_activeDialogs.size() > 0); +} + +/// \brief Get the ID of the top most routed window +/// \return id ID of the window or WINDOW_INVALID if no routed window available +int CGUIWindowManager::GetTopMostModalDialogID() const +{ + for (crDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it) + { + CGUIWindow *dialog = *it; + if (dialog->IsModalDialog()) + { // have a modal window + return dialog->GetID(); + } + } + return WINDOW_INVALID; +} + +void CGUIWindowManager::SendThreadMessage(CGUIMessage& message) +{ + ::EnterCriticalSection(&m_critSection ); + + CGUIMessage* msg = new CGUIMessage(message); + m_vecThreadMessages.push_back( pair<CGUIMessage*,int>(msg,0) ); + + ::LeaveCriticalSection(&m_critSection ); +} + +void CGUIWindowManager::SendThreadMessage(CGUIMessage& message, int window) +{ + ::EnterCriticalSection(&m_critSection ); + + CGUIMessage* msg = new CGUIMessage(message); + m_vecThreadMessages.push_back( pair<CGUIMessage*,int>(msg,window) ); + + ::LeaveCriticalSection(&m_critSection ); +} + +void CGUIWindowManager::DispatchThreadMessages() +{ + ::EnterCriticalSection(&m_critSection ); + vector< pair<CGUIMessage*,int> > messages(m_vecThreadMessages); + m_vecThreadMessages.erase(m_vecThreadMessages.begin(), m_vecThreadMessages.end()); + ::LeaveCriticalSection(&m_critSection ); + + while ( messages.size() > 0 ) + { + vector< pair<CGUIMessage*,int> >::iterator it = messages.begin(); + CGUIMessage* pMsg = it->first; + int window = it->second; + // first remove the message from the queue, + // else the message could be processed more then once + it = messages.erase(it); + + if (window) + SendMessage( *pMsg, window ); + else + SendMessage( *pMsg ); + delete pMsg; + } +} + +void CGUIWindowManager::AddMsgTarget( IMsgTargetCallback* pMsgTarget ) +{ + m_vecMsgTargets.push_back( pMsgTarget ); +} + +int CGUIWindowManager::GetActiveWindow() const +{ + if (!m_windowHistory.empty()) + return m_windowHistory.top(); + return WINDOW_INVALID; +} + +// same as GetActiveWindow() except it first grabs dialogs +int CGUIWindowManager::GetFocusedWindow() const +{ + int dialog = GetTopMostModalDialogID(); + if (dialog != WINDOW_INVALID) + return dialog; + + return GetActiveWindow(); +} + +bool CGUIWindowManager::IsWindowActive(int id, bool ignoreClosing /* = true */) const +{ + // mask out multiple instances of the same window + id &= WINDOW_ID_MASK; + if ((GetActiveWindow() & WINDOW_ID_MASK) == id) return true; + // run through the dialogs + for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + CGUIWindow *window = *it; + if ((window->GetID() & WINDOW_ID_MASK) == id && (!ignoreClosing || !window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE))) + return true; + } + return false; // window isn't active +} + +bool CGUIWindowManager::IsWindowActive(const CStdString &xmlFile, bool ignoreClosing /* = true */) const +{ + CGUIWindow *window = GetWindow(GetActiveWindow()); + if (window && CUtil::GetFileName(window->GetXMLFile()).Equals(xmlFile)) return true; + // run through the dialogs + for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + CGUIWindow *window = *it; + if (CUtil::GetFileName(window->GetXMLFile()).Equals(xmlFile) && (!ignoreClosing || !window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE))) + return true; + } + return false; // window isn't active +} + +bool CGUIWindowManager::IsWindowVisible(int id) const +{ + return IsWindowActive(id, false); +} + +bool CGUIWindowManager::IsWindowVisible(const CStdString &xmlFile) const +{ + return IsWindowActive(xmlFile, false); +} + +void CGUIWindowManager::LoadNotOnDemandWindows() +{ + for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++) + { + CGUIWindow *pWindow = (*it).second; + if (!pWindow ->GetLoadOnDemand()) + { + pWindow->FreeResources(true); + pWindow->Initialize(); + } + } +} + +void CGUIWindowManager::UnloadNotOnDemandWindows() +{ + for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++) + { + CGUIWindow *pWindow = (*it).second; + if (!pWindow->GetLoadOnDemand()) + { + pWindow->FreeResources(true); + } + } +} + +bool CGUIWindowManager::IsOverlayAllowed() const +{ + return m_bShowOverlay; +} + +void CGUIWindowManager::ShowOverlay(CGUIWindow::OVERLAY_STATE state) +{ + if (state != CGUIWindow::OVERLAY_STATE_PARENT_WINDOW) + m_bShowOverlay = state == CGUIWindow::OVERLAY_STATE_SHOWN; +} + +void CGUIWindowManager::HideOverlay(CGUIWindow::OVERLAY_STATE state) +{ + if (state == CGUIWindow::OVERLAY_STATE_HIDDEN) + m_bShowOverlay = false; +} + +void CGUIWindowManager::AddToWindowHistory(int newWindowID) +{ + // Check the window stack to see if this window is in our history, + // and if so, pop all the other windows off the stack so that we + // always have a predictable "Back" behaviour for each window + stack<int> historySave = m_windowHistory; + while (historySave.size()) + { + if (historySave.top() == newWindowID) + break; + historySave.pop(); + } + if (!historySave.empty()) + { // found window in history + m_windowHistory = historySave; + } + else + { // didn't find window in history - add it to the stack + m_windowHistory.push(newWindowID); + } +} + +void CGUIWindowManager::GetActiveModelessWindows(vector<int> &ids) +{ + // run through our modeless windows, and construct a vector of them + // useful for saving and restoring the modeless windows on skin change etc. + for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + if (!(*it)->IsModalDialog()) + ids.push_back((*it)->GetID()); + } +} + +CGUIWindow *CGUIWindowManager::GetTopMostDialog() const +{ + // find the window with the lowest render order + vector<CGUIWindow *> renderList = m_activeDialogs; + stable_sort(renderList.begin(), renderList.end(), RenderOrderSortFunction); + + if (!renderList.size()) + return NULL; + + // return the last window in the list + return *renderList.rbegin(); +} + +bool CGUIWindowManager::IsWindowTopMost(int id) const +{ + CGUIWindow *topMost = GetTopMostDialog(); + if (topMost && (topMost->GetID() & WINDOW_ID_MASK) == id) + return true; + return false; +} + +bool CGUIWindowManager::IsWindowTopMost(const CStdString &xmlFile) const +{ + CGUIWindow *topMost = GetTopMostDialog(); + if (topMost && CUtil::GetFileName(topMost->GetXMLFile()).Equals(xmlFile)) + return true; + return false; +} + +void CGUIWindowManager::ClearWindowHistory() +{ + while (m_windowHistory.size()) + m_windowHistory.pop(); +} + +#ifdef _DEBUG +void CGUIWindowManager::DumpTextureUse() +{ + CGUIWindow* pWindow = GetWindow(GetActiveWindow()); + if (pWindow) + pWindow->DumpTextureUse(); + + for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it) + { + if ((*it)->IsDialogRunning()) + (*it)->DumpTextureUse(); + } +} +#endif |