
Previously, Frames could set both these properties along with a thickness to confusing effect: Most shapes of the same shadowing only differentiated at a thickness >= 2, and some not at all. This led to a lot of creative but ultimately superfluous choices in the code. Instead let's streamline our options, automate thickness, and get the right look without so much guesswork. Plain shadowing has been consolidated into a single Plain style, and 0 thickness can be had by setting style to NoFrame.
177 lines
5.4 KiB
C++
177 lines
5.4 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
* Copyright (c) 2022, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibGUI/BoxLayout.h>
|
|
#include <LibGUI/Painter.h>
|
|
#include <LibGUI/ResizeCorner.h>
|
|
#include <LibGUI/Statusbar.h>
|
|
#include <LibGUI/Window.h>
|
|
#include <LibGfx/Palette.h>
|
|
#include <LibGfx/StylePainter.h>
|
|
|
|
REGISTER_WIDGET(GUI, Statusbar)
|
|
|
|
namespace GUI {
|
|
|
|
Statusbar::Statusbar(int count)
|
|
{
|
|
set_fixed_height(18);
|
|
set_layout<HorizontalBoxLayout>(0, 2);
|
|
|
|
m_corner = add<ResizeCorner>();
|
|
set_segment_count(count);
|
|
|
|
REGISTER_DEPRECATED_STRING_PROPERTY("text", text, set_text);
|
|
REGISTER_INT_PROPERTY("segment_count", segment_count, set_segment_count);
|
|
}
|
|
|
|
NonnullRefPtr<Statusbar::Segment> Statusbar::create_segment()
|
|
{
|
|
auto widget = Segment::construct();
|
|
insert_child_before(*widget, *m_corner);
|
|
return widget;
|
|
}
|
|
|
|
void Statusbar::child_event(Core::ChildEvent& event)
|
|
{
|
|
auto& event_to_forward = event;
|
|
// To ensure that the ResizeCorner is always the last widget, and thus stays in the corner,
|
|
// we replace ChildAdded events that do not request specific placement with events that request placement before the corner
|
|
if (event.type() == Event::ChildAdded && is<Widget>(*event.child()) && !event.insertion_before_child()) {
|
|
Core::ChildEvent new_event(Event::ChildAdded, *event.child(), m_corner.ptr());
|
|
event_to_forward = new_event;
|
|
}
|
|
|
|
return Widget::child_event(event_to_forward);
|
|
}
|
|
|
|
void Statusbar::set_segment_count(size_t count)
|
|
{
|
|
if (count <= 1)
|
|
count = 1;
|
|
|
|
for (auto i = m_segments.size(); i < count; i++) {
|
|
auto segment = create_segment();
|
|
m_segments.append(move(segment));
|
|
}
|
|
}
|
|
|
|
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().is_int()) {
|
|
segment->set_restored_width(segment->max_width().as_int());
|
|
segment->set_fixed_width(segment->max_width());
|
|
}
|
|
}
|
|
|
|
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(String::from_utf8(segment->restored_text()).release_value_but_fixme_should_propagate_errors());
|
|
segment->set_frame_style(Gfx::FrameStyle::SunkenPanel);
|
|
if (segment->mode() != Segment::Mode::Proportional)
|
|
segment->set_fixed_width(segment->restored_width());
|
|
} else {
|
|
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(String::from_utf8(segment->override_text()).release_value_but_fixme_should_propagate_errors());
|
|
segment->set_frame_style(Gfx::FrameStyle::NoFrame);
|
|
if (segment->mode() != Segment::Mode::Proportional)
|
|
segment->set_fixed_width(SpecialDimension::Grow);
|
|
}
|
|
}
|
|
|
|
DeprecatedString Statusbar::text(size_t index) const
|
|
{
|
|
return m_segments[index]->text().to_deprecated_string();
|
|
}
|
|
|
|
void Statusbar::set_text(DeprecatedString text)
|
|
{
|
|
set_text(0, move(text));
|
|
}
|
|
|
|
void Statusbar::set_text(size_t index, DeprecatedString text)
|
|
{
|
|
m_segments[index]->m_restored_text = move(text);
|
|
update_segment(index);
|
|
}
|
|
|
|
void Statusbar::set_override_text(DeprecatedString override_text)
|
|
{
|
|
m_segments[0]->m_override_text = move(override_text);
|
|
update_segment(0);
|
|
}
|
|
|
|
void Statusbar::paint_event(PaintEvent& event)
|
|
{
|
|
Painter painter(*this);
|
|
painter.add_clip_rect(event.rect());
|
|
painter.fill_rect(rect(), palette().button());
|
|
}
|
|
|
|
void Statusbar::resize_event(ResizeEvent& event)
|
|
{
|
|
if (auto* window = this->window()) {
|
|
m_corner->set_visible(window->is_resizable() && !window->is_maximized());
|
|
}
|
|
|
|
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());
|
|
|
|
bool skip_vertical_lines = window()->is_maximized() && spans_entire_window_horizontally();
|
|
Gfx::StylePainter::current().paint_frame(painter, rect(), palette(), m_style, skip_vertical_lines);
|
|
|
|
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);
|
|
}
|
|
|
|
}
|