mirror of https://github.com/xbmc/xbmc
241 lines
5.5 KiB
C++
241 lines
5.5 KiB
C++
/*
|
|
* 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/actions/Action.h"
|
|
#include "input/actions/ActionIDs.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.empty())
|
|
{
|
|
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.emplace_back(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 ¶m /* = "" */)
|
|
{
|
|
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 ¶m /* = "" */)
|
|
{
|
|
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);
|
|
}
|