summaryrefslogtreecommitdiffstats
path: root/xbmc/guilib/GUIDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/guilib/GUIDialog.cpp')
-rw-r--r--xbmc/guilib/GUIDialog.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/xbmc/guilib/GUIDialog.cpp b/xbmc/guilib/GUIDialog.cpp
new file mode 100644
index 0000000..a3d0e02
--- /dev/null
+++ b/xbmc/guilib/GUIDialog.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUIDialog.h"
+
+#include "GUIComponent.h"
+#include "GUIControlFactory.h"
+#include "GUILabelControl.h"
+#include "GUIWindowManager.h"
+#include "ServiceBroker.h"
+#include "input/Key.h"
+#include "messaging/ApplicationMessenger.h"
+#include "threads/SingleLock.h"
+#include "utils/TimeUtils.h"
+
+CGUIDialog::CGUIDialog(int id, const std::string &xmlFile, DialogModalityType modalityType /* = DialogModalityType::MODAL */)
+ : CGUIWindow(id, xmlFile)
+{
+ m_modalityType = modalityType;
+ m_wasRunning = false;
+ m_renderOrder = RENDER_ORDER_DIALOG;
+ m_autoClosing = false;
+ m_showStartTime = 0;
+ m_showDuration = 0;
+ m_enableSound = true;
+ m_bAutoClosed = false;
+}
+
+CGUIDialog::~CGUIDialog(void) = default;
+
+bool CGUIDialog::Load(TiXmlElement* pRootElement)
+{
+ return CGUIWindow::Load(pRootElement);
+}
+
+void CGUIDialog::OnWindowLoaded()
+{
+ CGUIWindow::OnWindowLoaded();
+
+ // Clip labels to extents
+ if (m_children.size())
+ {
+ CGUIControl* pBase = m_children[0];
+
+ for (iControls p = m_children.begin() + 1; p != m_children.end(); ++p)
+ {
+ if ((*p)->GetControlType() == CGUIControl::GUICONTROL_LABEL)
+ {
+ CGUILabelControl* pLabel = (CGUILabelControl*)(*p);
+
+ if (!pLabel->GetWidth())
+ {
+ float spacing = (pLabel->GetXPosition() - pBase->GetXPosition()) * 2;
+ pLabel->SetWidth(pBase->GetWidth() - spacing);
+ }
+ }
+ }
+ }
+}
+
+bool CGUIDialog::OnAction(const CAction &action)
+{
+ // keyboard or controller movement should prevent autoclosing
+ if (!action.IsMouse() && m_autoClosing)
+ SetAutoClose(m_showDuration);
+
+ return CGUIWindow::OnAction(action);
+}
+
+bool CGUIDialog::OnBack(int actionID)
+{
+ Close();
+ return true;
+}
+
+bool CGUIDialog::OnMessage(CGUIMessage& message)
+{
+ switch ( message.GetMessage() )
+ {
+ case GUI_MSG_WINDOW_DEINIT:
+ {
+ CGUIWindow::OnMessage(message);
+ return true;
+ }
+ case GUI_MSG_WINDOW_INIT:
+ {
+ CGUIWindow::OnMessage(message);
+ m_showStartTime = 0;
+ return true;
+ }
+ }
+
+ return CGUIWindow::OnMessage(message);
+}
+
+void CGUIDialog::OnDeinitWindow(int nextWindowID)
+{
+ if (m_active)
+ {
+ CServiceBroker::GetGUI()->GetWindowManager().RemoveDialog(GetID());
+ m_autoClosing = false;
+ }
+ CGUIWindow::OnDeinitWindow(nextWindowID);
+}
+
+void CGUIDialog::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions)
+{
+ UpdateVisibility();
+
+ // if we were running but now we're not, mark us dirty
+ if (!m_active && m_wasRunning)
+ dirtyregions.push_back(CDirtyRegion(m_renderRegion));
+
+ if (m_active)
+ CGUIWindow::DoProcess(currentTime, dirtyregions);
+
+ m_wasRunning = m_active;
+}
+
+void CGUIDialog::UpdateVisibility()
+{
+ if (m_visibleCondition)
+ {
+ if (m_visibleCondition->Get(INFO::DEFAULT_CONTEXT))
+ Open();
+ else
+ Close();
+ }
+
+ if (m_autoClosing)
+ { // check if our timer is running
+ if (!m_showStartTime)
+ {
+ if (HasProcessed()) // start timer
+ m_showStartTime = CTimeUtils::GetFrameTime();
+ }
+ else
+ {
+ if (m_showStartTime + m_showDuration < CTimeUtils::GetFrameTime() && !m_closing)
+ {
+ m_bAutoClosed = true;
+ Close();
+ }
+ }
+ }
+}
+
+void CGUIDialog::Open_Internal(bool bProcessRenderLoop, const std::string &param /* = "" */)
+{
+ if (!CServiceBroker::GetGUI()->GetWindowManager().Initialized() ||
+ (m_active && !m_closing && !IsAnimating(ANIM_TYPE_WINDOW_CLOSE)))
+ return;
+
+ // set running before it's added to the window manager, else the auto-show code
+ // could show it as well if we are in a different thread from the main rendering
+ // thread (this should really be handled via a thread message though IMO)
+ m_active = true;
+ m_closing = false;
+ CServiceBroker::GetGUI()->GetWindowManager().RegisterDialog(this);
+
+ // active this window
+ CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0, 0);
+ msg.SetStringParam(param);
+ OnMessage(msg);
+
+ // process render loop
+ if (bProcessRenderLoop)
+ {
+ if (!m_windowLoaded)
+ Close(true);
+
+ while (m_active)
+ {
+ if (!CServiceBroker::GetGUI()->GetWindowManager().ProcessRenderLoop(false))
+ break;
+ }
+ }
+}
+
+void CGUIDialog::Open(const std::string &param /* = "" */)
+{
+ CGUIDialog::Open(m_modalityType != DialogModalityType::MODELESS, param);
+}
+
+
+void CGUIDialog::Open(bool bProcessRenderLoop, const std::string& param /* = "" */)
+{
+ if (!CServiceBroker::GetAppMessenger()->IsProcessThread())
+ {
+ // make sure graphics lock is not held
+ CSingleExit leaveIt(CServiceBroker::GetWinSystem()->GetGfxContext());
+ CServiceBroker::GetAppMessenger()->SendMsg(TMSG_GUI_DIALOG_OPEN, -1, bProcessRenderLoop,
+ static_cast<void*>(this), param);
+ }
+ else
+ Open_Internal(bProcessRenderLoop, param);
+}
+
+void CGUIDialog::Render()
+{
+ if (!m_active)
+ return;
+
+ CGUIWindow::Render();
+}
+
+void CGUIDialog::SetDefaults()
+{
+ CGUIWindow::SetDefaults();
+ m_renderOrder = RENDER_ORDER_DIALOG;
+}
+
+void CGUIDialog::SetAutoClose(unsigned int timeoutMs)
+{
+ m_autoClosing = true;
+ m_showDuration = timeoutMs;
+ ResetAutoClose();
+}
+
+void CGUIDialog::ResetAutoClose(void)
+{
+ if (m_autoClosing && m_active)
+ m_showStartTime = CTimeUtils::GetFrameTime();
+}
+
+void CGUIDialog::CancelAutoClose(void)
+{
+ m_autoClosing = false;
+}
+
+void CGUIDialog::ProcessRenderLoop(bool renderOnly)
+{
+ CServiceBroker::GetGUI()->GetWindowManager().ProcessRenderLoop(renderOnly);
+}