diff options
author | thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> | 2022-02-22 07:20:05 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-24 19:09:41 +0100 |
commit | 3aa95dd4d5be91898d912a39c97a432b05c6f401 (patch) | |
tree | d80c708e1a13cee959ea14ca49567790de4c94a6 /Userland | |
parent | e113e3ccaa7066b1f1ff9b18e3df05c21fdbc62e (diff) | |
download | serenity-3aa95dd4d5be91898d912a39c97a432b05c6f401.zip |
LibGUI+Apps: Convert Statusbar Labels to Segments
Segments inherit from Button and let us add clickable widgets
to status bars. This patch also adds proportional, fixed and
autosized modes for segments and lets the status bar consume
all non-clickable segments for override text.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/HexEditor/GoToOffsetDialog.gml | 2 | ||||
-rw-r--r-- | Userland/Applications/HexEditor/HexEditorWindow.gml | 2 | ||||
-rw-r--r-- | Userland/Applications/TextEditor/TextEditorWindow.gml | 2 | ||||
-rw-r--r-- | Userland/Games/Solitaire/Solitaire.gml | 2 | ||||
-rw-r--r-- | Userland/Games/Spider/Spider.gml | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/Statusbar.cpp | 145 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/Statusbar.h | 66 |
7 files changed, 150 insertions, 71 deletions
diff --git a/Userland/Applications/HexEditor/GoToOffsetDialog.gml b/Userland/Applications/HexEditor/GoToOffsetDialog.gml index cfd7d9495f..9504757f94 100644 --- a/Userland/Applications/HexEditor/GoToOffsetDialog.gml +++ b/Userland/Applications/HexEditor/GoToOffsetDialog.gml @@ -57,6 +57,6 @@ @GUI::Statusbar { name: "statusbar" - label_count: 2 + segment_count: 2 } } diff --git a/Userland/Applications/HexEditor/HexEditorWindow.gml b/Userland/Applications/HexEditor/HexEditorWindow.gml index 4a7d4e0935..10a271af1b 100644 --- a/Userland/Applications/HexEditor/HexEditorWindow.gml +++ b/Userland/Applications/HexEditor/HexEditorWindow.gml @@ -31,6 +31,6 @@ @GUI::Statusbar { name: "statusbar" - label_count: 5 + segment_count: 5 } } diff --git a/Userland/Applications/TextEditor/TextEditorWindow.gml b/Userland/Applications/TextEditor/TextEditorWindow.gml index 3f567a9a47..b8556df9a8 100644 --- a/Userland/Applications/TextEditor/TextEditorWindow.gml +++ b/Userland/Applications/TextEditor/TextEditorWindow.gml @@ -106,6 +106,6 @@ @GUI::Statusbar { name: "statusbar" - label_count: 2 + segment_count: 3 } } diff --git a/Userland/Games/Solitaire/Solitaire.gml b/Userland/Games/Solitaire/Solitaire.gml index 7dc3180ede..c2089f680a 100644 --- a/Userland/Games/Solitaire/Solitaire.gml +++ b/Userland/Games/Solitaire/Solitaire.gml @@ -10,6 +10,6 @@ @GUI::Statusbar { name: "statusbar" - label_count: 3 + segment_count: 3 } } diff --git a/Userland/Games/Spider/Spider.gml b/Userland/Games/Spider/Spider.gml index 83ad529034..1ed45a5299 100644 --- a/Userland/Games/Spider/Spider.gml +++ b/Userland/Games/Spider/Spider.gml @@ -10,6 +10,6 @@ @GUI::Statusbar { name: "statusbar" - label_count: 3 + segment_count: 3 } } diff --git a/Userland/Libraries/LibGUI/Statusbar.cpp b/Userland/Libraries/LibGUI/Statusbar.cpp index cc66795e81..abce4af03c 100644 --- a/Userland/Libraries/LibGUI/Statusbar.cpp +++ b/Userland/Libraries/LibGUI/Statusbar.cpp @@ -5,7 +5,6 @@ */ #include <LibGUI/BoxLayout.h> -#include <LibGUI/Label.h> #include <LibGUI/Painter.h> #include <LibGUI/ResizeCorner.h> #include <LibGUI/Statusbar.h> @@ -17,7 +16,7 @@ REGISTER_WIDGET(GUI, Statusbar) namespace GUI { -Statusbar::Statusbar(int label_count) +Statusbar::Statusbar(int count) { set_fixed_height(18); set_layout<HorizontalBoxLayout>(); @@ -25,87 +24,93 @@ Statusbar::Statusbar(int label_count) layout()->set_spacing(2); m_corner = add<ResizeCorner>(); - set_label_count(label_count); + set_segment_count(count); REGISTER_STRING_PROPERTY("text", text, set_text); - REGISTER_INT_PROPERTY("label_count", label_count, set_label_count); + REGISTER_INT_PROPERTY("segment_count", segment_count, set_segment_count); } Statusbar::~Statusbar() { } -NonnullRefPtr<Label> Statusbar::create_label() +NonnullRefPtr<Statusbar::Segment> Statusbar::create_segment() { - auto label = Label::construct(); - insert_child_before(*label, *m_corner); - label->set_frame_shadow(Gfx::FrameShadow::Sunken); - label->set_frame_shape(Gfx::FrameShape::Panel); - label->set_frame_thickness(1); - label->set_text_alignment(Gfx::TextAlignment::CenterLeft); - label->set_text_wrapping(Gfx::TextWrapping::DontWrap); - return label; + auto widget = Segment::construct(); + insert_child_before(*widget, *m_corner); + return widget; } -void Statusbar::set_text(String text) -{ - set_text(0, move(text)); -} - -String Statusbar::text() const +void Statusbar::set_segment_count(size_t count) { - return text(0); -} - -void Statusbar::set_text(size_t index, String text) -{ - m_segments.at(index).text = move(text); - update_label(index); -} + if (count <= 1) + count = 1; -void Statusbar::set_label_count(size_t label_count) -{ - if (label_count <= 1) - label_count = 1; - - for (auto i = m_segments.size(); i < label_count; i++) { - m_segments.append(Segment { - .label = create_label(), - .text = {}, - .override_text = {}, - }); + for (auto i = m_segments.size(); i < count; i++) { + auto segment = create_segment(); + m_segments.append(move(segment)); } } -void Statusbar::update_label(size_t index) +void Statusbar::update_segment(size_t index) { auto& segment = m_segments.at(index); + if (segment.mode() == Segment::Mode::Auto) { + if (segment.restored_text().is_empty()) + segment.set_visible(false); + else { + constexpr auto horizontal_padding { 10 }; + auto width = font().width(segment.restored_text()) + horizontal_padding; + segment.set_restored_width(width); + segment.set_fixed_width(width); + } + } else if (segment.mode() == Segment::Mode::Fixed) { + if (segment.max_width() != -1) + segment.set_restored_width(segment.max_width()); + segment.set_fixed_width(segment.max_width()); + } - if (segment.override_text.is_null()) { - segment.label->set_frame_shadow(Gfx::FrameShadow::Sunken); - segment.label->set_frame_shape(Gfx::FrameShape::Panel); - segment.label->set_text(segment.text); + if (segment.override_text().is_null()) { + for (size_t i = 1; i < m_segments.size(); i++) { + if (!text(i).is_empty()) + m_segments[i].set_visible(true); + } + segment.set_text(segment.restored_text()); + segment.set_frame_shape(Gfx::FrameShape::Panel); + if (segment.mode() != Segment::Mode::Proportional) + segment.set_fixed_width(segment.restored_width()); } else { - segment.label->set_frame_shadow(Gfx::FrameShadow::Plain); - segment.label->set_frame_shape(Gfx::FrameShape::NoFrame); - segment.label->set_text(segment.override_text); + for (size_t i = 1; i < m_segments.size(); i++) { + if (!m_segments[i].is_clickable()) + m_segments[i].set_visible(false); + } + segment.set_text(segment.override_text()); + segment.set_frame_shape(Gfx::FrameShape::NoFrame); + if (segment.mode() != Segment::Mode::Proportional) + segment.set_fixed_width(-1); } } String Statusbar::text(size_t index) const { - return m_segments.at(index).label->text(); + return m_segments.at(index).text(); } -void Statusbar::set_override_text(String override_text) +void Statusbar::set_text(String text) +{ + set_text(0, move(text)); +} + +void Statusbar::set_text(size_t index, String text) { - set_override_text(0, move(override_text)); + m_segments.at(index).m_restored_text = move(text); + update_segment(index); } -void Statusbar::set_override_text(size_t index, String override_text) +void Statusbar::set_override_text(String override_text) { - m_segments.at(index).override_text = move(override_text); - update_label(index); + m_segments.at(0).m_override_text = move(override_text); + update_segment(0); } void Statusbar::paint_event(PaintEvent& event) @@ -123,4 +128,40 @@ void Statusbar::resize_event(ResizeEvent& event) Widget::resize_event(event); } + +Statusbar::Segment::Segment() +{ + set_fixed_height(18); + set_focus_policy(GUI::FocusPolicy::NoFocus); + set_button_style(Gfx::ButtonStyle::Tray); + set_text_alignment(Gfx::TextAlignment::CenterLeft); +} + +void Statusbar::Segment::paint_event(PaintEvent& event) +{ + Painter painter(*this); + painter.add_clip_rect(event.rect()); + + Gfx::StylePainter::current().paint_frame(painter, rect(), palette(), m_shape, Gfx::FrameShadow::Sunken, m_thickness, spans_entire_window_horizontally()); + + if (is_clickable()) + Button::paint_event(event); + else if (!text().is_empty()) + painter.draw_text(rect().shrunken(font().max_glyph_width(), 0), text(), text_alignment(), palette().color(foreground_role()), Gfx::TextElision::Right, Gfx::TextWrapping::DontWrap); +} + +void Statusbar::Segment::mousedown_event(MouseEvent& event) +{ + if (!is_clickable()) + return; + Button::mousedown_event(event); +} + +void Statusbar::Segment::mouseup_event(MouseEvent& event) +{ + if (!is_clickable()) + return; + Button::mouseup_event(event); +} + } diff --git a/Userland/Libraries/LibGUI/Statusbar.h b/Userland/Libraries/LibGUI/Statusbar.h index 0f6e5ad5d2..818eb04037 100644 --- a/Userland/Libraries/LibGUI/Statusbar.h +++ b/Userland/Libraries/LibGUI/Statusbar.h @@ -6,7 +6,10 @@ #pragma once +#include <LibGUI/Button.h> +#include <LibGUI/Painter.h> #include <LibGUI/Widget.h> +#include <LibGfx/Palette.h> namespace GUI { @@ -15,29 +18,64 @@ class Statusbar : public Widget { public: virtual ~Statusbar() override; - String text() const; - String text(size_t index) const; + String text(size_t index = 0) const; void set_text(String); void set_text(size_t index, String); void set_override_text(String); - void set_override_text(size_t index, String); + + class Segment final : public Button { + C_OBJECT(Segment) + friend class Statusbar; + + public: + enum class Mode { + Proportional, + Fixed, + Auto, + }; + + void set_clickable(bool b) { m_clickable = b; } + bool is_clickable() { return m_clickable; } + void set_mode(Mode mode) { m_mode = mode; } + Mode mode() const { return m_mode; } + + protected: + virtual void paint_event(PaintEvent& event) override; + virtual void mousedown_event(MouseEvent& event) override; + virtual void mouseup_event(MouseEvent& event) override; + + private: + Segment(); + + void set_frame_shape(Gfx::FrameShape shape) { m_shape = shape; } + void set_restored_width(int width) { m_restored_width = width; } + int restored_width() const { return m_restored_width; } + String const& override_text() const { return m_override_text; } + String const& restored_text() const { return m_restored_text; } + + String m_override_text; + String m_restored_text; + bool m_clickable { false }; + int m_restored_width { 0 }; + int m_thickness { 1 }; + Mode m_mode { Mode::Proportional }; + Gfx::FrameShape m_shape { Gfx::FrameShape::Panel }; + }; + + Segment& segment(size_t index) { return m_segments.at(index); } protected: - explicit Statusbar(int label_count = 1); + explicit Statusbar(int segment_count = 1); virtual void paint_event(PaintEvent&) override; virtual void resize_event(ResizeEvent&) override; private: - size_t label_count() const { return m_segments.size(); } - void set_label_count(size_t label_count); - NonnullRefPtr<Label> create_label(); - struct Segment { - NonnullRefPtr<GUI::Label> label; - String text; - String override_text; - }; - void update_label(size_t); - Vector<Segment> m_segments; + void set_segment_count(size_t); + size_t segment_count() const { return m_segments.size(); } + void update_segment(size_t); + NonnullRefPtr<Segment> create_segment(); + + NonnullRefPtrVector<Segment> m_segments; RefPtr<ResizeCorner> m_corner; }; |