Procházet zdrojové kódy

Add a simple clock window to guitest2.

This is driven by mousedown events right now, since there are no timers.
Andreas Kling před 6 roky
rodič
revize
e04ba0a83c

+ 39 - 2
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;

+ 2 - 2
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&)
 {
 }
 

+ 1 - 1
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 };
 

+ 1 - 1
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())

+ 1 - 1
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();

+ 3 - 3
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

+ 66 - 0
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;
+}