usbloadergx/source/libwiigui/gui_window.cpp
giantpune 9e79c9d99b * remove little unused code
* code cleanup
2010-09-18 23:16:05 +00:00

431 lines
11 KiB
C++

/****************************************************************************
* libwiigui
*
* Tantric 2009
*
* gui_window.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
GuiWindow::GuiWindow()
{
width = 0;
height = 0;
focus = 0; // allow focus
}
GuiWindow::GuiWindow( int w, int h )
{
width = w;
height = h;
focus = 0; // allow focus
}
GuiWindow::~GuiWindow()
{
}
void GuiWindow::Append( GuiElement* e )
{
LOCK( this );
if ( e == NULL )
return;
Remove( e );
_elements.push_back( e );
e->SetParent( this );
}
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 );
}
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();
}
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 )
//Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1);
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 ) { }
}
}
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 ) { }
}
}
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 ) { }
}
}
void GuiWindow::SetFocus( int f )
{
LOCK( this );
focus = f;
if ( f == 1 )
this->MoveSelectionVert( 1 );
else
this->ResetState();
}
void GuiWindow::ChangeFocus( GuiElement* e )
{
LOCK( this );
if ( parentElement )
return; // this is only intended for the main window
for ( u8 i = 0; i < _elements.size(); i++ )
{
if ( e == _elements.at( i ) )
_elements.at( i )->SetFocus( 1 );
else if ( _elements.at( i )->IsFocused() == 1 )
_elements.at( i )->SetFocus( 0 );
}
}
void GuiWindow::ToggleFocus( GuiTrigger * t )
{
LOCK( this );
if ( parentElement )
return; // this is only intended for the main window
int found = -1;
int newfocus = -1;
u8 i;
// look for currently in focus element
for ( i = 0; i < _elements.size(); i++ )
{
try
{
if ( _elements.at( i )->IsFocused() == 1 )
{
found = i;
break;
}
}
catch ( const std::exception& e ) { }
}
// element with focus not found, try to give focus
if ( found == -1 )
{
for ( i = 0; i < _elements.size(); i++ )
{
try
{
if ( _elements.at( i )->IsFocused() == 0 && _elements.at( i )->GetState() != STATE_DISABLED ) // focus is possible (but not set)
{
_elements.at( i )->SetFocus( 1 ); // give this element focus
break;
}
}
catch ( const std::exception& e ) { }
}
}
// change focus
else if ( t->wpad.btns_d & ( WPAD_BUTTON_1 | WPAD_BUTTON_1 | WPAD_CLASSIC_BUTTON_PLUS )
|| t->pad.btns_d & PAD_BUTTON_B )
{
for ( i = found; i < _elements.size(); i++ )
{
try
{
if ( _elements.at( i )->IsFocused() == 0 && _elements.at( i )->GetState() != STATE_DISABLED ) // focus is possible (but not set)
{
newfocus = i;
_elements.at( i )->SetFocus( 1 ); // give this element focus
_elements.at( found )->SetFocus( 0 ); // disable focus on other element
break;
}
}
catch ( const std::exception& e ) { }
}
if ( newfocus == -1 )
{
for ( i = 0; i < found; i++ )
{
try
{
if ( _elements.at( i )->IsFocused() == 0 && _elements.at( i )->GetState() != STATE_DISABLED ) // focus is possible (but not set)
{
_elements.at( i )->SetFocus( 1 ); // give this element focus
_elements.at( found )->SetFocus( 0 ); // disable focus on other element
break;
}
}
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
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();
}
}
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();
}
}
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 ) { }
}
this->ToggleFocus( t );
if ( focus ) // only send actions to this window if it's in focus
{
// pad/joystick navigation
if ( t->Right() )
this->MoveSelectionHor( 1 );
else if ( t->Left() )
this->MoveSelectionHor( -1 );
else if ( t->Down() )
this->MoveSelectionVert( 1 );
else if ( t->Up() )
this->MoveSelectionVert( -1 );
}
if ( updateCB )
updateCB( this );
}