From c3b0c1ba68c79c4df1efed8b6d12b1d60187c9a6 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 22 Mar 2019 02:49:14 +0100 Subject: [PATCH] LibGUI: Add a GProgressBar widget. --- LibGUI/GProgressBar.cpp | 65 +++++++++++++++++++++++++++++++++++++++++ LibGUI/GProgressBar.h | 22 ++++++++++++++ LibGUI/Makefile | 1 + Userland/guitest2.cpp | 37 +++++++++++++++++++++-- 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 LibGUI/GProgressBar.cpp create mode 100644 LibGUI/GProgressBar.h diff --git a/LibGUI/GProgressBar.cpp b/LibGUI/GProgressBar.cpp new file mode 100644 index 0000000000..b92dc5c3bf --- /dev/null +++ b/LibGUI/GProgressBar.cpp @@ -0,0 +1,65 @@ +#include +#include + +GProgressBar::GProgressBar(GWidget* parent) + : GWidget(parent) +{ + start_timer(10); +} + +GProgressBar::~GProgressBar() +{ +} + +void GProgressBar::set_value(int value) +{ + if (m_value == value) + return; + m_value = value; + update(); +} + +void GProgressBar::set_range(int min, int max) +{ + ASSERT(min < max); + m_min = min; + m_max = max; + if (m_value > m_max) + m_value = m_max; + if (m_value < m_min) + m_value = m_min; +} + +void GProgressBar::paint_event(GPaintEvent& event) +{ + Painter painter(*this); + painter.set_clip_rect(event.rect()); + + // First we fill the entire widget with the gradient. This incurs a bit of + // overdraw but ensures a consistent look throughout the progression. + Color start_color(110, 34, 9); + Color end_color(244, 202, 158); + painter.fill_rect_with_gradient(rect(), start_color, end_color); + + float range_size = m_max - m_min; + float progress = (m_value - m_min) / range_size; + + // Then we draw the progress text over the gradient. + // We draw it twice, once offset (1, 1) for a drop shadow look. + auto progress_text = String::format("%d%%", (int)(progress * 100)); + painter.draw_text(rect().translated(1, 1), progress_text, TextAlignment::Center, Color::Black); + painter.draw_text(rect(), progress_text, TextAlignment::Center, Color::White); + + // Then we carve out a hole in the remaining part of the widget. + // We draw the text a third time, clipped and inverse, for sharp contrast. + painter.save(); + float progress_width = progress * width(); + Rect hole_rect { (int)progress_width, 0, (int)(width() - progress_width), height() }; + painter.set_clip_rect(hole_rect); + painter.fill_rect(hole_rect, Color::White); + painter.draw_text(rect().translated(0, 0), progress_text, TextAlignment::Center, Color::Black); + painter.restore(); + + // Finally, draw a frame around the widget. + painter.draw_rect(rect(), Color::Black); +} diff --git a/LibGUI/GProgressBar.h b/LibGUI/GProgressBar.h new file mode 100644 index 0000000000..6768e28871 --- /dev/null +++ b/LibGUI/GProgressBar.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +class GProgressBar : public GWidget { +public: + explicit GProgressBar(GWidget* parent); + virtual ~GProgressBar() override; + + void set_range(int min, int max); + void set_value(int); + + int value() const { return m_value; } + +protected: + virtual void paint_event(GPaintEvent&) override; + +private: + int m_min { 0 }; + int m_max { 100 }; + int m_value { 0 }; +}; diff --git a/LibGUI/Makefile b/LibGUI/Makefile index c0f6398669..5cf1c4abeb 100644 --- a/LibGUI/Makefile +++ b/LibGUI/Makefile @@ -47,6 +47,7 @@ LIBGUI_OBJS = \ GInputBox.o \ GDialog.o \ GDesktop.o \ + GProgressBar.o \ GWindow.o OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS) diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index 4e8e593b67..e96be84bd3 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -14,11 +14,14 @@ #include #include #include +#include #include +#include #include #include static GWindow* make_launcher_window(); +static GWindow* make_progress_window(); void handle_sigchld(int) { @@ -38,18 +41,21 @@ int main(int argc, char** argv) launcher_window->set_should_exit_event_loop_on_close(true); launcher_window->show(); + auto* progress_window = make_progress_window(); + progress_window->show(); + return app.exec(); } GWindow* make_launcher_window() { auto* window = new GWindow; - window->set_title("guitest2"); + window->set_title("GUI Test II"); window->set_rect({ 100, 400, 100, 230 }); auto* widget = new GWidget; + widget->set_fill_with_background_color(true); window->set_main_widget(widget); - widget->set_relative_rect({ 0, 0, 100, 230 }); auto* label = new GLabel(widget); label->set_relative_rect({ 0, 0, 100, 20 }); @@ -116,3 +122,30 @@ GWindow* make_launcher_window() return window; } + +static GWindow* make_progress_window() +{ + auto* window = new GWindow; + window->set_title("Progress bar test"); + window->set_rect({ 100, 400, 240, 80 }); + + auto* widget = new GWidget; + widget->set_fill_with_background_color(true); + window->set_main_widget(widget); + + widget->set_layout(make(Orientation::Vertical)); + + widget->layout()->set_margins({ 8, 8, 8, 8 }); + + auto* label = new GLabel("Hi /dpt/", widget); + label->set_size_policy(SizePolicy::Fill, SizePolicy::Fill); + + auto* progress_bar = new GProgressBar(widget); + progress_bar->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); + progress_bar->set_preferred_size({ 200, 20 }); + + progress_bar->set_range(0, 100); + progress_bar->set_value(25); + + return window; +}