diff --git a/Widgets/Makefile b/Widgets/Makefile index aa59e78b3d..f11a3980df 100644 --- a/Widgets/Makefile +++ b/Widgets/Makefile @@ -21,6 +21,7 @@ VFS_OBJS = \ TerminalWidget.o \ WindowManager.o \ Font.o \ + Window.o \ test.o OBJS = $(AK_OBJS) $(VFS_OBJS) diff --git a/Widgets/Object.h b/Widgets/Object.h index bee2d06e56..3ecd19db5b 100644 --- a/Widgets/Object.h +++ b/Widgets/Object.h @@ -15,6 +15,9 @@ public: Vector& children() { return m_children; } + Object* parent() { return m_parent; } + const Object* parent() const { return m_parent; } + private: void addChild(Object&); void removeChild(Object&); diff --git a/Widgets/Point.h b/Widgets/Point.h index 529648c504..0230d83c20 100644 --- a/Widgets/Point.h +++ b/Widgets/Point.h @@ -17,6 +17,12 @@ public: m_y += dy; } + bool operator==(const Point& other) const + { + return m_x == other.m_x + && m_y == other.m_y; + } + private: int m_x { 0 }; int m_y { 0 }; diff --git a/Widgets/Rect.h b/Widgets/Rect.h index 92ab8cb107..339db76cd4 100644 --- a/Widgets/Rect.h +++ b/Widgets/Rect.h @@ -57,6 +57,13 @@ public: Point location() const { return m_location; } + bool operator==(const Rect& other) const + { + return m_location == other.m_location + && m_width == other.m_width + && m_height == other.m_height; + } + private: Point m_location; int m_width { 0 }; diff --git a/Widgets/TerminalWidget.cpp b/Widgets/TerminalWidget.cpp index c96d5fc7a2..f3be6415b0 100644 --- a/Widgets/TerminalWidget.cpp +++ b/Widgets/TerminalWidget.cpp @@ -12,8 +12,6 @@ TerminalWidget* g_tw; TerminalWidget::TerminalWidget(Widget* parent) : Widget(parent) { - setIsWindow(true); - g_tw = this; auto& font = Font::defaultFont(); diff --git a/Widgets/Widget.cpp b/Widgets/Widget.cpp index 5257172239..30de0f5d82 100644 --- a/Widgets/Widget.cpp +++ b/Widgets/Widget.cpp @@ -22,17 +22,6 @@ void Widget::setRect(const Rect& rect) update(); } -void Widget::setIsWindow(bool value) -{ - if (m_isWindow == value) - return; - m_isWindow = value; - if (m_isWindow) { - WindowManager::the().addWindow(*this); - } - update(); -} - void Widget::event(Event& event) { switch (event.type()) { @@ -116,10 +105,3 @@ Widget::HitTestResult Widget::hitTest(int x, int y) return { this, x, y }; } -void Widget::setWindowTitle(String&& title) -{ - if (title == m_windowTitle) - return; - m_windowTitle = std::move(title); - WindowManager::the().notifyTitleChanged(*this); -} diff --git a/Widgets/Widget.h b/Widgets/Widget.h index 6392dd037f..d7a698b3f9 100644 --- a/Widgets/Widget.h +++ b/Widgets/Widget.h @@ -6,6 +6,8 @@ #include "Color.h" #include +class Window; + class Widget : public Object { public: explicit Widget(Widget* parent = nullptr); @@ -46,18 +48,29 @@ public: void setBackgroundColor(Color color) { m_backgroundColor = color; } void setForegroundColor(Color color) { m_foregroundColor = color; } - bool isWindow() const { return m_isWindow; } - void setIsWindow(bool); + Window* window() + { + if (auto* pw = parentWidget()) + return pw->window(); + return m_window; + } - void setWindowTitle(String&&); - String windowTitle() const { return m_windowTitle; } + const Window* window() const + { + if (auto* pw = parentWidget()) + return pw->window(); + return m_window; + } + + Widget* parentWidget() { return static_cast(parent()); } + const Widget* parentWidget() const { return static_cast(parent()); } private: + Window* m_window { nullptr }; + Rect m_rect; Color m_backgroundColor; Color m_foregroundColor; - String m_windowTitle; - bool m_isWindow { false }; bool m_hasPendingPaintEvent { false }; }; diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp new file mode 100644 index 0000000000..aba80e3715 --- /dev/null +++ b/Widgets/Window.cpp @@ -0,0 +1,39 @@ +#include "Window.h" +#include "WindowManager.h" + +Window::Window(Object* parent) + : Object(parent) +{ + WindowManager::the().addWindow(*this); +} + +Window::~Window() +{ +} + +void Window::setMainWidget(Widget* widget) +{ + if (m_mainWidget == widget) + return; + + m_mainWidget = widget; +} + +void Window::setTitle(String&& title) +{ + if (m_title == title) + return; + + m_title = std::move(title); + WindowManager::the().notifyTitleChanged(*this); +} + + +void Window::setRect(const Rect& rect) +{ + if (m_rect == rect) + return; + auto oldRect = m_rect; + m_rect = rect; + WindowManager::the().notifyRectChanged(*this, oldRect, m_rect); +} diff --git a/Widgets/Window.h b/Widgets/Window.h new file mode 100644 index 0000000000..1d33d55505 --- /dev/null +++ b/Widgets/Window.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include "Object.h" +#include "Rect.h" + +class Widget; + +class Window : public Object { +public: + explicit Window(Object* parent = nullptr); + virtual ~Window() override; + + String title() const { return m_title; } + void setTitle(String&&); + + int x() const { return m_rect.x(); } + int y() const { return m_rect.y(); } + int width() const { return m_rect.width(); } + int height() const { return m_rect.height(); } + + const Rect& rect() const { return m_rect; } + void setRect(const Rect&); + + Widget* mainWidget() { return m_mainWidget; } + const Widget* mainWidget() const { return m_mainWidget; } + + void setMainWidget(Widget*); + +private: + String m_title; + Rect m_rect; + Widget* m_mainWidget { nullptr }; +}; + diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp index 467c764ce2..1a21b194fb 100644 --- a/Widgets/WindowManager.cpp +++ b/Widgets/WindowManager.cpp @@ -1,6 +1,7 @@ #include "WindowManager.h" #include "Painter.h" #include "Widget.h" +#include "Window.h" #include "AbstractScreen.h" WindowManager& WindowManager::the() @@ -19,44 +20,43 @@ WindowManager::~WindowManager() void WindowManager::paintWindowFrames() { - for (auto* widget : m_windows) { - paintWindowFrame(*widget); - } + for (auto* window : m_windows) + paintWindowFrame(*window); } -void WindowManager::paintWindowFrame(Widget& widget) +void WindowManager::paintWindowFrame(Window& window) { Painter p(*AbstractScreen::the().rootWidget()); - printf("WM: paintWindowFrame %s{%p}, rect: %d,%d %dx%d\n", widget.className(), &widget, widget.rect().x(), widget.rect().y(), widget.rect().width(), widget.rect().height()); + printf("WM: paintWindowFrame {%p}, rect: %d,%d %dx%d\n", &window, window.rect().x(), window.rect().y(), window.rect().width(), window.rect().height()); static const int windowFrameWidth = 2; static const int windowTitleBarHeight = 16; Rect topRect { - widget.x() - windowFrameWidth, - widget.y() - windowTitleBarHeight - windowFrameWidth, - widget.width() + windowFrameWidth * 2, + window.x() - windowFrameWidth, + window.y() - windowTitleBarHeight - windowFrameWidth, + window.width() + windowFrameWidth * 2, windowTitleBarHeight + windowFrameWidth }; Rect bottomRect { - widget.x() - windowFrameWidth, - widget.y() + widget.height(), - widget.width() + windowFrameWidth * 2, + window.x() - windowFrameWidth, + window.y() + window.height(), + window.width() + windowFrameWidth * 2, windowFrameWidth }; Rect leftRect { - widget.x() - windowFrameWidth, - widget.y(), + window.x() - windowFrameWidth, + window.y(), windowFrameWidth, - widget.height() + window.height() }; Rect rightRect { - widget.x() + widget.width(), - widget.y(), + window.x() + window.width(), + window.y(), windowFrameWidth, - widget.height() + window.height() }; static const Color windowBorderColor(0x00, 0x00, 0x80); @@ -66,7 +66,7 @@ void WindowManager::paintWindowFrame(Widget& widget) topRect.x() - 1, topRect.y() - 1, topRect.width() + 2, - windowFrameWidth + windowTitleBarHeight + widget.height() + 4 + windowFrameWidth + windowTitleBarHeight + window.rect().height() + 4 }; p.drawRect(borderRect, Color(255, 255, 255)); borderRect.inflate(2, 2); @@ -77,16 +77,29 @@ void WindowManager::paintWindowFrame(Widget& widget) p.fillRect(leftRect, windowBorderColor); p.fillRect(rightRect, windowBorderColor); - p.drawText(topRect, widget.windowTitle(), Painter::TextAlignment::Center, windowTitleColor); + p.drawText(topRect, window.title(), Painter::TextAlignment::Center, windowTitleColor); } -void WindowManager::addWindow(Widget& widget) +void WindowManager::addWindow(Window& window) { - m_windows.set(&widget); + m_windows.set(&window); } -void WindowManager::notifyTitleChanged(Widget&) +void WindowManager::notifyTitleChanged(Window& window) { - AbstractScreen::the().rootWidget()->update(); + printf("[WM] ]Window{%p} title set to '%s'\n", &window, window.title().characters()); } +void WindowManager::notifyRectChanged(Window& window, const Rect& oldRect, const Rect& newRect) +{ + printf("[WM] Window %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", + &window, + oldRect.x(), + oldRect.y(), + oldRect.width(), + oldRect.height(), + newRect.x(), + newRect.y(), + newRect.width(), + newRect.height()); +} diff --git a/Widgets/WindowManager.h b/Widgets/WindowManager.h index 14405001c0..05a8798783 100644 --- a/Widgets/WindowManager.h +++ b/Widgets/WindowManager.h @@ -1,24 +1,26 @@ #pragma once -class Widget; +class Window; #include "Object.h" +#include "Rect.h" #include class WindowManager : public Object { public: static WindowManager& the(); - void addWindow(Widget&); + void addWindow(Window&); void paintWindowFrames(); - void notifyTitleChanged(Widget&); + void notifyTitleChanged(Window&); + void notifyRectChanged(Window&, const Rect& oldRect, const Rect& newRect); private: WindowManager(); ~WindowManager(); - void paintWindowFrame(Widget&); + void paintWindowFrame(Window&); - HashTable m_windows; + HashTable m_windows; }; diff --git a/Widgets/test.cpp b/Widgets/test.cpp index 95639ddb93..9cd7b8580c 100644 --- a/Widgets/test.cpp +++ b/Widgets/test.cpp @@ -5,6 +5,7 @@ #include "Button.h" #include "TerminalWidget.h" #include "WindowManager.h" +#include "Window.h" #include int main(int c, char** v) @@ -39,8 +40,12 @@ int main(int c, char** v) b->setRect(Rect(10, 10, 100, 30)); b->setCaption("Button!"); + auto* win = new Window; + win->setTitle("Console"); + win->setRect({100, 300, 644, 254}); + auto* t = new TerminalWidget(&w); - t->setWindowTitle("Console"); + win->setMainWidget(t); return loop.exec(); }