瀏覽代碼

LibGUI: Improve GBoxLayout so it can better support GToolBar.

Added spacing and margin concepts to GLayout. Support layout a sequence
of nothing but fixed-size objects in the desired orientation. :^)
Andreas Kling 6 年之前
父節點
當前提交
dc753b58a5
共有 5 個文件被更改,包括 84 次插入20 次删除
  1. 12 15
      LibGUI/GBoxLayout.cpp
  2. 18 0
      LibGUI/GLayout.cpp
  3. 10 0
      LibGUI/GLayout.h
  4. 40 0
      LibGUI/GMargins.h
  5. 4 5
      LibGUI/GToolBar.cpp

+ 12 - 15
LibGUI/GBoxLayout.cpp

@@ -66,25 +66,22 @@ void GBoxLayout::run(GWidget& widget)
     dbgprintf("GBoxLayout: automatic_size=%s\n", automatic_size.to_string().characters());
 #endif
 
-    int current_x = 0;
-    int current_y = 0;
- for (auto& entry : m_entries) {
+    // FIXME: We should also respect the bottom and right margins.
+    int current_x = margins().left();
+    int current_y = margins().top();
+
+    for (auto& entry : m_entries) {
         Rect rect(current_x, current_y, 0, 0);
         if (entry.layout) {
             // FIXME: Implement recursive layout.
             ASSERT_NOT_REACHED();
         }
         ASSERT(entry.widget);
-        if (entry.widget->size_policy(orientation()) == SizePolicy::Fixed) {
-            rect.set_size(automatic_size);
-            if (orientation() == Orientation::Vertical) {
-                rect.set_height(entry.widget->preferred_size().height());
-            } else {
-                rect.set_width(entry.widget->preferred_size().height());
-            }
-        } else {
-            rect.set_size(automatic_size);
-        }
+        rect.set_size(automatic_size);
+        if (entry.widget->size_policy(Orientation::Vertical) == SizePolicy::Fixed)
+            rect.set_height(entry.widget->preferred_size().height());
+        if (entry.widget->size_policy(Orientation::Horizontal) == SizePolicy::Fixed)
+            rect.set_width(entry.widget->preferred_size().height());
 
 #ifdef GBOXLAYOUT_DEBUG
         dbgprintf("GBoxLayout: apply, %s{%p} <- %s\n", entry.widget->class_name(), entry.widget.ptr(), rect.to_string().characters());
@@ -92,8 +89,8 @@ void GBoxLayout::run(GWidget& widget)
         entry.widget->set_relative_rect(rect);
 
         if (orientation() == Orientation::Horizontal)
-            current_x += rect.width();
+            current_x += rect.width() + spacing();
         else
-            current_y += rect.height();
+            current_y += rect.height() + spacing();
     }
 }

+ 18 - 0
LibGUI/GLayout.cpp

@@ -39,3 +39,21 @@ void GLayout::add_widget(GWidget& widget)
     if (m_owner)
         m_owner->notify_layout_changed(Badge<GLayout>());
 }
+
+void GLayout::set_spacing(int spacing)
+{
+    if (m_spacing == spacing)
+        return;
+    m_spacing = spacing;
+    if (m_owner)
+        m_owner->notify_layout_changed(Badge<GLayout>());
+}
+
+void GLayout::set_margins(const GMargins& margins)
+{
+    if (m_margins == margins)
+        return;
+    m_margins = margins;
+    if (m_owner)
+        m_owner->notify_layout_changed(Badge<GLayout>());
+}

+ 10 - 0
LibGUI/GLayout.h

@@ -4,6 +4,7 @@
 #include <AK/OwnPtr.h>
 #include <AK/Vector.h>
 #include <AK/WeakPtr.h>
+#include <LibGUI/GMargins.h>
 
 class GWidget;
 
@@ -20,6 +21,12 @@ public:
     void notify_adopted(Badge<GWidget>, GWidget&);
     void notify_disowned(Badge<GWidget>, GWidget&);
 
+    GMargins margins() const { return m_margins; }
+    void set_margins(const GMargins&);
+
+    int spacing() const { return m_spacing; }
+    void set_spacing(int);
+
 protected:
     struct Entry {
         WeakPtr<GWidget> widget;
@@ -27,5 +34,8 @@ protected:
     };
     WeakPtr<GWidget> m_owner;
     Vector<Entry> m_entries;
+
+    GMargins m_margins;
+    int m_spacing { 0 };
 };
 

+ 40 - 0
LibGUI/GMargins.h

@@ -0,0 +1,40 @@
+#pragma once
+
+class GMargins {
+public:
+    GMargins() { }
+    GMargins(int left, int top, int right, int bottom)
+        : m_left(left)
+        , m_top(top)
+        , m_right(right)
+        , m_bottom(bottom)
+    {
+    }
+    ~GMargins() { }
+
+    bool is_null() const { return !m_left && !m_top && !m_right && !m_bottom; }
+
+    int left() const { return m_left; }
+    int top() const { return m_top; }
+    int right() const { return m_right; }
+    int bottom() const { return m_bottom; }
+
+    void set_left(int value) { m_left = value; }
+    void set_top(int value) { m_top = value; }
+    void set_right(int value) { m_right = value; }
+    void set_bottom(int value) { m_bottom = value; }
+
+    bool operator==(const GMargins& other) const
+    {
+        return m_left == other.m_left
+            && m_top == other.m_top
+            && m_right == other.m_right
+            && m_bottom == other.m_bottom;
+    }
+
+private:
+    int m_left { 0 };
+    int m_top { 0 };
+    int m_right { 0 };
+    int m_bottom { 0 };
+};

+ 4 - 5
LibGUI/GToolBar.cpp

@@ -8,8 +8,10 @@ GToolBar::GToolBar(GWidget* parent)
     : GWidget(parent)
 {
     set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
-    set_preferred_size({ 0, 24 });
+    set_preferred_size({ 0, 25 });
     set_layout(make<GBoxLayout>(Orientation::Horizontal));
+    layout()->set_spacing(1);
+    layout()->set_margins({1, 1, 1, 1});
 }
 
 GToolBar::~GToolBar()
@@ -33,11 +35,8 @@ void GToolBar::add_action(RetainPtr<GAction>&& action)
         raw_action_ptr->activate();
     };
 
-#if 0
-    // FIXME: Gotta fix GBoxLayout for this to work.
     button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
-    button->set_preferred_size({ 16, 16 });
-#endif
+    button->set_preferred_size({ 22, 22 });
 
     m_items.append(move(item));
 }