This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/gui/interface/Window.cpp
jacob1 e5230b5b9f upgrade to SDL 2
Still currently in process, there are some issues:
Windows version doesn't work, mac version might not work, opengl might not work
Icon doesn't work (on Linux at least)
Lua will need some changes, there are some sdl 1.2 hacks in there
When entering fullscreen, the window loses focus
When holding down mouse out of bounds, mouse move events stop being sent
When letting go of mouse out of bounds, mouseup event doesn't take into account double scale mode
Clicking on startup without moving mouse will draw at 0,0 for a frame
Renderer probably won't compile because USE_SDL doesn't entirely work

... and maybe others

Some nice things were done though:
no more blit2, sdl can do the scaling itself
3d effect removed, no reason to support this joke any longer
No need to support copy/paste ourselves, sdl does it now
text handling done much better now, separate events for key presses and text input
when a new window is shown, all events ignored until next tick (ignore textinput event if window shown from key press event like console)
2018-05-25 21:19:44 -04:00

621 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
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;
}