[gtkmm-documentation] Update the custom container example
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm-documentation] Update the custom container example
- Date: Mon, 1 Aug 2022 08:37:33 +0000 (UTC)
commit 5a4a541ce827ad6a20c1cd2fd6d4d1f7f2a29617
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date: Mon Aug 1 10:34:26 2022 +0200
Update the custom container example
Make it more similar to a GtkBox, using get_first_child(), insert_at_end()
and similar Widget methods. It can have more than two children.
.../book/custom/custom_container/examplewindow.cc | 11 +-
.../book/custom/custom_container/examplewindow.h | 8 +-
.../book/custom/custom_container/mycontainer.cc | 221 +++++++--------------
.../book/custom/custom_container/mycontainer.h | 16 +-
4 files changed, 85 insertions(+), 171 deletions(-)
---
diff --git a/examples/book/custom/custom_container/examplewindow.cc
b/examples/book/custom/custom_container/examplewindow.cc
index cc8a0f5..feb1812 100644
--- a/examples/book/custom/custom_container/examplewindow.cc
+++ b/examples/book/custom/custom_container/examplewindow.cc
@@ -14,13 +14,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_VBox(Gtk::Orientation::VERTICAL),
- m_Button_One("Child One"),
- m_Label_Two("Child 2", Gtk::Align::END, Gtk::Align::CENTER),
+ m_Button_Child("Child button"),
+ m_Label_Child("Child label", Gtk::Align::END, Gtk::Align::CENTER),
m_Button_Quit("Quit")
{
set_title("Custom Container example");
@@ -30,7 +29,10 @@ ExampleWindow::ExampleWindow()
set_child(m_VBox);
//Add the child widgets to the custom container:
- m_MyContainer.set_child_widgets(m_Button_One, m_Label_Two);
+ m_MyContainer.append(m_Button_Child);
+ m_MyContainer.append(m_Label_Child);
+ m_MyContainer.prepend(*Gtk::make_managed<Gtk::Label>(
+ "First line\nSecond line\nThird line"));
m_MyContainer.set_expand();
m_VBox.append(m_MyContainer);
@@ -52,4 +54,3 @@ void ExampleWindow::on_button_quit()
{
hide();
}
-
diff --git a/examples/book/custom/custom_container/examplewindow.h
b/examples/book/custom/custom_container/examplewindow.h
index 5d50f1b..5c4406c 100644
--- a/examples/book/custom/custom_container/examplewindow.h
+++ b/examples/book/custom/custom_container/examplewindow.h
@@ -24,7 +24,7 @@ class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
- virtual ~ExampleWindow();
+ ~ExampleWindow() override;
protected:
//Signal handlers:
@@ -32,11 +32,9 @@ protected:
//Child widgets:
Gtk::Box m_VBox;
- Gtk::Button m_Button_One;
- Gtk::Label m_Label_Two;
- // A restriction with MyContainer is that it must be deleted before
- // its children, meaning that it must be declared after its children.
MyContainer m_MyContainer;
+ Gtk::Button m_Button_Child;
+ Gtk::Label m_Label_Child;
Gtk::Box m_ButtonBox;
Gtk::Button m_Button_Quit;
};
diff --git a/examples/book/custom/custom_container/mycontainer.cc
b/examples/book/custom/custom_container/mycontainer.cc
index e17047f..73ba51e 100644
--- a/examples/book/custom/custom_container/mycontainer.cc
+++ b/examples/book/custom/custom_container/mycontainer.cc
@@ -15,34 +15,35 @@
*/
#include <iostream>
-#include <algorithm> // std::max
#include "mycontainer.h"
+// This example container is a simplified vertical Box.
+//
+// It can't be used as a managed widget, managed by another container.
+// It would cause an error like
+// Gtk-WARNING **: 08:31:48.137: Finalizing gtkmm__GtkWidget 0x561b777462c0, but it still has children left:
+
MyContainer::MyContainer()
-: m_child_one(nullptr), m_child_two(nullptr)
{
}
MyContainer::~MyContainer()
{
- if (m_child_one)
- m_child_one->unparent();
-
- if (m_child_two)
- m_child_two->unparent();
+ while (Widget* child = get_first_child())
+ child->unparent();
}
-void MyContainer::set_child_widgets(Gtk::Widget& child_one,
- Gtk::Widget& child_two)
+// Get number of visible children.
+int MyContainer::get_nvis_children() const
{
- m_child_one = &child_one;
- m_child_two = &child_two;
+ int nvis_children = 0;
+ for (const Widget* child = get_first_child(); child; child = child->get_next_sibling())
+ if (child->get_visible())
+ ++nvis_children;
- m_child_one->set_parent(*this);
- m_child_two->set_parent(*this);
+ return nvis_children;
}
-// This example container is a simplified vertical Box with at most two children.
Gtk::SizeRequestMode MyContainer::get_request_mode_vfunc() const
{
return Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH;
@@ -57,6 +58,9 @@ void MyContainer::measure_vfunc(Gtk::Orientation orientation, int for_size,
minimum_baseline = -1;
natural_baseline = -1;
+ minimum = 0;
+ natural = 0;
+
int dummy_minimum_baseline = 0;
int dummy_natural_baseline = 0;
@@ -66,78 +70,60 @@ void MyContainer::measure_vfunc(Gtk::Orientation orientation, int for_size,
if (for_size >= 0)
{
- int nvis_children = 0;
-
- // Get number of visible children.
- if (m_child_one && m_child_one->get_visible())
- ++nvis_children;
- if (m_child_two && m_child_two->get_visible())
- ++nvis_children;
+ // Number of visible children.
+ const int nvis_children = get_nvis_children();
// Divide the height equally among the visible children.
if (nvis_children > 0)
height_per_child = for_size / nvis_children;
}
- int child_minimum_width[2] = {0, 0};
- int child_natural_width[2] = {0, 0};
-
- if (m_child_one && m_child_one->get_visible())
- m_child_one->measure(orientation, height_per_child, child_minimum_width[0],
- child_natural_width[0], dummy_minimum_baseline, dummy_natural_baseline);
-
- if (m_child_two && m_child_two->get_visible())
- m_child_two->measure(orientation, height_per_child, child_minimum_width[1],
- child_natural_width[1], dummy_minimum_baseline, dummy_natural_baseline);
-
// Request a width equal to the width of the widest visible child.
- minimum = std::max(child_minimum_width[0], child_minimum_width[1]);
- natural = std::max(child_natural_width[0], child_natural_width[1]);
+ for (const Widget* child = get_first_child(); child; child = child->get_next_sibling())
+ if (child->get_visible())
+ {
+ int child_minimum_width = 0;
+ int child_natural_width = 0;
+ child->measure(orientation, height_per_child, child_minimum_width,
+ child_natural_width, dummy_minimum_baseline, dummy_natural_baseline);
+ if (child_minimum_width > minimum)
+ minimum = child_minimum_width;
+ if (child_natural_width > natural)
+ natural = child_natural_width;
+ }
}
else // Gtk::Orientation::VERTICAL
{
- int child_minimum_height[2] = {0, 0};
- int child_natural_height[2] = {0, 0};
- int nvis_children = 0;
-
- if (m_child_one && m_child_one->get_visible())
- {
- ++nvis_children;
- m_child_one->measure(orientation, for_size, child_minimum_height[0],
- child_natural_height[0], dummy_minimum_baseline, dummy_natural_baseline);
- }
-
- if (m_child_two && m_child_two->get_visible())
- {
- ++nvis_children;
- m_child_two->measure(orientation, for_size, child_minimum_height[1],
- child_natural_height[1], dummy_minimum_baseline, dummy_natural_baseline);
- }
-
// The allocated height will be divided equally among the visible children.
// Request a height equal to the number of visible children times the height
// of the highest child.
- minimum = nvis_children * std::max(child_minimum_height[0],
- child_minimum_height[1]);
- natural = nvis_children * std::max(child_natural_height[0],
- child_natural_height[1]);
+ int nvis_children = 0;
+ for (const Widget* child = get_first_child(); child; child = child->get_next_sibling())
+ if (child->get_visible())
+ {
+ ++nvis_children;
+ int child_minimum_height = 0;
+ int child_natural_height = 0;
+ child->measure(orientation, for_size, child_minimum_height,
+ child_natural_height, dummy_minimum_baseline, dummy_natural_baseline);
+ if (child_minimum_height > minimum)
+ minimum = child_minimum_height;
+ if (child_natural_height > natural)
+ natural = child_natural_height;
+ }
+ minimum *= nvis_children;
+ natural *= nvis_children;
}
}
-void MyContainer::size_allocate_vfunc(int width, int height, int baseline)
+void MyContainer::size_allocate_vfunc(int width, int height, int baseline)
{
//Do something with the space that we have actually been given:
//(We will not be given heights or widths less than we have requested, though
//we might get more.)
- //Get number of visible children.
- const bool visible_one = m_child_one && m_child_one->get_visible();
- const bool visible_two = m_child_two && m_child_two->get_visible();
- int nvis_children = 0;
- if (visible_one)
- ++nvis_children;
- if (visible_two)
- ++nvis_children;
+ // Number of visible children.
+ const int nvis_children = get_nvis_children();
if (nvis_children <= 0)
{
@@ -146,102 +132,37 @@ void MyContainer::size_allocate_vfunc(int width, int height, int baseline)
}
//Assign space to the children:
- Gtk::Allocation child_allocation_one;
- Gtk::Allocation child_allocation_two;
+ Gtk::Allocation child_allocation;
+ const int height_per_child = height / nvis_children;
- //Place the first child at the top-left:
- child_allocation_one.set_x(0);
- child_allocation_one.set_y(0);
+ //Place the first visible child at the top-left:
+ child_allocation.set_x(0);
+ child_allocation.set_y(0);
//Make it take up the full width available:
- child_allocation_one.set_width(width);
-
- if (visible_one)
- {
- //Divide the height equally among the visible children.
- child_allocation_one.set_height(height / nvis_children);
- m_child_one->size_allocate(child_allocation_one, baseline);
- }
- else
- child_allocation_one.set_height(0);
-
- //Place the second child below the first child:
- child_allocation_two.set_x(0);
- child_allocation_two.set_y(child_allocation_one.get_height());
+ child_allocation.set_width(width);
+ child_allocation.set_height(height_per_child);
- //Make it take up the full width available:
- child_allocation_two.set_width(width);
-
- //Make it take up the remaining height:
- child_allocation_two.set_height(height - child_allocation_one.get_height());
-
- if (visible_two)
- {
- m_child_two->size_allocate(child_allocation_two, baseline);
- }
-}
-#if 0
-void MyContainer::forall_vfunc(const ForeachSlot& slot)
-{
- if (m_child_one)
- slot(*m_child_one);
-
- if (m_child_two)
- slot(*m_child_two);
+ //Divide the height equally among the visible children.
+ for (Widget* child = get_first_child(); child; child = child->get_next_sibling())
+ if (child->get_visible())
+ {
+ child->size_allocate(child_allocation, baseline);
+ child_allocation.set_y(child_allocation.get_y() + height_per_child);
+ }
}
-void MyContainer::on_add(Gtk::Widget* child)
+void MyContainer::append(Gtk::Widget& child)
{
- if(!m_child_one)
- {
- m_child_one = child;
- m_child_one->set_parent(*this);
- }
- else if(!m_child_two)
- {
- m_child_two = child;
- m_child_two->set_parent(*this);
- }
+ child.insert_at_end(*this);
}
-void MyContainer::on_remove(Gtk::Widget* child)
+void MyContainer::prepend(Gtk::Widget& child)
{
- if(child)
- {
- const bool visible = child->get_visible();
- bool found = false;
-
- if(child == m_child_one)
- {
- m_child_one = nullptr;
- found = true;
- }
- else if(child == m_child_two)
- {
- m_child_two = nullptr;
- found = true;
- }
-
- if(found)
- {
- child->unparent();
-
- if(visible)
- queue_resize();
- }
- }
+ child.insert_at_start(*this);
}
-GType MyContainer::child_type_vfunc() const
+void MyContainer::remove(Gtk::Widget& child)
{
- //If there is still space for one widget, then report the type of widget that
- //may be added.
- if(!m_child_one || !m_child_two)
- return Gtk::Widget::get_type();
- else
- {
- //No more widgets may be added.
- return G_TYPE_NONE;
- }
+ child.unparent();
}
-#endif
diff --git a/examples/book/custom/custom_container/mycontainer.h
b/examples/book/custom/custom_container/mycontainer.h
index 6e0d86c..8eef093 100644
--- a/examples/book/custom/custom_container/mycontainer.h
+++ b/examples/book/custom/custom_container/mycontainer.h
@@ -23,26 +23,20 @@ class MyContainer : public Gtk::Widget
{
public:
MyContainer();
- virtual ~MyContainer();
+ ~MyContainer() override;
- void set_child_widgets(Gtk::Widget& child_one, Gtk::Widget& child_two);
+ void append(Gtk::Widget& child);
+ void prepend(Gtk::Widget& child);
+ void remove(Gtk::Widget& child);
protected:
+ int get_nvis_children() const;
//Overrides:
Gtk::SizeRequestMode get_request_mode_vfunc() const override;
void measure_vfunc(Gtk::Orientation orientation, int for_size, int& minimum, int& natural,
int& minimum_baseline, int& natural_baseline) const override;
void size_allocate_vfunc(int width, int height, int baseline) override;
-#if 0
- void forall_vfunc(const ForeachSlot& slot) override;
-
- void on_add(Gtk::Widget* child) override;
- void on_remove(Gtk::Widget* child) override;
- GType child_type_vfunc() const override;
-#endif
- Gtk::Widget* m_child_one;
- Gtk::Widget* m_child_two;
};
#endif //GTKMM_CUSTOM_CONTAINER_MYCONTAINER_H
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]