LibGUI: Make Layout a Core::Object and add basic serialization

This allows you to view layouts (as data) in Inspector.
This commit is contained in:
Andreas Kling 2020-03-05 09:21:46 +01:00
parent ecc39678f5
commit 849fdc1c0b
8 changed files with 66 additions and 13 deletions

View file

@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AK/JsonObject.h>
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Widget.h>
#include <LibGfx/Orientation.h>
@ -174,4 +175,10 @@ void BoxLayout::run(Widget& widget)
}
}
void BoxLayout::save_to(JsonObject& json)
{
Layout::save_to(json);
json.set("orientation", m_orientation == Gfx::Orientation::Vertical ? "Vertical" : "Horizontal");
}
}

View file

@ -33,19 +33,25 @@
namespace GUI {
class BoxLayout : public Layout {
C_OBJECT(BoxLayout);
public:
explicit BoxLayout(Gfx::Orientation);
virtual ~BoxLayout() override {}
Gfx::Orientation orientation() const { return m_orientation; }
virtual void run(Widget&) override;
protected:
explicit BoxLayout(Gfx::Orientation);
virtual void save_to(JsonObject &) override;
private:
Gfx::Orientation m_orientation;
};
class VerticalBoxLayout final : public BoxLayout {
C_OBJECT(VerticalBoxLayout);
public:
explicit VerticalBoxLayout()
: BoxLayout(Gfx::Orientation::Vertical)
@ -55,6 +61,7 @@ public:
};
class HorizontalBoxLayout final : public BoxLayout {
C_OBJECT(HorizontalBoxLayout);
public:
explicit HorizontalBoxLayout()
: BoxLayout(Gfx::Orientation::Horizontal)

View file

@ -25,6 +25,7 @@
*/
#include <AK/Badge.h>
#include <AK/JsonObject.h>
#include <LibGUI/Layout.h>
#include <LibGUI/Widget.h>
@ -120,4 +121,32 @@ void Layout::set_margins(const Margins& margins)
m_owner->notify_layout_changed({});
}
void Layout::save_to(JsonObject& json)
{
Core::Object::save_to(json);
json.set("spacing", m_spacing);
JsonObject margins_object;
margins_object.set("left", m_margins.left());
margins_object.set("right", m_margins.right());
margins_object.set("top", m_margins.top());
margins_object.set("bottom", m_margins.bottom());
json.set("margins", move(margins_object));
JsonArray entries_array;
for (auto& entry : m_entries) {
JsonObject entry_object;
if (entry.type == Entry::Type::Widget) {
entry_object.set("type", "Widget");
entry_object.set("widget", (uintptr_t)entry.widget.ptr());
} else if (entry.type == Entry::Type::Spacer) {
entry_object.set("type", "Spacer");
} else {
ASSERT_NOT_REACHED();
}
entries_array.append(move(entry_object));
}
json.set("entries", move(entries_array));
}
}

View file

@ -29,14 +29,16 @@
#include <AK/OwnPtr.h>
#include <AK/Vector.h>
#include <AK/WeakPtr.h>
#include <LibCore/Object.h>
#include <LibGUI/Forward.h>
#include <LibGUI/Margins.h>
namespace GUI {
class Layout {
class Layout : public Core::Object {
C_OBJECT_ABSTRACT(Layout);
public:
Layout();
virtual ~Layout();
void add_widget(Widget&);
@ -57,7 +59,11 @@ public:
int spacing() const { return m_spacing; }
void set_spacing(int);
virtual void save_to(JsonObject&) override;
protected:
Layout();
struct Entry {
enum class Type {
Invalid = 0,

View file

@ -36,7 +36,7 @@ Splitter::Splitter(Orientation orientation)
: m_orientation(orientation)
{
set_background_role(ColorRole::Button);
set_layout(make<BoxLayout>(orientation));
set_layout<BoxLayout>(orientation);
set_fill_with_background_color(true);
layout()->set_spacing(4);
}

View file

@ -44,7 +44,7 @@ ToolBar::ToolBar(Orientation orientation, int button_size)
set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
set_preferred_size(button_size + 12, 0);
}
set_layout(make<BoxLayout>(orientation));
set_layout<BoxLayout>(orientation);
layout()->set_spacing(0);
layout()->set_margins({ 2, 2, 2, 2 });
}

View file

@ -242,12 +242,15 @@ void Widget::handle_paint_event(PaintEvent& event)
second_paint_event(event);
}
void Widget::set_layout(OwnPtr<Layout>&& layout)
void Widget::set_layout(NonnullRefPtr<Layout> layout)
{
if (m_layout)
if (m_layout) {
m_layout->notify_disowned({}, *this);
m_layout->remove_from_parent();
}
m_layout = move(layout);
if (m_layout) {
add_child(*m_layout);
m_layout->notify_adopted({}, *this);
do_layout();
} else {

View file

@ -96,13 +96,14 @@ public:
Layout* layout() { return m_layout.ptr(); }
const Layout* layout() const { return m_layout.ptr(); }
void set_layout(OwnPtr<Layout>&&);
void set_layout(NonnullRefPtr<Layout>);
template<typename T>
T& set_layout()
template<class T, class... Args>
inline T& set_layout(Args&&... args)
{
set_layout(make<T>());
return static_cast<T&>(*layout());
auto layout = T::construct(forward<Args>(args)...);
set_layout(*layout);
return layout;
}
SizePolicy horizontal_size_policy() const { return m_horizontal_size_policy; }
@ -304,7 +305,7 @@ private:
void focus_next_widget();
Window* m_window { nullptr };
OwnPtr<Layout> m_layout;
RefPtr<Layout> m_layout;
Gfx::Rect m_relative_rect;
Gfx::ColorRole m_background_role;