usbloadergx/source/GUI/gui_window.cpp

330 lines
5.9 KiB
C++
Raw Normal View History

/****************************************************************************
* libwiigui
*
* Tantric 2009
*
* gui_window.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
GuiWindow::GuiWindow()
{
width = 0;
height = 0;
forceDim = false;
allowDim = true;
}
2010-09-24 02:48:03 +02:00
GuiWindow::GuiWindow(int w, int h)
{
width = w;
height = h;
forceDim = false;
allowDim = true;
}
GuiWindow::~GuiWindow()
{
}
2010-09-24 02:48:03 +02:00
void GuiWindow::Append(GuiElement* e)
{
LOCK( this );
if (e == NULL) return;
Remove(e);
_elements.push_back(e);
e->SetParent(this);
}
2010-09-24 02:48:03 +02:00
void GuiWindow::Insert(GuiElement* e, u32 index)
{
LOCK( this );
if (e == NULL || index > (_elements.size() - 1)) return;
Remove(e);
_elements.insert(_elements.begin() + index, e);
e->SetParent(this);
}
2010-09-24 02:48:03 +02:00
void GuiWindow::Remove(GuiElement* e)
{
LOCK( this );
if (e == NULL) return;
for (u8 i = 0; i < _elements.size(); i++)
{
if (e == _elements.at(i))
{
_elements.erase(_elements.begin() + i);
break;
}
}
}
void GuiWindow::RemoveAll()
{
LOCK( this );
_elements.clear();
}
2010-09-24 02:48:03 +02:00
GuiElement* GuiWindow::GetGuiElementAt(u32 index) const
{
if (index >= _elements.size()) return NULL;
return _elements.at(index);
}
u32 GuiWindow::GetSize()
{
return _elements.size();
}
void GuiWindow::Draw()
{
LOCK( this );
if (_elements.size() == 0 || !this->IsVisible()) return;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->Draw();
}
catch (const std::exception& e)
{
}
}
this->UpdateEffects();
if ((parentElement && state == STATE_DISABLED && allowDim) || forceDim)
Menu_DrawRectangle(0, 0, screenwidth, screenheight, (GXColor) {0, 0, 0, 0x70}, 1);
}
void GuiWindow::DrawTooltip()
{
LOCK( this );
if (_elements.size() == 0 || !this->IsVisible()) return;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->DrawTooltip();
}
catch (const std::exception& e)
{
}
}
}
void GuiWindow::ResetState()
{
LOCK( this );
if (state != STATE_DISABLED) state = STATE_DEFAULT;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->ResetState();
}
catch (const std::exception& e)
{
}
}
}
2010-09-24 02:48:03 +02:00
void GuiWindow::SetState(int s)
{
LOCK( this );
state = s;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->SetState(s);
}
catch (const std::exception& e)
{
}
}
}
2010-09-24 02:48:03 +02:00
void GuiWindow::SetVisible(bool v)
{
LOCK( this );
visible = v;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->SetVisible(v);
}
catch (const std::exception& e)
{
}
}
}
int GuiWindow::GetSelected()
{
// find selected element
int found = -1;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
if (_elements.at(i)->GetState() == STATE_SELECTED)
{
found = i;
break;
}
}
catch (const std::exception& e)
{
}
}
return found;
}
// set element to left/right as selected
// there's probably a more clever way to do this, but this way works
2010-09-24 02:48:03 +02:00
void GuiWindow::MoveSelectionHor(int dir)
{
LOCK( this );
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if (selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button on the same row, to the left/right
for (i = 0; i < _elements.size(); i++)
{
try
{
if (_elements.at(i)->IsSelectable())
{
if (_elements.at(i)->GetLeft() * dir > left * dir && _elements.at(i)->GetTop() == top)
{
if (found == -1)
found = i;
else if (_elements.at(i)->GetLeft() * dir < _elements.at(found)->GetLeft() * dir) found = i; // this is a better match
}
}
}
catch (const std::exception& e)
{
}
}
if (found >= 0) goto matchfound;
// match still not found, let's try the first button in the next row
for (i = 0; i < _elements.size(); i++)
{
try
{
if (_elements.at(i)->IsSelectable())
{
if (_elements.at(i)->GetTop() * dir > top * dir)
{
if (found == -1)
found = i;
else if (_elements.at(i)->GetTop() * dir < _elements.at(found)->GetTop() * dir)
found = i; // this is a better match
else if (_elements.at(i)->GetTop() * dir == _elements.at(found)->GetTop() * dir
&& _elements.at(i)->GetLeft() * dir < _elements.at(found)->GetLeft() * dir) found = i; // this is a better match
}
}
}
catch (const std::exception& e)
{
}
}
// match found
matchfound: if (found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if (selected >= 0) _elements.at(selected)->ResetState();
}
}
2010-09-24 02:48:03 +02:00
void GuiWindow::MoveSelectionVert(int dir)
{
LOCK( this );
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if (selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button above/below, with the least horizontal difference
for (i = 0; i < _elements.size(); i++)
{
try
{
if (_elements.at(i)->IsSelectable())
{
if (_elements.at(i)->GetTop() * dir > top * dir)
{
if (found == -1)
found = i;
else if (_elements.at(i)->GetTop() * dir < _elements.at(found)->GetTop() * dir)
found = i; // this is a better match
else if (_elements.at(i)->GetTop() * dir == _elements.at(found)->GetTop() * dir && abs(
_elements.at(i)->GetLeft() - left) < abs(_elements.at(found)->GetLeft() - left)) found = i;
}
}
}
catch (const std::exception& e)
{
}
}
if (found >= 0) goto matchfound;
// match found
matchfound: if (found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if (selected >= 0) _elements.at(selected)->ResetState();
}
}
2010-09-24 02:48:03 +02:00
void GuiWindow::Update(GuiTrigger * t)
{
LOCK( this );
if (_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) return;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
_elements.at(i)->Update(t);
}
catch (const std::exception& e)
{
}
}
if (updateCB) updateCB(this);
}