mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:28:10 +00:00
LibGUI: Introduce widget content margins + improve splitters
A GUI::Widget can now set an optional content margin (4x0 by default.) Pixels in the content margin will be ignored for hit testing purposes. Use this to allow frame-like widgets (like GUI::Frame!) to ignore any mouse events in the frame area, and instead let those go to parent. This allows GUI::Splitter to react "sooner" to mouse events that were previously swallowed by the child widgets instead of ending up in the splitter. The net effect is that 2 more pixels on each side of a splitter handle are now interactive and usable for splitting! :^)
This commit is contained in:
parent
9badcff1ba
commit
42f0b2522b
6 changed files with 57 additions and 17 deletions
|
@ -42,6 +42,14 @@ Frame::~Frame()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Frame::set_frame_thickness(int thickness)
|
||||||
|
{
|
||||||
|
if (m_thickness == thickness)
|
||||||
|
return;
|
||||||
|
m_thickness = thickness;
|
||||||
|
set_content_margins({ thickness, thickness, thickness, thickness });
|
||||||
|
}
|
||||||
|
|
||||||
void Frame::paint_event(PaintEvent& event)
|
void Frame::paint_event(PaintEvent& event)
|
||||||
{
|
{
|
||||||
if (m_shape == Gfx::FrameShape::NoFrame)
|
if (m_shape == Gfx::FrameShape::NoFrame)
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
virtual ~Frame() override;
|
virtual ~Frame() override;
|
||||||
|
|
||||||
int frame_thickness() const { return m_thickness; }
|
int frame_thickness() const { return m_thickness; }
|
||||||
void set_frame_thickness(int thickness) { m_thickness = thickness; }
|
void set_frame_thickness(int thickness);
|
||||||
|
|
||||||
Gfx::FrameShadow frame_shadow() const { return m_shadow; }
|
Gfx::FrameShadow frame_shadow() const { return m_shadow; }
|
||||||
void set_frame_shadow(Gfx::FrameShadow shadow) { m_shadow = shadow; }
|
void set_frame_shadow(Gfx::FrameShadow shadow) { m_shadow = shadow; }
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace GUI {
|
||||||
MultiView::MultiView()
|
MultiView::MultiView()
|
||||||
{
|
{
|
||||||
set_active_widget(nullptr);
|
set_active_widget(nullptr);
|
||||||
|
set_content_margins({ 2, 2, 2, 2 });
|
||||||
m_item_view = add<ItemView>();
|
m_item_view = add<ItemView>();
|
||||||
m_table_view = add<TableView>();
|
m_table_view = add<TableView>();
|
||||||
|
|
||||||
|
|
|
@ -76,17 +76,23 @@ void Splitter::leave_event(Core::Event&)
|
||||||
bool Splitter::get_resize_candidates_at(const Gfx::Point& position, Widget*& first, Widget*& second)
|
bool Splitter::get_resize_candidates_at(const Gfx::Point& position, Widget*& first, Widget*& second)
|
||||||
{
|
{
|
||||||
int x_or_y = position.primary_offset_for_orientation(m_orientation);
|
int x_or_y = position.primary_offset_for_orientation(m_orientation);
|
||||||
int fudge = layout()->spacing();
|
|
||||||
for_each_child_widget([&](auto& child) {
|
auto child_widgets = this->child_widgets();
|
||||||
int child_start = child.relative_rect().first_edge_for_orientation(m_orientation);
|
if (child_widgets.size() < 2)
|
||||||
int child_end = child.relative_rect().last_edge_for_orientation(m_orientation);
|
return false;
|
||||||
if (x_or_y > child_end && (x_or_y - fudge) <= child_end)
|
|
||||||
first = &child;
|
for (size_t i = 0; i < child_widgets.size() - 1; ++i) {
|
||||||
if (x_or_y < child_start && (x_or_y + fudge) >= child_start)
|
auto* first_candidate = child_widgets[i];
|
||||||
second = &child;
|
auto* second_candidate = child_widgets[i + 1];
|
||||||
return IterationDecision::Continue;
|
|
||||||
});
|
if (x_or_y > first_candidate->content_rect().last_edge_for_orientation(m_orientation)
|
||||||
return first && second;
|
&& x_or_y <= second_candidate->content_rect().first_edge_for_orientation(m_orientation)) {
|
||||||
|
first = first_candidate;
|
||||||
|
second = second_candidate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Splitter::mousedown_event(MouseEvent& event)
|
void Splitter::mousedown_event(MouseEvent& event)
|
||||||
|
@ -109,13 +115,14 @@ void Splitter::mousedown_event(MouseEvent& event)
|
||||||
|
|
||||||
void Splitter::recompute_grabbable_rect(const Widget& first, const Widget& second)
|
void Splitter::recompute_grabbable_rect(const Widget& first, const Widget& second)
|
||||||
{
|
{
|
||||||
auto first_edge = first.relative_rect().primary_offset_for_orientation(m_orientation) + first.relative_rect().primary_size_for_orientation(m_orientation);
|
auto first_edge = first.content_rect().primary_offset_for_orientation(m_orientation) + first.content_rect().primary_size_for_orientation(m_orientation);
|
||||||
auto second_edge = second.relative_rect().primary_offset_for_orientation(m_orientation);
|
auto second_edge = second.content_rect().primary_offset_for_orientation(m_orientation);
|
||||||
Gfx::Rect rect;
|
Gfx::Rect rect;
|
||||||
rect.set_primary_offset_for_orientation(m_orientation, first_edge);
|
rect.set_primary_offset_for_orientation(m_orientation, first_edge);
|
||||||
rect.set_primary_size_for_orientation(m_orientation, second_edge - first_edge);
|
rect.set_primary_size_for_orientation(m_orientation, second_edge - first_edge);
|
||||||
rect.set_secondary_offset_for_orientation(m_orientation, first.relative_rect().secondary_offset_for_orientation(m_orientation));
|
rect.set_secondary_offset_for_orientation(m_orientation, first.content_rect().secondary_offset_for_orientation(m_orientation));
|
||||||
rect.set_secondary_size_for_orientation(m_orientation, first.relative_rect().secondary_size_for_orientation(m_orientation));
|
rect.set_secondary_size_for_orientation(m_orientation, first.content_rect().secondary_size_for_orientation(m_orientation));
|
||||||
|
|
||||||
if (m_grabbable_rect != rect) {
|
if (m_grabbable_rect != rect) {
|
||||||
m_grabbable_rect = rect;
|
m_grabbable_rect = rect;
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -472,7 +472,7 @@ Widget* Widget::child_at(const Gfx::Point& point) const
|
||||||
auto& child = Core::to<Widget>(children()[i]);
|
auto& child = Core::to<Widget>(children()[i]);
|
||||||
if (!child.is_visible())
|
if (!child.is_visible())
|
||||||
continue;
|
continue;
|
||||||
if (child.relative_rect().contains(point))
|
if (child.content_rect().contains(point))
|
||||||
return const_cast<Widget*>(&child);
|
return const_cast<Widget*>(&child);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -811,4 +811,21 @@ void Widget::did_end_inspection()
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::set_content_margins(const Margins& margins)
|
||||||
|
{
|
||||||
|
if (m_content_margins == margins)
|
||||||
|
return;
|
||||||
|
m_content_margins = margins;
|
||||||
|
invalidate_layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
Gfx::Rect Widget::content_rect() const
|
||||||
|
{
|
||||||
|
auto rect = relative_rect();
|
||||||
|
rect.move_by(m_content_margins.left(), m_content_margins.top());
|
||||||
|
rect.set_width(rect.width() - (m_content_margins.left() + m_content_margins.right()));
|
||||||
|
rect.set_height(rect.height() - (m_content_margins.top() + m_content_margins.bottom()));
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <LibCore/Object.h>
|
#include <LibCore/Object.h>
|
||||||
#include <LibGUI/Event.h>
|
#include <LibGUI/Event.h>
|
||||||
#include <LibGUI/Forward.h>
|
#include <LibGUI/Forward.h>
|
||||||
|
#include <LibGUI/Margins.h>
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
#include <LibGfx/Forward.h>
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibGfx/Orientation.h>
|
#include <LibGfx/Orientation.h>
|
||||||
|
@ -266,6 +267,11 @@ public:
|
||||||
Gfx::Palette palette() const;
|
Gfx::Palette palette() const;
|
||||||
void set_palette(const Gfx::Palette&);
|
void set_palette(const Gfx::Palette&);
|
||||||
|
|
||||||
|
const Margins& content_margins() const { return m_content_margins; }
|
||||||
|
void set_content_margins(const Margins&);
|
||||||
|
|
||||||
|
Gfx::Rect content_rect() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Widget();
|
Widget();
|
||||||
|
|
||||||
|
@ -324,6 +330,7 @@ private:
|
||||||
SizePolicy m_horizontal_size_policy { SizePolicy::Fill };
|
SizePolicy m_horizontal_size_policy { SizePolicy::Fill };
|
||||||
SizePolicy m_vertical_size_policy { SizePolicy::Fill };
|
SizePolicy m_vertical_size_policy { SizePolicy::Fill };
|
||||||
Gfx::Size m_preferred_size;
|
Gfx::Size m_preferred_size;
|
||||||
|
Margins m_content_margins;
|
||||||
|
|
||||||
bool m_fill_with_background_color { false };
|
bool m_fill_with_background_color { false };
|
||||||
bool m_visible { true };
|
bool m_visible { true };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue