622 lines
14 KiB
C++
622 lines
14 KiB
C++
#include <iostream>
|
|
#include "Window.h"
|
|
#include "Engine.h"
|
|
#include "Keys.h"
|
|
#include "Component.h"
|
|
#include "gui/interface/Point.h"
|
|
#include "gui/interface/Button.h"
|
|
|
|
using namespace ui;
|
|
|
|
Window::Window(Point _position, Point _size):
|
|
Position(_position),
|
|
Size(_size),
|
|
AllowExclusiveDrawing(true),
|
|
okayButton(NULL),
|
|
cancelButton(NULL),
|
|
focusedComponent_(NULL),
|
|
hoverComponent(NULL),
|
|
#ifdef DEBUG
|
|
debugMode(false),
|
|
#endif
|
|
halt(false),
|
|
destruct(false),
|
|
stop(false)
|
|
{
|
|
}
|
|
|
|
Window::~Window()
|
|
{
|
|
for (unsigned i = 0, sz = Components.size(); i < sz; ++i)
|
|
if (Components[i])
|
|
{
|
|
delete Components[i];
|
|
}
|
|
Components.clear();
|
|
}
|
|
|
|
void Window::AddComponent(Component* c)
|
|
{
|
|
if (c->GetParentWindow() == NULL)
|
|
{
|
|
c->SetParentWindow(this);
|
|
Components.push_back(c);
|
|
|
|
if (Engine::Ref().GetMouseX() > Position.X + c->Position.X && Engine::Ref().GetMouseX() < Position.X + c->Position.X + c->Size.X &&
|
|
Engine::Ref().GetMouseY() > Position.Y + c->Position.Y && Engine::Ref().GetMouseY() < Position.Y + c->Position.Y + c->Size.Y)
|
|
c->OnMouseEnter(Engine::Ref().GetMouseX() - (Position.X + c->Position.X), Engine::Ref().GetMouseY() - (Position.Y + c->Position.Y));
|
|
}
|
|
else
|
|
{
|
|
//Component already in a window
|
|
}
|
|
}
|
|
|
|
unsigned Window::GetComponentCount()
|
|
{
|
|
return Components.size();
|
|
}
|
|
|
|
Component* Window::GetComponent(unsigned idx)
|
|
{
|
|
return Components[idx];
|
|
}
|
|
|
|
void Window::RemoveComponent(Component* c)
|
|
{
|
|
// remove component WITHOUT freeing it.
|
|
for (unsigned i = 0; i < Components.size(); ++i)
|
|
{
|
|
// find the appropriate component index
|
|
if (Components[i] == c)
|
|
{
|
|
//Make sure any events don't continue
|
|
halt = true;
|
|
if (Components[i] == focusedComponent_)
|
|
focusedComponent_ = NULL;
|
|
if (Components[i] == hoverComponent)
|
|
hoverComponent = NULL;
|
|
|
|
Components.erase(Components.begin() + i);
|
|
|
|
// we're done
|
|
c->SetParentWindow(NULL);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::OnTryExit(ExitMethod method)
|
|
{
|
|
if (cancelButton && method != MouseOutside)
|
|
cancelButton->DoAction();
|
|
}
|
|
|
|
void Window::OnTryOkay(OkayMethod method)
|
|
{
|
|
if (okayButton)
|
|
okayButton->DoAction();
|
|
}
|
|
|
|
void Window::RemoveComponent(unsigned idx)
|
|
{
|
|
halt = true;
|
|
// free component and remove it.
|
|
if (Components[idx] == focusedComponent_)
|
|
focusedComponent_ = NULL;
|
|
if (Components[idx] == hoverComponent)
|
|
hoverComponent = NULL;
|
|
delete Components[idx];
|
|
Components.erase(Components.begin() + idx);
|
|
}
|
|
|
|
bool Window::IsFocused(const Component* c) const
|
|
{
|
|
return c == focusedComponent_;
|
|
}
|
|
|
|
void Window::FocusComponent(Component* c)
|
|
{
|
|
this->focusedComponent_ = c;
|
|
}
|
|
|
|
void Window::MakeActiveWindow()
|
|
{
|
|
if (Engine::Ref().GetWindow() != this)
|
|
Engine::Ref().ShowWindow(this);
|
|
}
|
|
|
|
bool Window::CloseActiveWindow()
|
|
{
|
|
if (Engine::Ref().GetWindow() == this)
|
|
{
|
|
Engine::Ref().CloseWindow();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Graphics * Window::GetGraphics()
|
|
{
|
|
return Engine::Ref().g;
|
|
}
|
|
|
|
void Window::DoExit()
|
|
{
|
|
OnExit();
|
|
}
|
|
|
|
void Window::DoInitialized()
|
|
{
|
|
OnInitialized();
|
|
}
|
|
|
|
void Window::DoBlur()
|
|
{
|
|
OnBlur();
|
|
}
|
|
|
|
void Window::DoFocus()
|
|
{
|
|
OnFocus();
|
|
}
|
|
|
|
void Window::DoDraw()
|
|
{
|
|
OnDraw();
|
|
for (int i = 0, sz = Components.size(); i < sz; ++i)
|
|
if (Components[i]->Visible && ((Components[i] != focusedComponent_ && Components[i] != hoverComponent) || Components[i]->GetParent()))
|
|
{
|
|
Point scrpos(Components[i]->Position.X + Position.X, Components[i]->Position.Y + Position.Y);
|
|
if (AllowExclusiveDrawing)
|
|
{
|
|
Components[i]->Draw(scrpos);
|
|
}
|
|
else
|
|
{
|
|
if (scrpos.X + Components[i]->Size.X >= 0 &&
|
|
scrpos.Y + Components[i]->Size.Y >= 0 &&
|
|
scrpos.X < ui::Engine::Ref().GetWidth() &&
|
|
scrpos.Y < ui::Engine::Ref().GetHeight())
|
|
{
|
|
Components[i]->Draw(scrpos);
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
{
|
|
if (focusedComponent_==Components[i])
|
|
{
|
|
ui::Engine::Ref().g->fillrect(Components[i]->Position.X+Position.X, Components[i]->Position.Y+Position.Y, Components[i]->Size.X, Components[i]->Size.Y, 0, 255, 0, 90);
|
|
}
|
|
else
|
|
{
|
|
ui::Engine::Ref().g->fillrect(Components[i]->Position.X+Position.X, Components[i]->Position.Y+Position.Y, Components[i]->Size.X, Components[i]->Size.Y, 255, 0, 0, 90);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// the component the mouse is hovering over and the focused component are always drawn last
|
|
if (hoverComponent && hoverComponent->Visible && hoverComponent->GetParent() == NULL)
|
|
{
|
|
Point scrpos(hoverComponent->Position.X + Position.X, hoverComponent->Position.Y + Position.Y);
|
|
if ((scrpos.X + hoverComponent->Size.X >= 0 &&
|
|
scrpos.Y + hoverComponent->Size.Y >= 0 &&
|
|
scrpos.X < ui::Engine::Ref().GetWidth() &&
|
|
scrpos.Y < ui::Engine::Ref().GetHeight()
|
|
) || AllowExclusiveDrawing)
|
|
{
|
|
hoverComponent->Draw(scrpos);
|
|
}
|
|
}
|
|
if (focusedComponent_ && focusedComponent_ != hoverComponent && focusedComponent_->Visible && focusedComponent_->GetParent() == NULL)
|
|
{
|
|
Point scrpos(focusedComponent_->Position.X + Position.X, focusedComponent_->Position.Y + Position.Y);
|
|
if ((scrpos.X + focusedComponent_->Size.X >= 0 &&
|
|
scrpos.Y + focusedComponent_->Size.Y >= 0 &&
|
|
scrpos.X < ui::Engine::Ref().GetWidth() &&
|
|
scrpos.Y < ui::Engine::Ref().GetHeight()
|
|
) || AllowExclusiveDrawing)
|
|
{
|
|
focusedComponent_->Draw(scrpos);
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
{
|
|
if (focusedComponent_)
|
|
{
|
|
int xPos = focusedComponent_->Position.X+focusedComponent_->Size.X+5+Position.X;
|
|
Graphics * g = ui::Engine::Ref().g;
|
|
String tempString, tempString2;
|
|
|
|
tempString = String::Build("Position: L ", focusedComponent_->Position.X, ", R ", Size.X-(focusedComponent_->Position.X+focusedComponent_->Size.X), ", T: ", focusedComponent_->Position.Y, ", B: ", Size.Y-(focusedComponent_->Position.Y+focusedComponent_->Size.Y));
|
|
tempString2 = String::Build("Size: ", focusedComponent_->Size.X, ", ", focusedComponent_->Size.Y);
|
|
|
|
if (Graphics::textwidth(tempString)+xPos > WINDOWW)
|
|
xPos = WINDOWW-(Graphics::textwidth(tempString)+5);
|
|
if (Graphics::textwidth(tempString2)+xPos > WINDOWW)
|
|
xPos = WINDOWW-(Graphics::textwidth(tempString2)+5);
|
|
|
|
g->drawtext(xPos, focusedComponent_->Position.Y+Position.Y+1, tempString, 0, 0, 0, 200);
|
|
g->drawtext(xPos, focusedComponent_->Position.Y+Position.Y, tempString, 255, 255, 255, 255);
|
|
g->drawtext(xPos, focusedComponent_->Position.Y+Position.Y+13, tempString2, 0, 0, 0, 200);
|
|
g->drawtext(xPos, focusedComponent_->Position.Y+Position.Y+12, tempString2, 255, 255, 255, 255);
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
void Window::DoTick(float dt)
|
|
{
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
//on mouse hover
|
|
for (int i = Components.size() - 1; i >= 0 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled &&
|
|
ui::Engine::Ref().GetMouseX() >= Components[i]->Position.X+Position.X &&
|
|
ui::Engine::Ref().GetMouseY() >= Components[i]->Position.Y+Position.Y &&
|
|
ui::Engine::Ref().GetMouseX() < Components[i]->Position.X+Position.X + Components[i]->Size.X &&
|
|
ui::Engine::Ref().GetMouseY() < Components[i]->Position.Y+Position.Y + Components[i]->Size.Y )
|
|
{
|
|
Components[i]->OnMouseHover(ui::Engine::Ref().GetMouseX() - (Components[i]->Position.X + Position.X), ui::Engine::Ref().GetMouseY() - (Components[i]->Position.Y + Position.Y));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//tick
|
|
for (int i = 0, sz = Components.size(); i < sz && !halt; ++i)
|
|
{
|
|
Components[i]->Tick(dt);
|
|
}
|
|
|
|
halt = false;
|
|
stop = false;
|
|
|
|
OnTick(dt);
|
|
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
|
{
|
|
#ifdef DEBUG
|
|
if (key == SDLK_TAB && ctrl)
|
|
debugMode = !debugMode;
|
|
if (debugMode)
|
|
{
|
|
if (focusedComponent_!=NULL)
|
|
{
|
|
if (shift)
|
|
{
|
|
if (key == SDLK_UP)
|
|
focusedComponent_->Size.Y--;
|
|
if (key == SDLK_DOWN)
|
|
focusedComponent_->Size.Y++;
|
|
if (key == SDLK_LEFT)
|
|
focusedComponent_->Size.X--;
|
|
if (key == SDLK_RIGHT)
|
|
focusedComponent_->Size.X++;
|
|
}
|
|
if (ctrl)
|
|
{
|
|
if (key == SDLK_UP)
|
|
focusedComponent_->Size.Y++;
|
|
if (key == SDLK_DOWN)
|
|
focusedComponent_->Size.Y--;
|
|
if (key == SDLK_LEFT)
|
|
focusedComponent_->Size.X++;
|
|
if (key == SDLK_RIGHT)
|
|
focusedComponent_->Size.X--;
|
|
}
|
|
if (!shift)
|
|
{
|
|
if (key == SDLK_UP)
|
|
focusedComponent_->Position.Y--;
|
|
if (key == SDLK_DOWN)
|
|
focusedComponent_->Position.Y++;
|
|
if (key == SDLK_LEFT)
|
|
focusedComponent_->Position.X--;
|
|
if (key == SDLK_RIGHT)
|
|
focusedComponent_->Position.X++;
|
|
}
|
|
if (key == SDLK_DELETE)
|
|
{
|
|
RemoveComponent(focusedComponent_);
|
|
halt = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (shift)
|
|
{
|
|
if (key == SDLK_UP)
|
|
Size.Y--;
|
|
if (key == SDLK_DOWN)
|
|
Size.Y++;
|
|
if (key == SDLK_LEFT)
|
|
Size.X--;
|
|
if (key == SDLK_RIGHT)
|
|
Size.X++;
|
|
}
|
|
if (ctrl)
|
|
{
|
|
if (key == SDLK_UP)
|
|
Size.Y++;
|
|
if (key == SDLK_DOWN)
|
|
Size.Y--;
|
|
if (key == SDLK_LEFT)
|
|
Size.X++;
|
|
if (key == SDLK_RIGHT)
|
|
Size.X--;
|
|
}
|
|
if (!shift)
|
|
{
|
|
if (key == SDLK_UP)
|
|
Position.Y--;
|
|
if (key == SDLK_DOWN)
|
|
Position.Y++;
|
|
if( key == SDLK_LEFT)
|
|
Position.X--;
|
|
if (key == SDLK_RIGHT)
|
|
Position.X++;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
//on key press
|
|
if (focusedComponent_ != NULL)
|
|
{
|
|
if (focusedComponent_->Enabled && focusedComponent_->Visible)
|
|
focusedComponent_->OnKeyPress(key, scan, repeat, shift, ctrl, alt);
|
|
}
|
|
|
|
if (!stop)
|
|
OnKeyPress(key, scan, repeat, shift, ctrl, alt);
|
|
|
|
if (key == SDLK_ESCAPE)
|
|
OnTryExit(Escape);
|
|
|
|
if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
|
|
OnTryOkay(Enter);
|
|
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
|
{
|
|
#ifdef DEBUG
|
|
if(debugMode)
|
|
return;
|
|
#endif
|
|
//on key unpress
|
|
if (focusedComponent_ != NULL)
|
|
{
|
|
if (focusedComponent_->Enabled && focusedComponent_->Visible)
|
|
focusedComponent_->OnKeyRelease(key, scan, repeat, shift, ctrl, alt);
|
|
}
|
|
|
|
if (!stop)
|
|
OnKeyRelease(key, scan, repeat, shift, ctrl, alt);
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoTextInput(String text)
|
|
{
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
//on key unpress
|
|
if (focusedComponent_ != NULL)
|
|
{
|
|
if (focusedComponent_->Enabled && focusedComponent_->Visible)
|
|
focusedComponent_->OnTextInput(text);
|
|
}
|
|
|
|
if (!stop)
|
|
OnTextInput(text);
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoMouseDown(int x_, int y_, unsigned button)
|
|
{
|
|
//on mouse click
|
|
int x = x_ - Position.X;
|
|
int y = y_ - Position.Y;
|
|
bool clickState = false;
|
|
for (int i = Components.size() - 1; i > -1 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
{
|
|
if (x >= Components[i]->Position.X && y >= Components[i]->Position.Y && x < Components[i]->Position.X + Components[i]->Size.X && y < Components[i]->Position.Y + Components[i]->Size.Y)
|
|
{
|
|
FocusComponent(Components[i]);
|
|
#ifdef DEBUG
|
|
if (!debugMode)
|
|
#endif
|
|
Components[i]->OnMouseClick(x - Components[i]->Position.X, y - Components[i]->Position.Y, button);
|
|
clickState = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!clickState)
|
|
FocusComponent(NULL);
|
|
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
|
|
//on mouse down
|
|
for (int i = Components.size() - 1; i > -1 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
Components[i]->OnMouseDown(x, y, button);
|
|
}
|
|
|
|
if (!stop)
|
|
OnMouseDown(x_, y_, button);
|
|
|
|
if (!clickState && (x_ < Position.X || y_ < Position.Y || x_ > Position.X+Size.X || y_ > Position.Y+Size.Y))
|
|
OnTryExit(MouseOutside);
|
|
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoMouseMove(int x_, int y_, int dx, int dy)
|
|
{
|
|
//on mouse move (if true, and inside)
|
|
int x = x_ - Position.X;
|
|
int y = y_ - Position.Y;
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
for (int i = Components.size() - 1; i > -1 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
{
|
|
Point local(x - Components[i]->Position.X, y - Components[i]->Position.Y);
|
|
Point a(local.X - dx, local.Y - dy);
|
|
|
|
Components[i]->OnMouseMoved(local.X, local.Y, dx, dy);
|
|
|
|
if (local.X >= 0 &&
|
|
local.Y >= 0 &&
|
|
local.X < Components[i]->Size.X &&
|
|
local.Y < Components[i]->Size.Y && !halt)
|
|
{
|
|
Components[i]->OnMouseMovedInside(local.X, local.Y, dx, dy);
|
|
|
|
// entering?
|
|
if (!(a.X >= 0 &&
|
|
a.Y >= 0 &&
|
|
a.X < Components[i]->Size.X &&
|
|
a.Y < Components[i]->Size.Y ))
|
|
{
|
|
Components[i]->OnMouseEnter(local.X, local.Y);
|
|
}
|
|
if (Components[i]->Enabled)
|
|
hoverComponent = Components[i];
|
|
}
|
|
else if (!halt)
|
|
{
|
|
// leaving?
|
|
if (a.X >= 0 &&
|
|
a.Y >= 0 &&
|
|
a.X < Components[i]->Size.X &&
|
|
a.Y < Components[i]->Size.Y )
|
|
{
|
|
Components[i]->OnMouseLeave(local.X, local.Y);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!stop)
|
|
OnMouseMove(x_, y_, dx, dy);
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoMouseUp(int x_, int y_, unsigned button)
|
|
{
|
|
int x = x_ - Position.X;
|
|
int y = y_ - Position.Y;
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
//on mouse unclick
|
|
for (int i = Components.size() - 1; i >= 0 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
{
|
|
if (x >= Components[i]->Position.X && y >= Components[i]->Position.Y && x < Components[i]->Position.X + Components[i]->Size.X && y < Components[i]->Position.Y + Components[i]->Size.Y)
|
|
{
|
|
Components[i]->OnMouseUnclick(x - Components[i]->Position.X, y - Components[i]->Position.Y, button);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//on mouse up
|
|
for (int i = Components.size() - 1; i >= 0 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
Components[i]->OnMouseUp(x, y, button);
|
|
}
|
|
|
|
if (!stop)
|
|
OnMouseUp(x_, y_, button);
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::DoMouseWheel(int x_, int y_, int d)
|
|
{
|
|
int x = x_ - Position.X;
|
|
int y = y_ - Position.Y;
|
|
#ifdef DEBUG
|
|
if (debugMode)
|
|
return;
|
|
#endif
|
|
//on mouse wheel focused
|
|
for (int i = Components.size() - 1; i >= 0 && !halt; --i)
|
|
{
|
|
if (x >= Components[i]->Position.X && y >= Components[i]->Position.Y && x < Components[i]->Position.X + Components[i]->Size.X && y < Components[i]->Position.Y + Components[i]->Size.Y)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
Components[i]->OnMouseWheelInside(x - Components[i]->Position.X, y - Components[i]->Position.Y, d);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//on mouse wheel
|
|
for (int i = Components.size() - 1; i >= 0 && !halt; --i)
|
|
{
|
|
if (Components[i]->Enabled && Components[i]->Visible)
|
|
Components[i]->OnMouseWheel(x - Components[i]->Position.X, y - Components[i]->Position.Y, d);
|
|
}
|
|
|
|
if (!stop)
|
|
OnMouseWheel(x_, y_, d);
|
|
|
|
if (destruct)
|
|
finalise();
|
|
}
|
|
|
|
void Window::finalise()
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
void Window::SelfDestruct()
|
|
{
|
|
destruct = true;
|
|
halt = true;
|
|
stop = true;
|
|
}
|
|
|
|
void Window::Halt()
|
|
{
|
|
stop = true;
|
|
halt = true;
|
|
}
|
|
|