Red GL4.5 screen.
This commit is contained in:
@@ -9,12 +9,14 @@
|
||||
|
||||
#include <poly/ui/control.h>
|
||||
|
||||
#include <poly/assert.h>
|
||||
|
||||
namespace poly {
|
||||
namespace ui {
|
||||
|
||||
Control::Control(Control* parent, uint32_t flags)
|
||||
: parent_(parent),
|
||||
flags_(flags),
|
||||
Control::Control(uint32_t flags)
|
||||
: flags_(flags),
|
||||
parent_(nullptr),
|
||||
width_(0),
|
||||
height_(0),
|
||||
is_cursor_visible_(true),
|
||||
@@ -34,23 +36,39 @@ void Control::AddChild(std::unique_ptr<Control> child_control) {
|
||||
}
|
||||
|
||||
void Control::AddChild(ControlPtr control) {
|
||||
assert_null(control->parent());
|
||||
control->parent_ = this;
|
||||
auto control_ptr = control.get();
|
||||
children_.emplace_back(std::move(control));
|
||||
OnChildAdded(control_ptr);
|
||||
}
|
||||
|
||||
void Control::RemoveChild(Control* child_control) {
|
||||
Control::ControlPtr Control::RemoveChild(Control* child_control) {
|
||||
assert_true(child_control->parent() == this);
|
||||
for (auto& it = children_.begin(); it != children_.end(); ++it) {
|
||||
if (it->get() == child_control) {
|
||||
auto control_ptr = std::move(*it);
|
||||
child_control->parent_ = nullptr;
|
||||
children_.erase(it);
|
||||
OnChildRemoved(child_control);
|
||||
break;
|
||||
return control_ptr;
|
||||
}
|
||||
}
|
||||
return ControlPtr(nullptr, [](Control*) {});
|
||||
}
|
||||
|
||||
void Control::Layout() {
|
||||
auto e = UIEvent(this);
|
||||
OnLayout(e);
|
||||
for (auto& child_control : children_) {
|
||||
child_control->OnLayout(e);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::OnResize(UIEvent& e) { on_resize(e); }
|
||||
|
||||
void Control::OnLayout(UIEvent& e) { on_layout(e); }
|
||||
|
||||
void Control::OnVisible(UIEvent& e) { on_visible(e); }
|
||||
|
||||
void Control::OnHidden(UIEvent& e) { on_hidden(e); }
|
||||
|
||||
@@ -34,15 +34,17 @@ class Control {
|
||||
void AddChild(Control* child_control);
|
||||
void AddChild(std::unique_ptr<Control> child_control);
|
||||
void AddChild(ControlPtr child_control);
|
||||
void RemoveChild(Control* child_control);
|
||||
ControlPtr RemoveChild(Control* child_control);
|
||||
|
||||
int32_t width() const { return width_; }
|
||||
int32_t height() const { return height_; }
|
||||
virtual void Resize(int32_t width, int32_t height) = 0;
|
||||
virtual void Resize(int32_t left, int32_t top, int32_t right,
|
||||
int32_t bottom) = 0;
|
||||
void ResizeToFill() { ResizeToFill(0, 0, 0, 0); }
|
||||
virtual void ResizeToFill(int32_t pad_left, int32_t pad_top,
|
||||
int32_t pad_right, int32_t pad_bottom) = 0;
|
||||
void Layout();
|
||||
|
||||
// TODO(benvanik): colors/brushes/etc.
|
||||
// TODO(benvanik): fonts.
|
||||
@@ -61,6 +63,7 @@ class Control {
|
||||
|
||||
public:
|
||||
poly::Delegate<UIEvent> on_resize;
|
||||
poly::Delegate<UIEvent> on_layout;
|
||||
|
||||
poly::Delegate<UIEvent> on_visible;
|
||||
poly::Delegate<UIEvent> on_hidden;
|
||||
@@ -77,7 +80,10 @@ class Control {
|
||||
poly::Delegate<MouseEvent> on_mouse_wheel;
|
||||
|
||||
protected:
|
||||
Control(Control* parent, uint32_t flags);
|
||||
explicit Control(uint32_t flags);
|
||||
|
||||
virtual bool Create() = 0;
|
||||
virtual void Destroy() {}
|
||||
|
||||
virtual void OnCreate() {}
|
||||
virtual void OnDestroy() {}
|
||||
@@ -86,6 +92,7 @@ class Control {
|
||||
virtual void OnChildRemoved(Control* child_control) {}
|
||||
|
||||
virtual void OnResize(UIEvent& e);
|
||||
virtual void OnLayout(UIEvent& e);
|
||||
|
||||
virtual void OnVisible(UIEvent& e);
|
||||
virtual void OnHidden(UIEvent& e);
|
||||
|
||||
@@ -13,26 +13,7 @@ namespace poly {
|
||||
namespace ui {
|
||||
namespace win32 {
|
||||
|
||||
LRESULT CALLBACK
|
||||
Win32Control::WndProcThunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
Win32Control* control = 0;
|
||||
if (message == WM_NCCREATE) {
|
||||
auto create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
control = reinterpret_cast<Win32Control*>(create_struct->lpCreateParams);
|
||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)control);
|
||||
} else {
|
||||
control =
|
||||
reinterpret_cast<Win32Control*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
}
|
||||
if (control) {
|
||||
return control->WndProc(hWnd, message, wParam, lParam);
|
||||
} else {
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
Win32Control::Win32Control(Control* parent, uint32_t flags)
|
||||
: Control(parent, flags), hwnd_(nullptr) {}
|
||||
Win32Control::Win32Control(uint32_t flags) : Control(flags), hwnd_(nullptr) {}
|
||||
|
||||
Win32Control::~Win32Control() {
|
||||
if (hwnd_) {
|
||||
@@ -43,6 +24,18 @@ Win32Control::~Win32Control() {
|
||||
|
||||
void Win32Control::OnCreate() {
|
||||
Control::OnCreate();
|
||||
|
||||
// Create all children, if needed.
|
||||
for (auto& child_control : children_) {
|
||||
auto win32_control = static_cast<Win32Control*>(child_control.get());
|
||||
if (!win32_control->hwnd()) {
|
||||
win32_control->Create();
|
||||
} else {
|
||||
SetParent(win32_control->hwnd(), hwnd());
|
||||
}
|
||||
win32_control->Layout();
|
||||
}
|
||||
|
||||
if (!is_cursor_visible_) {
|
||||
ShowCursor(FALSE);
|
||||
}
|
||||
@@ -57,6 +50,35 @@ void Win32Control::OnCreate() {
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Control::OnDestroy() {
|
||||
// Destroy all children, if needed.
|
||||
for (auto& child_control : children_) {
|
||||
auto win32_control = static_cast<Win32Control*>(child_control.get());
|
||||
if (!win32_control->hwnd()) {
|
||||
win32_control->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Control::OnChildAdded(Control* child_control) {
|
||||
auto win32_control = static_cast<Win32Control*>(child_control);
|
||||
if (hwnd_) {
|
||||
if (!win32_control->hwnd()) {
|
||||
win32_control->Create();
|
||||
} else {
|
||||
SetParent(win32_control->hwnd(), hwnd());
|
||||
}
|
||||
child_control->Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Control::OnChildRemoved(Control* child_control) {
|
||||
auto win32_control = static_cast<Win32Control*>(child_control);
|
||||
if (win32_control->hwnd()) {
|
||||
SetParent(win32_control->hwnd(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Control::Resize(int32_t width, int32_t height) {
|
||||
MoveWindow(hwnd_, 0, 0, width, height, TRUE);
|
||||
}
|
||||
@@ -77,7 +99,23 @@ void Win32Control::ResizeToFill(int32_t pad_left, int32_t pad_top,
|
||||
GetClientRect(parent_control->hwnd(), &parent_rect);
|
||||
MoveWindow(hwnd_, parent_rect.left + pad_left, parent_rect.top + pad_top,
|
||||
parent_rect.right - pad_right - pad_left,
|
||||
parent_rect.right - pad_bottom - pad_top, TRUE);
|
||||
parent_rect.bottom - pad_bottom - pad_top, TRUE);
|
||||
}
|
||||
|
||||
void Win32Control::OnResize(UIEvent& e) {
|
||||
RECT client_rect;
|
||||
GetClientRect(hwnd_, &client_rect);
|
||||
int32_t width = client_rect.right - client_rect.left;
|
||||
int32_t height = client_rect.bottom - client_rect.top;
|
||||
if (width != width_ || height != height_) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
Layout();
|
||||
for (auto& child_control : children_) {
|
||||
auto win32_control = static_cast<Win32Control*>(child_control.get());
|
||||
win32_control->OnResize(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Control::set_cursor_visible(bool value) {
|
||||
@@ -129,6 +167,24 @@ void Win32Control::set_focus(bool value) {
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK Win32Control::WndProcThunk(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam) {
|
||||
Win32Control* control = nullptr;
|
||||
if (message == WM_NCCREATE) {
|
||||
auto create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
control = reinterpret_cast<Win32Control*>(create_struct->lpCreateParams);
|
||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)control);
|
||||
} else {
|
||||
control =
|
||||
reinterpret_cast<Win32Control*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
}
|
||||
if (control) {
|
||||
return control->WndProc(hWnd, message, wParam, lParam);
|
||||
} else {
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT Win32Control::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) {
|
||||
@@ -147,10 +203,8 @@ LRESULT Win32Control::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
|
||||
switch (message) {
|
||||
case WM_NCCREATE:
|
||||
hwnd_ = hWnd;
|
||||
break;
|
||||
case WM_CREATE:
|
||||
OnCreate();
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
OnDestroy();
|
||||
@@ -163,25 +217,12 @@ LRESULT Win32Control::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
case WM_SIZING:
|
||||
break;
|
||||
case WM_SIZE: {
|
||||
RECT client_rect;
|
||||
GetClientRect(hwnd_, &client_rect);
|
||||
int32_t width = client_rect.right - client_rect.left;
|
||||
int32_t height = client_rect.bottom - client_rect.top;
|
||||
if (width != width_ || height != height_) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
auto e = UIEvent(this);
|
||||
OnResize(e);
|
||||
}
|
||||
auto e = UIEvent(this);
|
||||
OnResize(e);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_PAINT:
|
||||
if (flags_ & kFlagOwnPaint) {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
break;
|
||||
case WM_ERASEBKGND:
|
||||
if (flags_ & kFlagOwnPaint) {
|
||||
|
||||
@@ -24,6 +24,9 @@ class Win32Control : public Control {
|
||||
~Win32Control() override;
|
||||
|
||||
HWND hwnd() const { return hwnd_; }
|
||||
HWND parent_hwnd() const {
|
||||
return parent_ ? static_cast<Win32Control*>(parent_)->hwnd() : nullptr;
|
||||
}
|
||||
|
||||
void Resize(int32_t width, int32_t height) override;
|
||||
void Resize(int32_t left, int32_t top, int32_t right,
|
||||
@@ -37,11 +40,15 @@ class Win32Control : public Control {
|
||||
void set_focus(bool value) override;
|
||||
|
||||
protected:
|
||||
Win32Control(Control* parent, uint32_t flags);
|
||||
|
||||
virtual bool CreateHWND() = 0;
|
||||
explicit Win32Control(uint32_t flags);
|
||||
|
||||
void OnCreate() override;
|
||||
void OnDestroy() override;
|
||||
|
||||
void OnChildAdded(Control* child_control) override;
|
||||
void OnChildRemoved(Control* child_control) override;
|
||||
|
||||
void OnResize(UIEvent& e) override;
|
||||
|
||||
static LRESULT CALLBACK
|
||||
WndProcThunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -25,16 +25,16 @@ Win32Window::Win32Window(const std::wstring& title)
|
||||
Win32Window::~Win32Window() {}
|
||||
|
||||
bool Win32Window::Initialize() {
|
||||
CreateHWND();
|
||||
Create();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32Window::CreateHWND() {
|
||||
bool Win32Window::Create() {
|
||||
HINSTANCE hInstance = GetModuleHandle(nullptr);
|
||||
|
||||
WNDCLASSEX wcex;
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_OWNDC;
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wcex.lpfnWndProc = Win32Control::WndProcThunk;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
@@ -52,7 +52,7 @@ bool Win32Window::CreateHWND() {
|
||||
|
||||
// Setup initial size.
|
||||
DWORD window_style = WS_OVERLAPPEDWINDOW;
|
||||
DWORD window_ex_style = WS_EX_APPWINDOW;
|
||||
DWORD window_ex_style = WS_EX_APPWINDOW | WS_EX_CONTROLPARENT;
|
||||
RECT rc = {0, 0, width_, height_};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
|
||||
@@ -199,7 +199,7 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
return Win32Control::WndProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
} // namespace win32
|
||||
|
||||
@@ -35,8 +35,7 @@ class Win32Window : public Window<Win32Control> {
|
||||
int32_t pad_bottom) override;
|
||||
|
||||
protected:
|
||||
bool CreateHWND() override;
|
||||
|
||||
bool Create() override;
|
||||
void OnClose() override;
|
||||
|
||||
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
|
||||
@@ -52,7 +52,7 @@ class Window : public T {
|
||||
poly::Delegate<UIEvent> on_closed;
|
||||
|
||||
protected:
|
||||
Window(const std::wstring& title) : T(nullptr, 0), title_(title) {}
|
||||
Window(const std::wstring& title) : T(0), title_(title) {}
|
||||
|
||||
void OnShow() {
|
||||
if (is_visible_) {
|
||||
|
||||
Reference in New Issue
Block a user