diff options
-rw-r--r-- | LibC/time.cpp | 41 | ||||
-rw-r--r-- | LibGUI/GObject.cpp | 4 | ||||
-rw-r--r-- | LibGUI/GObject.h | 2 | ||||
-rw-r--r-- | LibGUI/GTextBox.cpp | 2 | ||||
-rw-r--r-- | LibGUI/GTextBox.h | 2 | ||||
-rw-r--r-- | SharedGraphics/Painter.h | 6 | ||||
-rw-r--r-- | Userland/guitest2.cpp | 66 |
7 files changed, 113 insertions, 10 deletions
diff --git a/LibC/time.cpp b/LibC/time.cpp index f78a73a114..6552c51118 100644 --- a/LibC/time.cpp +++ b/LibC/time.cpp @@ -27,9 +27,46 @@ char* ctime(const time_t*) return const_cast<char*>("ctime() not implemented"); } -struct tm* localtime(const time_t*) +inline bool is_leap_year(unsigned year) { - assert(false); + return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400) == 0)); +} + +static void time_to_tm(struct tm* tm, time_t t) +{ + static const unsigned seconds_per_day = 60 * 60 * 24; + static const unsigned days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned days = t / seconds_per_day; + unsigned rem = t % seconds_per_day; + tm->tm_sec = rem % 60; + rem /= 60; + tm->tm_min = rem % 60; + tm->tm_hour = rem / 60; + tm->tm_wday = (4 + days) % 7; + unsigned year; + for (year = 1970; days >= 365 + is_leap_year(year); ++year) + days -= 365 + is_leap_year(year); + tm->tm_year = year - 1900; + tm->tm_yday = days; + tm->tm_mday = 1; + if (is_leap_year(year) && days == 59) + ++tm->tm_mday; + if (is_leap_year(year) && days >= 59) + --days; + unsigned month; + for (month = 0; month < 11 && days >= days_per_month[month]; ++month) + days -= days_per_month[month]; + tm->tm_mon = month; + tm->tm_mday += days; +} + +struct tm* localtime(const time_t* t) +{ + if (!t) + return nullptr; + static struct tm tm_buf; + time_to_tm(&tm_buf, *t); + return &tm_buf; } long timezone = 0; diff --git a/LibGUI/GObject.cpp b/LibGUI/GObject.cpp index 881f220317..c980e70192 100644 --- a/LibGUI/GObject.cpp +++ b/LibGUI/GObject.cpp @@ -23,7 +23,7 @@ void GObject::event(GEvent& event) { switch (event.type()) { case GEvent::Timer: - return timerEvent(static_cast<GTimerEvent&>(event)); + return timer_event(static_cast<GTimerEvent&>(event)); case GEvent::DeferredDestroy: delete this; break; @@ -50,7 +50,7 @@ void GObject::removeChild(GObject& object) } } -void GObject::timerEvent(GTimerEvent&) +void GObject::timer_event(GTimerEvent&) { } diff --git a/LibGUI/GObject.h b/LibGUI/GObject.h index c4d2679101..d31d3c1a23 100644 --- a/LibGUI/GObject.h +++ b/LibGUI/GObject.h @@ -30,7 +30,7 @@ public: void delete_later(); private: - virtual void timerEvent(GTimerEvent&); + virtual void timer_event(GTimerEvent&); GObject* m_parent { nullptr }; diff --git a/LibGUI/GTextBox.cpp b/LibGUI/GTextBox.cpp index fc05417353..44d9f277f7 100644 --- a/LibGUI/GTextBox.cpp +++ b/LibGUI/GTextBox.cpp @@ -123,7 +123,7 @@ void GTextBox::keydown_event(GKeyEvent& event) } } -void GTextBox::timerEvent(GTimerEvent&) +void GTextBox::timer_event(GTimerEvent&) { // FIXME: Disable the timer when not focused. if (!is_focused()) diff --git a/LibGUI/GTextBox.h b/LibGUI/GTextBox.h index d34dbc406a..65ef7f0c9d 100644 --- a/LibGUI/GTextBox.h +++ b/LibGUI/GTextBox.h @@ -18,7 +18,7 @@ private: virtual void paint_event(GPaintEvent&) override; virtual void mousedown_event(GMouseEvent&) override; virtual void keydown_event(GKeyEvent&) override; - virtual void timerEvent(GTimerEvent&) override; + virtual void timer_event(GTimerEvent&) override; virtual bool accepts_focus() const override { return true; } void handle_backspace(); diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index 45e4f6f08c..f28db3ac5c 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -10,14 +10,14 @@ class CharacterBitmap; class GraphicsBitmap; class Font; -#ifdef LIBGUI +#ifndef KERNEL class GWidget; class GWindow; #endif class Painter { public: -#ifdef LIBGUI +#ifndef KERNEL explicit Painter(GWidget&); #endif explicit Painter(GraphicsBitmap&); @@ -52,7 +52,7 @@ private: Point m_translation; Rect m_clip_rect; RetainPtr<GraphicsBitmap> m_target; -#ifdef LIBGUI +#ifndef KERNEL GWindow* m_window { nullptr }; void* m_backing_store_id { nullptr }; #endif diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index a73d04545d..231a8d75d2 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -5,6 +5,7 @@ #include <stdlib.h> #include <fcntl.h> #include <assert.h> +#include <time.h> #include <Kernel/Syscall.h> #include <SharedGraphics/GraphicsBitmap.h> #include <SharedGraphics/Painter.h> @@ -16,8 +17,56 @@ #include <LibGUI/GTextBox.h> #include <LibGUI/GCheckBox.h> +class ClockWidget final : public GWidget { +public: + explicit ClockWidget(GWidget* parent = nullptr); + virtual ~ClockWidget() override { } + +private: + virtual void paint_event(GPaintEvent&) override; + virtual void timer_event(GTimerEvent&) override; + virtual void mousedown_event(GMouseEvent&) override; + + dword m_last_time { 0 }; +}; + +ClockWidget::ClockWidget(GWidget* parent) + : GWidget(parent) +{ + set_relative_rect({ 0, 0, 100, 40 }); + startTimer(250); +} + +void ClockWidget::paint_event(GPaintEvent&) +{ + auto now = time(nullptr); + auto& tm = *localtime(&now); + + char timeBuf[128]; + sprintf(timeBuf, "%02u:%02u:%02u", tm.tm_hour, tm.tm_min, tm.tm_sec); + + Painter painter(*this); + painter.fill_rect(rect(), Color::White); + painter.draw_text(rect(), timeBuf, Painter::TextAlignment::Center, Color::Black); +} + +void ClockWidget::timer_event(GTimerEvent&) +{ + auto now = time(nullptr); + if (now == m_last_time) + return; + m_last_time = now; + update(); +} + +void ClockWidget::mousedown_event(GMouseEvent&) +{ + update(); +} + static GWindow* make_font_test_window(); static GWindow* make_launcher_window(); +static GWindow* make_clock_window(); int main(int argc, char** argv) { @@ -27,6 +76,10 @@ int main(int argc, char** argv) auto* launcher_window = make_launcher_window(); launcher_window->show(); + + auto* clock_window = make_clock_window(); + clock_window->show(); + return loop.exec(); } @@ -133,3 +186,16 @@ GWindow* make_launcher_window() return window; } + +GWindow* make_clock_window() +{ + auto* window = new GWindow; + window->set_title("Clock"); + window->set_rect({ 200, 200, 100, 40 }); + + auto* clock_widget = new ClockWidget; + clock_widget->set_relative_rect({ 0, 0, 100, 40 }); + window->set_main_widget(clock_widget); + + return window; +} |