2014-10-14 13:11:37 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
2016-02-13 13:11:30 +00:00
|
|
|
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
2015-08-22 14:40:02 +00:00
|
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
2014-10-14 13:11:37 +00:00
|
|
|
*
|
|
|
|
* 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 3 of the License, 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 this program. If not, see http://gnu.org/licenses
|
|
|
|
*/
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
2012-09-18 22:04:21 +00:00
|
|
|
#include "ui/mainshort.h"
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
#include "app/app.h"
|
2015-08-31 19:57:46 +00:00
|
|
|
#include "app/pausemanager.h"
|
2013-02-16 21:37:43 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
#include "common/logger.h"
|
|
|
|
|
2015-08-13 09:47:32 +00:00
|
|
|
#include "level/robotmain.h"
|
|
|
|
|
2015-07-12 10:13:19 +00:00
|
|
|
#include "object/object.h"
|
2015-08-02 11:09:48 +00:00
|
|
|
#include "object/object_manager.h"
|
2013-02-16 21:37:43 +00:00
|
|
|
|
2015-08-10 21:20:36 +00:00
|
|
|
#include "object/interface/controllable_object.h"
|
2015-08-10 16:16:00 +00:00
|
|
|
#include "object/interface/programmable_object.h"
|
|
|
|
|
2015-09-27 14:28:11 +00:00
|
|
|
#include "ui/controls/interface.h"
|
|
|
|
#include "ui/controls/shortcut.h"
|
|
|
|
|
2015-08-15 12:02:07 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
2015-08-02 09:40:47 +00:00
|
|
|
namespace Ui
|
|
|
|
{
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
// Constructor of the application card.
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
CMainShort::CMainShort()
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
m_event = CApplication::GetInstancePointer()->GetEventQueue();
|
|
|
|
m_engine = Gfx::CEngine::GetInstancePointer();
|
|
|
|
m_main = CRobotMain::GetInstancePointer();
|
|
|
|
m_interface = m_main->GetInterface();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
m_shortcuts.clear();
|
2015-08-11 20:47:07 +00:00
|
|
|
|
|
|
|
m_bBuilding = false;
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Destructor of the application card.
|
|
|
|
|
|
|
|
CMainShort::~CMainShort()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CMainShort::SetMode(bool bBuilding)
|
|
|
|
{
|
|
|
|
m_bBuilding = bBuilding;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Interface creates shortcuts to the units.
|
|
|
|
|
|
|
|
bool CMainShort::CreateShortcuts()
|
|
|
|
{
|
|
|
|
Math::Point pos, dim;
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( m_main->GetFixScene() ) return false;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
// Delete all old controls
|
2012-06-26 20:23:05 +00:00
|
|
|
m_interface->DeleteControl(EVENT_OBJECT_MOVIELOCK);
|
|
|
|
m_interface->DeleteControl(EVENT_OBJECT_EDITLOCK);
|
2015-08-06 18:15:17 +00:00
|
|
|
m_interface->DeleteControl(EVENT_OBJECT_SAVING);
|
2015-07-16 11:46:05 +00:00
|
|
|
m_interface->DeleteControl(EVENT_OBJECT_SHORTCUT_MODE);
|
|
|
|
for (int i = EVENT_OBJECT_SHORTCUT; i <= EVENT_OBJECT_SHORTCUT_MAX; i++)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
m_interface->DeleteControl(static_cast<EventType>(i));
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
2015-07-16 11:46:05 +00:00
|
|
|
m_shortcuts.clear();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-20 19:07:20 +00:00
|
|
|
|
|
|
|
Math::IntPoint size = m_engine->GetWindowSize();
|
|
|
|
float ratio = static_cast<float>(size.y) / static_cast<float>(size.x);
|
|
|
|
|
2015-07-16 18:09:06 +00:00
|
|
|
// Display pause / movie indicator
|
2012-06-26 20:23:05 +00:00
|
|
|
dim.y = 28.0f/480.0f;
|
2015-07-20 19:07:20 +00:00
|
|
|
dim.x = dim.y*ratio;
|
2012-06-26 20:23:05 +00:00
|
|
|
pos.x = 4.0f/640.0f;
|
|
|
|
pos.y = (480.0f-32.0f)/480.0f;
|
|
|
|
|
2015-08-06 18:15:17 +00:00
|
|
|
m_interface->CreateShortcut(pos, dim, 58, EVENT_OBJECT_SAVING);
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( m_main->GetMovieLock() &&
|
|
|
|
!m_main->GetEditLock() ) // hangs during film?
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-08-06 18:15:17 +00:00
|
|
|
m_interface->CreateShortcut(pos, dim, 128+7, EVENT_OBJECT_MOVIELOCK);
|
2012-06-26 20:23:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-10-01 16:55:41 +00:00
|
|
|
if ( !m_main->GetPauseManager()->IsPauseType(PAUSE_PHOTO) &&
|
2012-08-21 19:38:13 +00:00
|
|
|
(m_main->GetEditLock() ||
|
|
|
|
m_engine->GetPause()) ) // hangs during edition?
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-08-06 18:15:17 +00:00
|
|
|
m_interface->CreateShortcut(pos, dim, 128+6, EVENT_OBJECT_EDITLOCK);
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
2015-10-01 16:55:41 +00:00
|
|
|
if (m_main->GetPauseManager()->IsPauseType(PAUSE_PHOTO) && m_main->GetSelect() == nullptr)
|
2015-07-14 19:32:08 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2015-08-31 19:57:46 +00:00
|
|
|
|
2015-10-01 16:55:41 +00:00
|
|
|
if (m_main->GetPauseManager()->IsPauseType(PAUSE_HIDE_SHORTCUTS))
|
2015-08-31 19:57:46 +00:00
|
|
|
return true;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
// Create new shortcuts
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-08-06 18:15:17 +00:00
|
|
|
m_interface->CreateShortcut(pos, dim, 128+2, EVENT_OBJECT_SHORTCUT_MODE);
|
2012-06-26 20:23:05 +00:00
|
|
|
pos.x += dim.x*1.2f;
|
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
std::vector<int> teams;
|
|
|
|
for (CObject* object : CObjectManager::GetInstancePointer()->GetAllObjects())
|
|
|
|
{
|
2015-08-16 18:24:48 +00:00
|
|
|
if (!object->GetDetectable())
|
2015-07-16 11:46:05 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if(GetShortcutIcon(object->GetType()) == -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(std::find(teams.begin(), teams.end(), object->GetTeam()) == teams.end())
|
|
|
|
teams.push_back(object->GetTeam());
|
|
|
|
}
|
|
|
|
std::sort(teams.begin(), teams.end());
|
|
|
|
|
|
|
|
std::vector<Math::Point> positions;
|
|
|
|
for(unsigned int i = 0; i < teams.size(); i++)
|
|
|
|
{
|
|
|
|
positions.push_back(pos);
|
|
|
|
pos.y -= dim.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rank = 0;
|
2015-06-21 14:22:09 +00:00
|
|
|
for (CObject* pObj : CObjectManager::GetInstancePointer()->GetAllObjects())
|
|
|
|
{
|
2015-08-16 18:24:48 +00:00
|
|
|
if ( !pObj->GetDetectable() ) continue;
|
2015-08-10 21:20:36 +00:00
|
|
|
if ( pObj->Implements(ObjectInterfaceType::Controllable) && !dynamic_cast<CControllableObject*>(pObj)->GetSelectable() ) continue;
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( pObj->GetProxyActivate() ) continue;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
int icon = GetShortcutIcon(pObj->GetType());
|
2012-06-26 20:23:05 +00:00
|
|
|
if ( icon == -1 ) continue;
|
|
|
|
|
2015-07-16 18:09:06 +00:00
|
|
|
unsigned int teamIndex = std::find(teams.begin(), teams.end(), pObj->GetTeam()) - teams.begin();
|
2015-07-16 11:46:05 +00:00
|
|
|
|
2015-07-16 18:09:06 +00:00
|
|
|
CShortcut* shortcut = m_interface->CreateShortcut(positions[teamIndex], dim, icon, static_cast<EventType>(EVENT_OBJECT_SHORTCUT+rank));
|
|
|
|
positions[teamIndex].x += dim.x;
|
2015-07-16 11:46:05 +00:00
|
|
|
m_shortcuts.push_back(pObj);
|
|
|
|
|
2015-08-11 22:12:37 +00:00
|
|
|
shortcut->SetTooltip(pObj->GetTooltipText());
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
rank ++;
|
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
if (rank > EVENT_OBJECT_SHORTCUT_MAX-EVENT_OBJECT_SHORTCUT)
|
|
|
|
{
|
2015-07-16 19:30:55 +00:00
|
|
|
GetLogger()->Warn("Not enough shortcut slots!\n");
|
2015-07-16 11:46:05 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateShortcuts();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
int CMainShort::GetShortcutIcon(ObjectType type)
|
|
|
|
{
|
|
|
|
int icon = -1;
|
|
|
|
if ( m_bBuilding )
|
|
|
|
{
|
|
|
|
if ( type == OBJECT_FACTORY ) icon = 32;
|
|
|
|
if ( type == OBJECT_DERRICK ) icon = 33;
|
|
|
|
if ( type == OBJECT_CONVERT ) icon = 34;
|
|
|
|
if ( type == OBJECT_RESEARCH ) icon = 35;
|
|
|
|
if ( type == OBJECT_STATION ) icon = 36;
|
|
|
|
if ( type == OBJECT_TOWER ) icon = 37;
|
|
|
|
if ( type == OBJECT_LABO ) icon = 38;
|
|
|
|
if ( type == OBJECT_ENERGY ) icon = 39;
|
|
|
|
if ( type == OBJECT_RADAR ) icon = 40;
|
|
|
|
if ( type == OBJECT_INFO ) icon = 44;
|
|
|
|
if ( type == OBJECT_REPAIR ) icon = 41;
|
|
|
|
if ( type == OBJECT_DESTROYER) icon = 41;
|
|
|
|
if ( type == OBJECT_NUCLEAR ) icon = 42;
|
|
|
|
if ( type == OBJECT_PARA ) icon = 46;
|
|
|
|
if ( type == OBJECT_SAFE ) icon = 47;
|
|
|
|
if ( type == OBJECT_HUSTON ) icon = 48;
|
|
|
|
if ( type == OBJECT_BASE ) icon = 43;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( type == OBJECT_HUMAN ) icon = 8;
|
|
|
|
if ( type == OBJECT_MOBILEfa ) icon = 11;
|
|
|
|
if ( type == OBJECT_MOBILEta ) icon = 10;
|
|
|
|
if ( type == OBJECT_MOBILEwa ) icon = 9;
|
|
|
|
if ( type == OBJECT_MOBILEia ) icon = 22;
|
|
|
|
if ( type == OBJECT_MOBILEfc ) icon = 17;
|
|
|
|
if ( type == OBJECT_MOBILEtc ) icon = 16;
|
|
|
|
if ( type == OBJECT_MOBILEwc ) icon = 15;
|
|
|
|
if ( type == OBJECT_MOBILEic ) icon = 23;
|
|
|
|
if ( type == OBJECT_MOBILEfi ) icon = 27;
|
|
|
|
if ( type == OBJECT_MOBILEti ) icon = 26;
|
|
|
|
if ( type == OBJECT_MOBILEwi ) icon = 25;
|
|
|
|
if ( type == OBJECT_MOBILEii ) icon = 28;
|
|
|
|
if ( type == OBJECT_MOBILEfs ) icon = 14;
|
|
|
|
if ( type == OBJECT_MOBILEts ) icon = 13;
|
|
|
|
if ( type == OBJECT_MOBILEws ) icon = 12;
|
|
|
|
if ( type == OBJECT_MOBILEis ) icon = 24;
|
|
|
|
if ( type == OBJECT_MOBILErt ) icon = 18;
|
|
|
|
if ( type == OBJECT_MOBILErc ) icon = 19;
|
|
|
|
if ( type == OBJECT_MOBILErr ) icon = 20;
|
|
|
|
if ( type == OBJECT_MOBILErs ) icon = 29;
|
|
|
|
if ( type == OBJECT_MOBILEsa ) icon = 21;
|
|
|
|
if ( type == OBJECT_MOBILEft ) icon = 30;
|
|
|
|
if ( type == OBJECT_MOBILEtt ) icon = 30;
|
|
|
|
if ( type == OBJECT_MOBILEwt ) icon = 30;
|
|
|
|
if ( type == OBJECT_MOBILEit ) icon = 30;
|
|
|
|
if ( type == OBJECT_MOBILEdr ) icon = 48;
|
|
|
|
if ( type == OBJECT_APOLLO2 ) icon = 49;
|
|
|
|
}
|
2015-08-06 18:15:17 +00:00
|
|
|
if ( icon == -1 ) return -1;
|
|
|
|
return 128+icon;
|
2015-07-16 11:46:05 +00:00
|
|
|
}
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
// Updates the interface shortcuts to the units.
|
|
|
|
|
|
|
|
bool CMainShort::UpdateShortcuts()
|
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
for(unsigned int i = 0; i < m_shortcuts.size(); i++)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
CControl* pc = m_interface->SearchControl(static_cast<EventType>(EVENT_OBJECT_SHORTCUT+i));
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( pc != nullptr )
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-08-10 21:20:36 +00:00
|
|
|
assert(m_shortcuts[i]->Implements(ObjectInterfaceType::Controllable));
|
|
|
|
pc->SetState(STATE_CHECK, dynamic_cast<CControllableObject*>(m_shortcuts[i])->GetSelect());
|
2015-08-10 16:16:00 +00:00
|
|
|
pc->SetState(STATE_RUN, m_shortcuts[i]->Implements(ObjectInterfaceType::Programmable) && dynamic_cast<CProgrammableObject*>(m_shortcuts[i])->IsProgram());
|
2017-06-20 21:35:33 +00:00
|
|
|
pc->SetState(STATE_DAMAGE, dynamic_cast<CDamageableObject*>(m_shortcuts[i])->IsDamaging());
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Selects an object through a shortcut.
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
void CMainShort::SelectShortcut(EventType event)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
if (event == EVENT_OBJECT_SHORTCUT_MODE)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
m_bBuilding = !m_bBuilding;
|
|
|
|
CreateShortcuts();
|
|
|
|
}
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
if(event >= EVENT_OBJECT_SHORTCUT && event <= EVENT_OBJECT_SHORTCUT_MAX)
|
|
|
|
{
|
|
|
|
unsigned int i = event-EVENT_OBJECT_SHORTCUT;
|
|
|
|
m_main->SelectObject(m_shortcuts[i]);
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Selects the next object.
|
|
|
|
|
|
|
|
void CMainShort::SelectNext()
|
|
|
|
{
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( m_main->GetMovieLock() ||
|
|
|
|
m_main->GetEditLock() ||
|
|
|
|
m_engine->GetPause() ) return;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2015-07-16 11:46:05 +00:00
|
|
|
CObject* pPrev = m_main->DeselectAll();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
2016-12-27 22:38:57 +00:00
|
|
|
if (m_shortcuts.size() == 0)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2016-12-27 22:38:57 +00:00
|
|
|
m_main->SelectObject(m_main->SearchHuman());
|
2015-07-16 18:09:06 +00:00
|
|
|
return;
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
2015-07-16 18:09:06 +00:00
|
|
|
// Find the current object in the list
|
|
|
|
auto it = std::find(m_shortcuts.begin(), m_shortcuts.end(), pPrev);
|
|
|
|
|
|
|
|
// Get the next one
|
|
|
|
if (it != m_shortcuts.end())
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 18:09:06 +00:00
|
|
|
++it;
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
2015-07-16 18:09:06 +00:00
|
|
|
// If there is no more left, return to the first one
|
|
|
|
if (it == m_shortcuts.end())
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 18:09:06 +00:00
|
|
|
it = m_shortcuts.begin();
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
2015-07-16 18:09:06 +00:00
|
|
|
|
|
|
|
m_main->SelectObject(*it);
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// The object detected by the mouse hovers over.
|
|
|
|
|
|
|
|
CObject* CMainShort::DetectShort(Math::Point pos)
|
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
for (unsigned int i = 0; i < m_shortcuts.size(); i++)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
CControl* pc = m_interface->SearchControl(static_cast<EventType>(EVENT_OBJECT_SHORTCUT+i));
|
|
|
|
if ( pc != nullptr )
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
Math::Point cpos = pc->GetPos();
|
|
|
|
Math::Point cdim = pc->GetDim();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
if ( pos.x >= cpos.x &&
|
|
|
|
pos.x <= cpos.x+cdim.x &&
|
|
|
|
pos.y >= cpos.y &&
|
|
|
|
pos.y <= cpos.y+cdim.y )
|
|
|
|
{
|
|
|
|
return m_shortcuts[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-17 20:40:52 +00:00
|
|
|
return nullptr;
|
2012-06-26 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reports the object with the mouse hovers over.
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
void CMainShort::SetHighlight(CObject* pObj)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
for (unsigned int i = 0; i < m_shortcuts.size(); i++)
|
2012-06-26 20:23:05 +00:00
|
|
|
{
|
2015-07-16 11:46:05 +00:00
|
|
|
CControl* pc = m_interface->SearchControl(static_cast<EventType>(EVENT_OBJECT_SHORTCUT+i));
|
2012-08-21 19:38:13 +00:00
|
|
|
if ( pc == nullptr ) continue;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
if ( m_shortcuts[i] == pObj )
|
|
|
|
{
|
|
|
|
pc->SetState(STATE_HILIGHT);
|
|
|
|
pc->SetState(STATE_FRAME);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pc->ClearState(STATE_HILIGHT);
|
|
|
|
pc->ClearState(STATE_FRAME);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-21 19:38:13 +00:00
|
|
|
}
|