Struct gtk4::Widget [−][src]
pub struct Widget(_);
Expand description
The base class for all widgets.
Widget
is the base class all widgets in GTK derive from. It manages the
widget lifecycle, layout, states and style.
Height-for-width Geometry Management
GTK uses a height-for-width (and width-for-height) geometry management system. Height-for-width means that a widget can change how much vertical space it needs, depending on the amount of horizontal space that it is given (and similar for width-for-height). The most common example is a label that reflows to fill up the available width, wraps to fewer lines, and therefore needs less height.
Height-for-width geometry management is implemented in GTK by way of two virtual methods:
vfunc::Gtk::Widget::get_request_mode
vfunc::Gtk::Widget::measure
There are some important things to keep in mind when implementing height-for-width and when using it in widget implementations.
If you implement a direct Widget
subclass that supports
height-for-width or width-for-height geometry management for itself
or its child widgets, the vfunc::Gtk::Widget::get_request_mode
virtual
function must be implemented as well and return the widget’s preferred
request mode. The default implementation of this virtual function
returns SizeRequestMode::ConstantSize
, which means that the widget will
only ever get -1 passed as the for_size value to its
vfunc::Gtk::Widget::measure
implementation.
The geometry management system will query a widget hierarchy in
only one orientation at a time. When widgets are initially queried
for their minimum sizes it is generally done in two initial passes
in the SizeRequestMode
chosen by the toplevel.
For example, when queried in the normal SizeRequestMode::HeightForWidth
mode:
First, the default minimum and natural width for each widget
in the interface will be computed using prelude::WidgetExt::measure
with an
orientation of Orientation::Horizontal
and a for_size of -1.
Because the preferred widths for each widget depend on the preferred
widths of their children, this information propagates up the hierarchy,
and finally a minimum and natural width is determined for the entire
toplevel. Next, the toplevel will use the minimum width to query for the
minimum height contextual to that width using prelude::WidgetExt::measure
with an
orientation of Orientation::Vertical
and a for_size of the just computed
width. This will also be a highly recursive operation. The minimum height
for the minimum width is normally used to set the minimum size constraint
on the toplevel.
After the toplevel window has initially requested its size in both
dimensions it can go on to allocate itself a reasonable size (or a size
previously specified with GtkWindowExt::set_default_size()
). During the
recursive allocation process it’s important to note that request cycles
will be recursively executed while widgets allocate their children.
Each widget, once allocated a size, will go on to first share the
space in one orientation among its children and then request each child’s
height for its target allocated width or its width for allocated height,
depending. In this way a Widget
will typically be requested its size
a number of times before actually being allocated a size. The size a
widget is finally allocated can of course differ from the size it has
requested. For this reason, Widget
caches a small number of results
to avoid re-querying for the same sizes in one allocation cycle.
If a widget does move content around to intelligently use up the
allocated size then it must support the request in both
SizeRequestMode
s even if the widget in question only
trades sizes in a single orientation.
For instance, a Label
that does height-for-width word wrapping
will not expect to have vfunc::Gtk::Widget::measure
with an orientation of
Orientation::Vertical
called because that call is specific to a
width-for-height request. In this case the label must return the height
required for its own minimum possible width. By following this rule any
widget that handles height-for-width or width-for-height requests will
always be allocated at least enough space to fit its own content.
Here are some examples of how a SizeRequestMode::HeightForWidth
widget
generally deals with width-for-height requests:
⚠️ The following code is in c ⚠️
static void
foo_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum_size,
int *natural_size,
int *minimum_baseline,
int *natural_baseline)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
// Calculate minimum and natural width
}
else // VERTICAL
{
if (i_am_in_height_for_width_mode)
{
int min_width, dummy;
// First, get the minimum width of our widget
GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
&min_width, &dummy, &dummy, &dummy);
// Now use the minimum width to retrieve the minimum and natural height to display
// that width.
GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_VERTICAL, min_width,
minimum_size, natural_size, &dummy, &dummy);
}
else
{
// ... some widgets do both.
}
}
}
Often a widget needs to get its own request during size request or allocation. For example, when computing height it may need to also compute width. Or when deciding how to use an allocation, the widget may need to know its natural size. In these cases, the widget should be careful to call its virtual methods directly, like in the code example above.
It will not work to use the wrapper function WidgetExt::measure()
inside your own vfunc::Gtk::Widget::size_allocate
implementation.
These return a request adjusted by SizeGroup
, the widget’s
align and expand flags, as well as its CSS style.
If a widget used the wrappers inside its virtual method implementations, then the adjustments (such as widget margins) would be applied twice. GTK therefore does not allow this and will warn if you try to do it.
Of course if you are getting the size request for another widget, such
as a child widget, you must use prelude::WidgetExt::measure
; otherwise, you
would not properly consider widget margins, SizeGroup
, and
so forth.
GTK also supports baseline vertical alignment of widgets. This
means that widgets are positioned such that the typographical baseline of
widgets in the same row are aligned. This happens if a widget supports
baselines, has a vertical alignment of Align::Baseline
, and is inside
a widget that supports baselines and has a natural “row” that it aligns to
the baseline, or a baseline assigned to it by the grandparent.
Baseline alignment support for a widget is also done by the
vfunc::Gtk::Widget::measure
virtual function. It allows you to report
both a minimum and natural size.
If a widget ends up baseline aligned it will be allocated all the space in
the parent as if it was Align::Fill
, but the selected baseline can be
found via [prelude::WidgetExt::get_allocated_baseline
][crate::prelude::WidgetExt::get_allocated_baseline]. If the baseline has a
value other than -1 you need to align the widget such that the baseline
appears at the position.
GtkWidget as GtkBuildable
The Widget
implementation of the Buildable
interface
supports various custom elements to specify additional aspects of widgets
that are not directly expressed as properties.
If the widget uses a LayoutManager
, Widget
supports
a custom <layout>
element, used to define layout properties:
<object class="GtkGrid" id="my_grid">
<child>
<object class="GtkLabel" id="label1">
<property name="label">Description</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="row-span">1</property>
<property name="column-span">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="description_entry">
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="row-span">1</property>
<property name="column-span">1</property>
</layout>
</object>
</child>
</object>
Widget
allows style information such as style classes to
be associated with widgets, using the custom <style>
element:
<object class="GtkButton" id="button1">
<style>
<class name="my-special-button-class"/>
<class name="dark-button"/>
</style>
</object>
Widget
allows defining accessibility information, such as properties,
relations, and states, using the custom <accessibility>
element:
<object class="GtkButton" id="button1">
<accessibility>
<property name="label">Download</property>
<relation name="labelled-by">label1</relation>
</accessibility>
</object>
Building composite widgets from template XML
GtkWidget
exposes some facilities to automate the procedure
of creating composite widgets using “templates”.
To create composite widgets with Builder
XML, one must associate
the interface description with the widget class at class initialization
time using Gtk::
WidgetClass::set_template()``.
The interface description semantics expected in composite template descriptions
is slightly different from regular Builder
XML.
Unlike regular interface descriptions, Gtk::
WidgetClass::set_template()will expect a
tag as a direct child of the toplevel
tag. The
`` tag must specify the “class” attribute which must be
the type name of the widget. Optionally, the “parent” attribute may be
specified to specify the direct parent type of the widget type, this is
ignored by Builder
but required for UI design tools like
Glade to introspect what kind of properties and
internal children exist for a given type when the actual type does not exist.
The XML which is contained inside the <template>
tag behaves as if it were
added to the <object>
tag defining the widget itself. You may set properties
on a widget by inserting <property>
tags into the <template>
tag, and also
add <child>
tags to add children and extend a widget in the normal way you
would with <object>
tags.
Additionally, <object>
tags can also be added before and after the initial
<template>
tag in the normal way, allowing one to define auxiliary objects
which might be referenced by other widgets declared as children of the
<template>
tag.
An example of a template definition:
<interface>
<template class="FooWidget" parent="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">4</property>
<child>
<object class="GtkButton" id="hello_button">
<property name="label">Hello World</property>
<signal name="clicked" handler="hello_button_clicked" object="FooWidget" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="goodbye_button">
<property name="label">Goodbye World</property>
</object>
</child>
</template>
</interface>
Typically, you’ll place the template fragment into a file that is
bundled with your project, using GResource
. In order to load the
template, you need to call Gtk::
WidgetClass::set_template_from_resource()``
from the class initialization of your Widget
type:
⚠️ The following code is in c ⚠️
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
}
You will also need to call WidgetExt::init_template()
from the
instance initialization function:
⚠️ The following code is in c ⚠️
static void
foo_widget_init (FooWidget *self)
{
// ...
gtk_widget_init_template (GTK_WIDGET (self));
}
You can access widgets defined in the template using the
[prelude::WidgetExt::get_template_child
][crate::prelude::WidgetExt::get_template_child] function, but you will typically declare
a pointer in the instance private data structure of your type using the same
name as the widget in the template definition, and call
Gtk::
WidgetClass::bind_template_child_full()(or one of its wrapper macros
widget_class_bind_template_child()and
widget_class_bind_template_child_private()``)
with that name, e.g.
⚠️ The following code is in c ⚠️
typedef struct {
GtkWidget *hello_button;
GtkWidget *goodbye_button;
} FooWidgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FooWidget, foo_widget, GTK_TYPE_BOX)
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
FooWidget, hello_button);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
FooWidget, goodbye_button);
}
static void
foo_widget_init (FooWidget *widget)
{
}
You can also use Gtk::
WidgetClass::bind_template_callback_full()(or is wrapper macro
widget_class_bind_template_callback()``) to connect
a signal callback defined in the template with a function visible in the
scope of the class, e.g.
⚠️ The following code is in c ⚠️
// the signal handler has the instance and user data swapped
// because of the swapped="yes" attribute in the template XML
static void
hello_button_clicked (FooWidget *self,
GtkButton *button)
{
g_print ("Hello, world!\n");
}
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), hello_button_clicked);
}
This is an Abstract Base Class, you cannot instantiate it.
Implements
WidgetExt
, glib::ObjectExt
, AccessibleExt
, BuildableExt
, ConstraintTargetExt
, WidgetExtManual
, AccessibleExtManual
Implementations
Sets the default reading direction for widgets.
See WidgetExt::set_direction()
.
dir
the new default direction. This cannot be TextDirection::None
.
Trait Implementations
This method returns an ordering between self
and other
values if one exists. Read more
This method tests less than (for self
and other
) and is used by the <
operator. Read more
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
This method tests greater than (for self
and other
) and is used by the >
operator. Read more
Returns the type identifier of Self
.
Auto Trait Implementations
impl RefUnwindSafe for Widget
impl UnwindSafe for Widget
Blanket Implementations
Mutably borrows from an owned value. Read more
Upcasts an object to a superclass or interface T
. Read more
Upcasts an object to a reference of its superclass or interface T
. Read more
Tries to downcast to a subclass or interface implementor T
. Read more
Tries to downcast to a reference of its subclass or interface implementor T
. Read more
Tries to cast to an object of type T
. This handles upcasting, downcasting
and casting between interface and interface implementors. All checks are performed at
runtime, while downcast
and upcast
will do many checks at compile-time already. Read more
Tries to cast to reference to an object of type T
. This handles upcasting, downcasting
and casting between interface and interface implementors. All checks are performed at
runtime, while downcast
and upcast
will do many checks at compile-time already. Read more
Casts to T
unconditionally. Read more
Casts to &T
unconditionally. Read more
Returns true
if the object is an instance of (can be cast to) T
.
pub fn set_property<'a, N, V>(
&self,
property_name: N,
value: V
) -> Result<(), BoolError> where
N: Into<&'a str>,
V: ToValue,
pub fn set_property_from_value<'a, N>(
&self,
property_name: N,
value: &Value
) -> Result<(), BoolError> where
N: Into<&'a str>,
pub fn set_properties_from_value(
&self,
property_values: &[(&str, Value)]
) -> Result<(), BoolError>
pub fn has_property<'a, N>(&self, property_name: N, type_: Option<Type>) -> bool where
N: Into<&'a str>,
pub fn find_property<'a, N>(&self, property_name: N) -> Option<ParamSpec> where
N: Into<&'a str>,
Safety Read more
Safety Read more
Safety Read more
Safety Read more
pub fn connect<'a, N, F>(
&self,
signal_name: N,
after: bool,
callback: F
) -> Result<SignalHandlerId, BoolError> where
N: Into<&'a str>,
F: 'static + Fn(&[Value]) -> Option<Value> + Send + Sync,
Same as connect
but takes a SignalId
instead of a signal name.
pub fn connect_local<'a, N, F>(
&self,
signal_name: N,
after: bool,
callback: F
) -> Result<SignalHandlerId, BoolError> where
N: Into<&'a str>,
F: 'static + Fn(&[Value]) -> Option<Value>,
Same as connect_local
but takes a SignalId
instead of a signal name.
pub unsafe fn connect_unsafe<'a, N, F>(
&self,
signal_name: N,
after: bool,
callback: F
) -> Result<SignalHandlerId, BoolError> where
N: Into<&'a str>,
F: Fn(&[Value]) -> Option<Value>,
Same as connect_unsafe
but takes a SignalId
instead of a signal name.
Emit signal by signal id.
Same as emit
but takes Value
for the arguments.
Emit signal by its name.
Same as emit_by_name
but takes Value
for the arguments.
Emit signal with details by signal id.
Same as emit_with_details
but takes Value
for the arguments.
pub fn connect_notify<F>(&self, name: Option<&str>, f: F) -> SignalHandlerId where
F: 'static + Fn(&T, &ParamSpec) + Send + Sync,
pub fn connect_notify_local<F>(
&self,
name: Option<&str>,
f: F
) -> SignalHandlerId where
F: 'static + Fn(&T, &ParamSpec),
pub unsafe fn connect_notify_unsafe<F>(
&self,
name: Option<&str>,
f: F
) -> SignalHandlerId where
F: Fn(&T, &ParamSpec),
pub fn bind_property<'a, O, N, M>(
&'a self,
source_property: N,
target: &'a O,
target_property: M
) -> BindingBuilder<'a> where
O: ObjectType,
N: Into<&'a str>,
M: Into<&'a str>,
Returns a SendValue
clone of self
.