diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-30 22:10:22 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-30 23:00:35 +0200 |
commit | e263dc8427aff08307faa02e1278d13c4901e810 (patch) | |
tree | e96dfc213309b6117d6ae1ed7dbd3f03f054425c | |
parent | 1d6ec51beece130ed8b3c8787b45e83bfe35dbf9 (diff) | |
download | serenity-e263dc8427aff08307faa02e1278d13c4901e810.zip |
Taskbar: Show window progress as a progress bar behind the window title
If a window in the taskbar has progress, we'll now draw that progress
in the form of a progress bar behind the window title on the taskbar
button for the window.
-rw-r--r-- | Services/Taskbar/TaskbarButton.cpp | 94 | ||||
-rw-r--r-- | Services/Taskbar/TaskbarButton.h | 1 | ||||
-rw-r--r-- | Services/Taskbar/TaskbarWindow.cpp | 1 | ||||
-rw-r--r-- | Services/Taskbar/WindowList.h | 11 |
4 files changed, 107 insertions, 0 deletions
diff --git a/Services/Taskbar/TaskbarButton.cpp b/Services/Taskbar/TaskbarButton.cpp index 68e0441211..166f709666 100644 --- a/Services/Taskbar/TaskbarButton.cpp +++ b/Services/Taskbar/TaskbarButton.cpp @@ -25,8 +25,13 @@ */ #include "TaskbarButton.h" +#include "WindowList.h" #include <LibGUI/Action.h> +#include <LibGUI/Painter.h> #include <LibGUI/WindowServerConnection.h> +#include <LibGfx/Font.h> +#include <LibGfx/Palette.h> +#include <LibGfx/StylePainter.h> TaskbarButton::TaskbarButton(const WindowIdentifier& identifier) : m_identifier(identifier) @@ -51,3 +56,92 @@ void TaskbarButton::resize_event(GUI::ResizeEvent& event) screen_relative_rect())); return GUI::Button::resize_event(event); } + +static void paint_custom_progress_bar(GUI::Painter& painter, const Gfx::Rect& rect, const Gfx::Rect& text_rect, const Palette& palette, int min, int max, int value, const StringView& text, const Gfx::Font& font, Gfx::TextAlignment text_alignment) +{ + float range_size = max - min; + float progress = (value - min) / range_size; + float progress_width = progress * rect.width(); + + Gfx::Rect progress_rect { rect.x(), rect.y(), (int)progress_width, rect.height() }; + + { + Gfx::PainterStateSaver saver(painter); + painter.add_clip_rect(progress_rect); + + Color start_color = palette.active_window_border1(); + Color end_color = palette.active_window_border2(); + painter.fill_rect_with_gradient(rect, start_color, end_color); + + if (!text.is_null()) { + painter.draw_text(text_rect.translated(1, 1), text, font, text_alignment, palette.base_text(), Gfx::TextElision::Right); + painter.draw_text(text_rect, text, font, text_alignment, palette.base_text().inverted(), Gfx::TextElision::Right); + } + } + + Gfx::Rect hole_rect { (int)progress_width, 0, (int)(rect.width() - progress_width), rect.height() }; + hole_rect.move_by(rect.location()); + hole_rect.set_right_without_resize(rect.right()); + Gfx::PainterStateSaver saver(painter); + painter.add_clip_rect(hole_rect); + if (!text.is_null()) + painter.draw_text(text_rect, text, font, text_alignment, palette.base_text(), Gfx::TextElision::Right); +} + +void TaskbarButton::paint_event(GUI::PaintEvent& event) +{ + ASSERT(icon()); + auto& icon = *this->icon(); + auto& font = is_checked() ? Gfx::Font::default_bold_font() : this->font(); + auto& window = WindowList::the().ensure_window(m_identifier); + + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + + Gfx::StylePainter::paint_button(painter, rect(), palette(), button_style(), is_being_pressed(), is_hovered(), is_checked(), is_enabled()); + + if (text().is_empty()) + return; + + bool has_progress = window.progress() >= 0 && window.progress() <= 100; + + auto content_rect = rect().shrunken(8, 2); + auto icon_location = content_rect.center().translated(-(icon.width() / 2), -(icon.height() / 2)); + if (!text().is_empty()) + icon_location.set_x(content_rect.x()); + + if (!text().is_empty()) { + content_rect.move_by(icon.width() + 4, 0); + content_rect.set_width(content_rect.width() - icon.width() - 4); + } + + Gfx::Rect text_rect { 0, 0, font.width(text()), font.glyph_height() }; + if (text_rect.width() > content_rect.width()) + text_rect.set_width(content_rect.width()); + text_rect.align_within(content_rect, text_alignment()); + + if (is_being_pressed() || is_checked()) { + text_rect.move_by(1, 1); + icon_location.move_by(1, 1); + } + + if (has_progress) { + auto adjusted_rect = rect().shrunken(4, 4); + if (is_being_pressed() || is_checked()) { + adjusted_rect.set_height(adjusted_rect.height() + 1); + } + paint_custom_progress_bar(painter, adjusted_rect, text_rect, palette(), 0, 100, window.progress(), text(), font, text_alignment()); + } + + if (is_enabled()) { + if (is_hovered()) + painter.blit_brightened(icon_location, icon, icon.rect()); + else + painter.blit(icon_location, icon, icon.rect()); + } else { + painter.blit_dimmed(icon_location, icon, icon.rect()); + } + + if (!has_progress) + paint_text(painter, text_rect, font, text_alignment()); +} diff --git a/Services/Taskbar/TaskbarButton.h b/Services/Taskbar/TaskbarButton.h index d8852cfcc1..6a5583b25a 100644 --- a/Services/Taskbar/TaskbarButton.h +++ b/Services/Taskbar/TaskbarButton.h @@ -39,6 +39,7 @@ private: virtual void context_menu_event(GUI::ContextMenuEvent&) override; virtual void resize_event(GUI::ResizeEvent&) override; + virtual void paint_event(GUI::PaintEvent&) override; WindowIdentifier m_identifier; }; diff --git a/Services/Taskbar/TaskbarWindow.cpp b/Services/Taskbar/TaskbarWindow.cpp index d287583cd7..8e33fa0e4f 100644 --- a/Services/Taskbar/TaskbarWindow.cpp +++ b/Services/Taskbar/TaskbarWindow.cpp @@ -221,6 +221,7 @@ void TaskbarWindow::wm_event(GUI::WMEvent& event) window.set_rect(changed_event.rect()); window.set_active(changed_event.is_active()); window.set_minimized(changed_event.is_minimized()); + window.set_progress(changed_event.progress()); if (window.is_minimized()) { window.button()->set_foreground_color(Color::DarkGray); window.button()->set_text(String::format("[%s]", changed_event.title().characters())); diff --git a/Services/Taskbar/WindowList.h b/Services/Taskbar/WindowList.h index 90d842c3f4..3e84f1603d 100644 --- a/Services/Taskbar/WindowList.h +++ b/Services/Taskbar/WindowList.h @@ -62,6 +62,16 @@ public: void set_minimized(bool minimized) { m_minimized = minimized; } bool is_minimized() const { return m_minimized; } + void set_progress(int progress) + { + if (m_progress == progress) + return; + m_progress = progress; + m_button->update(); + } + + int progress() const { return m_progress; } + const Gfx::Bitmap* icon() const { return m_icon.ptr(); } private: @@ -72,6 +82,7 @@ private: RefPtr<Gfx::Bitmap> m_icon; bool m_active { false }; bool m_minimized { false }; + int m_progress { -1 }; }; class WindowList { |