Package org.gnome.gtk

Class Widget

java.lang.Object
All Implemented Interfaces:
Proxy, Accessible, Buildable, ConstraintTarget
Direct Known Subclasses:
Actionable.ActionableImpl, ActionBar, AppChooser.AppChooserImpl, AppChooserButton, AppChooserWidget, AspectFrame, Avatar, Banner, Bin, BottomSheet, Box, BreakpointBin, Button, ButtonContent, Calendar, Carousel, CarouselIndicatorDots, CarouselIndicatorLines, CellEditable.CellEditableImpl, CellView, CenterBox, CheckButton, Clamp, ClampScrollable, ColorButton, ColorChooserWidget, ColorDialogButton, ColumnView, ComboBox, CompletionCell, Dialog, DragIcon, DrawingArea, DropDown, Editable.EditableImpl, EditableLabel, Entry, Expander, FileChooserWidget, Fixed, Flap, FlowBox, FlowBoxChild, FontButton, FontChooserWidget, FontDialogButton, Frame, GLArea, GraphicsOffload, Grid, Gutter, GutterRenderer, HeaderBar, HeaderBar, HoverDisplay, IconView, Image, InfoBar, Inscription, Label, LayoutSlot, Leaflet, LevelBar, ListBase, ListBox, ListBoxRow, MediaControls, MenuButton, MultiLayoutView, Native.NativeImpl, NavigationPage, NavigationSplitView, NavigationView, Notebook, Overlay, OverlaySplitView, Paned, PasswordEntry, Picture, Popover, PopoverMenuBar, PreferencesGroup, PreferencesPage, ProgressBar, Range, Revealer, Root.RootImpl, ScaleButton, Scrollbar, ScrolledWindow, SearchBar, SearchEntry, Separator, ShortcutLabel, ShortcutsShortcut, SpinButton, Spinner, Spinner, SplitButton, Squeezer, Stack, StackSidebar, StackSwitcher, Statusbar, StatusPage, StyleSchemeChooserWidget, StyleSchemePreview, Swipeable.SwipeableImpl, Switch, TabBar, TabButton, TabOverview, TabView, Text, TextView, ToastOverlay, ToolbarView, TreeExpander, TreeView, Video, Viewport, ViewStack, ViewSwitcher, ViewSwitcherBar, ViewSwitcherTitle, WebViewBase, Widget.WidgetImpl, Window, WindowControls, WindowHandle, WindowTitle

@Generated("io.github.jwharm.JavaGI") public abstract class Widget extends InitiallyUnowned implements Accessible, Buildable, ConstraintTarget
The base class for all widgets.

GtkWidget 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:

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 GtkWidget subclass that supports height-for-width or width-for-height geometry management for itself or its child widgets, the getRequestMode() virtual function must be implemented as well and return the widget's preferred request mode. The default implementation of this virtual function returns SizeRequestMode.CONSTANT_SIZE, which means that the widget will only ever get -1 passed as the for_size value to its measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) 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 Gtk.SizeRequestMode chosen by the toplevel.

For example, when queried in the normal SizeRequestMode.HEIGHT_FOR_WIDTH mode:

First, the default minimum and natural width for each widget in the interface will be computed using measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) 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 measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) 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 Window.setDefaultSize(int, int)). 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 GtkWidget 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, GtkWidget 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 GtkSizeRequestModes 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 measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) 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.HEIGHT_FOR_WIDTH widget generally deals with width-for-height requests:

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 measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) inside your own sizeAllocate(org.gnome.gtk.Allocation, int) 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 measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>); 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 using baselines, 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 measure(org.gnome.gtk.Orientation, int, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>, io.github.jwharm.javagi.base.Out<java.lang.Integer>) 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 getBaseline(). 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 GtkWidget implementation of the GtkBuildable interface supports various custom elements to specify additional aspects of widgets that are not directly expressed as properties.

If the widget uses a LayoutManager, GtkWidget 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>
 

GtkWidget 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>
 

GtkWidget 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 GtkBuilder XML, one must associate the interface description with the widget class at class initialization time using WidgetClass#setTemplate.

The interface description semantics expected in composite template descriptions is slightly different from regular GtkBuilder XML.

Unlike regular interface descriptions, WidgetClass#setTemplate will expect a <template> tag as a direct child of the toplevel <interface> tag. The <template> 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 GtkBuilder but can be used by UI design tools 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.

Since, unlike the <object> tag, the <template> tag does not contain an “id” attribute, if you need to refer to the instance of the object itself that the template will create, simply refer to the template class name in an applicable element content.

Here is an example of a template definition, which includes an example of this in the <signal> tag:

<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 WidgetClass#setTemplateFromResource from the class initialization of your GtkWidget type:

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 initTemplate() from the instance initialization function:

static void
 foo_widget_init (FooWidget *self)
 {
   gtk_widget_init_template (GTK_WIDGET (self));

   // Initialize the rest of the widget...
 }
 

as well as calling disposeTemplate(org.gnome.glib.Type) from the dispose function:

static void
 foo_widget_dispose (GObject *gobject)
 {
   FooWidget *self = FOO_WIDGET (gobject);

   // Dispose objects for which you have a reference...

   // Clear the template children for this widget type
   gtk_widget_dispose_template (GTK_WIDGET (self), FOO_TYPE_WIDGET);

   G_OBJECT_CLASS (foo_widget_parent_class)->dispose (gobject);
 }
 

You can access widgets defined in the template using the getTemplateChild(org.gnome.glib.Type, java.lang.String) 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 WidgetClass#bindTemplateChildFull (or one of its wrapper macros Gtk#widgetClassBindTemplateChild and Gtk#widgetClassBindTemplateChildPrivate) with that name, e.g.

typedef struct {
   GtkWidget *hello_button;
   GtkWidget *goodbye_button;
 } FooWidgetPrivate;

 G_DEFINE_TYPE_WITH_PRIVATE (FooWidget, foo_widget, GTK_TYPE_BOX)

 static void
 foo_widget_dispose (GObject *gobject)
 {
   gtk_widget_dispose_template (GTK_WIDGET (gobject), FOO_TYPE_WIDGET);

   G_OBJECT_CLASS (foo_widget_parent_class)->dispose (gobject);
 }

 static void
 foo_widget_class_init (FooWidgetClass *klass)
 {
   // ...
   G_OBJECT_CLASS (klass)->dispose = foo_widget_dispose;

   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)
 {
   gtk_widget_init_template (GTK_WIDGET (widget));
 }
 

You can also use WidgetClass#bindTemplateCallbackFull (or is wrapper macro Gtk#widgetClassBindTemplateCallback) to connect a signal callback defined in the template with a function visible in the scope of the class, e.g.

// 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);
 }