From a4491e9630cb175ab8f0fa8cee1c224dbf4ad0e2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 11 Oct 2018 16:52:40 +0200 Subject: [PATCH] More hacking on Widgets. --- Widgets/Makefile | 1 + Widgets/Rect.h | 8 ++++ Widgets/RootWidget.cpp | 6 ++- Widgets/TerminalWidget.cpp | 2 + Widgets/Widget.cpp | 19 +++++++++ Widgets/Widget.h | 9 +++++ Widgets/WindowManager.cpp | 79 ++++++++++++++++++++++++++++++++++++++ Widgets/WindowManager.h | 24 ++++++++++++ Widgets/test.cpp | 4 ++ 9 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 Widgets/WindowManager.cpp create mode 100644 Widgets/WindowManager.h diff --git a/Widgets/Makefile b/Widgets/Makefile index 11ed7e6b51..31295d7dae 100644 --- a/Widgets/Makefile +++ b/Widgets/Makefile @@ -19,6 +19,7 @@ VFS_OBJS = \ Label.o \ Button.o \ TerminalWidget.o \ + WindowManager.o \ test.o OBJS = $(AK_OBJS) $(VFS_OBJS) diff --git a/Widgets/Rect.h b/Widgets/Rect.h index 08e1d5860a..92ab8cb107 100644 --- a/Widgets/Rect.h +++ b/Widgets/Rect.h @@ -22,6 +22,14 @@ public: return { x() + width() / 2, y() + height() / 2 }; } + void inflate(int w, int h) + { + setX(x() - w / 2); + setWidth(width() + w); + setY(y() - h / 2); + setHeight(height() + h); + } + bool contains(int x, int y) const { return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom(); diff --git a/Widgets/RootWidget.cpp b/Widgets/RootWidget.cpp index 614ef8709e..dc3b260bad 100644 --- a/Widgets/RootWidget.cpp +++ b/Widgets/RootWidget.cpp @@ -1,5 +1,6 @@ #include "RootWidget.h" #include "Painter.h" +#include "WindowManager.h" #include RootWidget::RootWidget() @@ -12,15 +13,16 @@ RootWidget::~RootWidget() void RootWidget::onPaint(PaintEvent& event) { - printf("RootWidget::onPaint\n"); + //printf("RootWidget::onPaint\n"); Painter painter(*this); painter.fillRect(Rect(0, 0, 800, 600), Color(0x40, 0x40, 0x40)); + WindowManager::the().paintWindowFrames(); Widget::onPaint(event); } void RootWidget::onMouseMove(MouseEvent& event) { - printf("RootWidget::onMouseMove: x=%d, y=%d\n", event.x(), event.y()); + //printf("RootWidget::onMouseMove: x=%d, y=%d\n", event.x(), event.y()); Widget::onMouseMove(event); } diff --git a/Widgets/TerminalWidget.cpp b/Widgets/TerminalWidget.cpp index c6f7a2307a..0d404b3f45 100644 --- a/Widgets/TerminalWidget.cpp +++ b/Widgets/TerminalWidget.cpp @@ -11,6 +11,8 @@ TerminalWidget* g_tw; TerminalWidget::TerminalWidget(Widget* parent) : Widget(parent) { + setIsWindow(true); + g_tw = this; setRect({ 100, 300, columns() * 8, rows() * 10 }); diff --git a/Widgets/Widget.cpp b/Widgets/Widget.cpp index 932d15de17..5257172239 100644 --- a/Widgets/Widget.cpp +++ b/Widgets/Widget.cpp @@ -1,6 +1,7 @@ #include "Widget.h" #include "Event.h" #include "EventLoop.h" +#include "WindowManager.h" #include Widget::Widget(Widget* parent) @@ -21,6 +22,17 @@ 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()) { @@ -104,3 +116,10 @@ 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 77c0f82738..6392dd037f 100644 --- a/Widgets/Widget.h +++ b/Widgets/Widget.h @@ -4,6 +4,7 @@ #include "Object.h" #include "Rect.h" #include "Color.h" +#include class Widget : public Object { public: @@ -45,10 +46,18 @@ public: void setBackgroundColor(Color color) { m_backgroundColor = color; } void setForegroundColor(Color color) { m_foregroundColor = color; } + bool isWindow() const { return m_isWindow; } + void setIsWindow(bool); + + void setWindowTitle(String&&); + String windowTitle() const { return m_windowTitle; } + private: Rect m_rect; Color m_backgroundColor; Color m_foregroundColor; + String m_windowTitle; + bool m_isWindow { false }; bool m_hasPendingPaintEvent { false }; }; diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp new file mode 100644 index 0000000000..15fab7a39b --- /dev/null +++ b/Widgets/WindowManager.cpp @@ -0,0 +1,79 @@ +#include "WindowManager.h" +#include "Painter.h" +#include "Widget.h" +#include "AbstractScreen.h" + +WindowManager& WindowManager::the() +{ + static WindowManager* s_the = new WindowManager; + return *s_the; +} + +WindowManager::WindowManager() +{ +} + +WindowManager::~WindowManager() +{ +} + +void WindowManager::paintWindowFrames() +{ + for (auto* widget : m_windows) { + paintWindowFrame(*widget); + } +} + +void WindowManager::paintWindowFrame(Widget& widget) +{ + 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()); + + static const int windowFrameWidth = 2; + static const int windowTitleBarHeight = 14; + + Rect topRect { + widget.x() - windowFrameWidth, + widget.y() - windowTitleBarHeight - windowFrameWidth, + widget.width() + windowFrameWidth * 2, + windowTitleBarHeight + windowFrameWidth }; + + Rect bottomRect { + widget.x() - windowFrameWidth, + widget.y() + widget.height(), + widget.width() + windowFrameWidth * 2, + windowFrameWidth }; + + Rect leftRect { + widget.x() - windowFrameWidth, + widget.y(), + windowFrameWidth, + widget.height() + }; + + Rect rightRect { + widget.x() + widget.width(), + widget.y(), + windowFrameWidth, + widget.height() + }; + + p.fillRect(topRect, Color(0x40, 0x40, 0xc0)); + p.fillRect(bottomRect, Color(0x40, 0x40, 0xc0)); + p.fillRect(leftRect, Color(0x40, 0x40, 0xc0)); + p.fillRect(rightRect, Color(0x40, 0x40, 0xc0)); + + p.drawText(topRect, widget.windowTitle(), Painter::TextAlignment::Center, Color(255, 255, 255)); +} + +void WindowManager::addWindow(Widget& widget) +{ + m_windows.set(&widget); +} + +void WindowManager::notifyTitleChanged(Widget&) +{ + AbstractScreen::the().rootWidget()->update(); +} + diff --git a/Widgets/WindowManager.h b/Widgets/WindowManager.h new file mode 100644 index 0000000000..14405001c0 --- /dev/null +++ b/Widgets/WindowManager.h @@ -0,0 +1,24 @@ +#pragma once + +class Widget; + +#include "Object.h" +#include + +class WindowManager : public Object { +public: + static WindowManager& the(); + + void addWindow(Widget&); + void paintWindowFrames(); + + void notifyTitleChanged(Widget&); + +private: + WindowManager(); + ~WindowManager(); + + void paintWindowFrame(Widget&); + + HashTable m_windows; +}; diff --git a/Widgets/test.cpp b/Widgets/test.cpp index 60426f7268..95639ddb93 100644 --- a/Widgets/test.cpp +++ b/Widgets/test.cpp @@ -4,6 +4,7 @@ #include "Label.h" #include "Button.h" #include "TerminalWidget.h" +#include "WindowManager.h" #include int main(int c, char** v) @@ -16,6 +17,8 @@ int main(int c, char** v) RootWidget w; fb.setRootWidget(&w); + WindowManager::the(); + auto* l1 = new Label(&w); l1->setRect(Rect(100, 100, 300, 20)); l1->setText("0123456789"); @@ -37,6 +40,7 @@ int main(int c, char** v) b->setCaption("Button!"); auto* t = new TerminalWidget(&w); + t->setWindowTitle("Console"); return loop.exec(); }