Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gtkcenterbox.c

  Sprache: C
 

/*
 * Copyright (c) 2017 Timm Bäder <mail@baedert.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Author: Timm Bäder <mail@baedert.org>
 */


/**
 * GtkCenterBox:
 *
 * Arranges three children in a row, keeping the middle child
 * centered as well as possible.
 *
 * <picture>
 *   <source srcset="centerbox-dark.png" media="(prefers-color-scheme: dark)">
 *   <img alt="An example GtkCenterBox" src="centerbox.png">
 * </picture>
 *
 * To add children to `GtkCenterBox`, use [method@Gtk.CenterBox.set_start_widget],
 * [method@Gtk.CenterBox.set_center_widget] and
 * [method@Gtk.CenterBox.set_end_widget].
 *
 * The sizing and positioning of children can be influenced with the
 * align and expand properties of the children.
 *
 * # GtkCenterBox as GtkBuildable
 *
 * The `GtkCenterBox` implementation of the `GtkBuildable` interface
 * supports placing children in the 3 positions by specifying start, center
 * or end as the type attribute of a `<child>` element.
 *
 * # CSS nodes
 *
 * `GtkCenterBox` uses a single CSS node with the name box,
 *
 * The first child of the `GtkCenterBox` will be allocated depending on the
 * text direction, i.e. in left-to-right layouts it will be allocated on the
 * left and in right-to-left layouts on the right.
 *
 * In vertical orientation, the nodes of the children are arranged from top to
 * bottom.
 *
 * # Accessibility
 *
 * Until GTK 4.10, `GtkCenterBox` used the [enum@Gtk.AccessibleRole.group] role.
 *
 * Starting from GTK 4.12, `GtkCenterBox` uses the [enum@Gtk.AccessibleRole.generic]
 * role.
 */


#include "config.h"
#include "gtkcenterbox.h"
#include "gtkcenterlayout.h"
#include "gtkwidgetprivate.h"
#include "gtkorientable.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtksizerequest.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"

struct _GtkCenterBox
{
  GtkWidget parent_instance;

  GtkWidget *start_widget;
  GtkWidget *center_widget;
  GtkWidget *end_widget;
};

struct _GtkCenterBoxClass
{
  GtkWidgetClass parent_class;
};


enum {
  PROP_0,
  PROP_START_WIDGET,
  PROP_CENTER_WIDGET,
  PROP_END_WIDGET,
  PROP_BASELINE_POSITION,
  PROP_SHRINK_CENTER_LAST,
  /* GtkOrientable */
  PROP_ORIENTATION,
  LAST_PROP,
};

static GParamSpec *props[LAST_PROP] = { NULL, };

static GtkBuildableIface *parent_buildable_iface;

static void gtk_center_box_buildable_init (GtkBuildableIface *iface);

G_DEFINE_TYPE_WITH_CODE (GtkCenterBox, gtk_center_box, GTK_TYPE_WIDGET,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_center_box_buildable_init))

static void
gtk_center_box_buildable_add_child (GtkBuildable  *buildable,
                                    GtkBuilder    *builder,
                                    GObject       *child,
                                    const char    *type)
{
  if (g_strcmp0 (type, "start") == 0)
    {
      gtk_buildable_child_deprecation_warning (buildable, builder, "start""start-widget");
      gtk_center_box_set_start_widget (GTK_CENTER_BOX (buildable), GTK_WIDGET (child));
    }
  else if (g_strcmp0 (type, "center") == 0)
    {
      gtk_buildable_child_deprecation_warning (buildable, builder, "center""center-widget");
      gtk_center_box_set_center_widget (GTK_CENTER_BOX (buildable), GTK_WIDGET (child));
    }
  else if (g_strcmp0 (type, "end") == 0)
    {
      gtk_buildable_child_deprecation_warning (buildable, builder, "end""end-widget");
      gtk_center_box_set_end_widget (GTK_CENTER_BOX (buildable), GTK_WIDGET (child));
    }
  else
    {
      parent_buildable_iface->add_child (buildable, builder, child, type);
    }
}

static void
gtk_center_box_buildable_init (GtkBuildableIface *iface)
{
  parent_buildable_iface = g_type_interface_peek_parent (iface);

  iface->add_child = gtk_center_box_buildable_add_child;
}

static void
gtk_center_box_set_property (GObject      *object,
                             guint         prop_id,
                             const GValue *value,
                             GParamSpec   *pspec)
{
  GtkCenterBox *self = GTK_CENTER_BOX (object);
  GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (object));

  switch (prop_id)
    {
    case PROP_BASELINE_POSITION:
      gtk_center_box_set_baseline_position (self, g_value_get_enum (value));
      break;

    case PROP_ORIENTATION:
      {
        GtkOrientation orientation = g_value_get_enum (value);
        GtkOrientation current = gtk_center_layout_get_orientation (GTK_CENTER_LAYOUT (layout));
        if (current != orientation)
          {
            gtk_center_layout_set_orientation (GTK_CENTER_LAYOUT (layout), orientation);
            gtk_widget_update_orientation (GTK_WIDGET (self), orientation);
            gtk_widget_queue_resize (GTK_WIDGET (self));
            g_object_notify_by_pspec (object, props[PROP_ORIENTATION]);
          }
      }
      break;

    case PROP_START_WIDGET:
      gtk_center_box_set_start_widget (self, GTK_WIDGET (g_value_get_object (value)));
      break;

    case PROP_CENTER_WIDGET:
      gtk_center_box_set_center_widget (self, GTK_WIDGET (g_value_get_object (value)));
      break;

    case PROP_END_WIDGET:
      gtk_center_box_set_end_widget (self, GTK_WIDGET (g_value_get_object (value)));
      break;

    case PROP_SHRINK_CENTER_LAST:
      gtk_center_box_set_shrink_center_last (self, g_value_get_boolean (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_center_box_get_property (GObject    *object,
                             guint       prop_id,
                             GValue     *value,
                             GParamSpec *pspec)
{
  GtkCenterBox *self = GTK_CENTER_BOX (object);
  GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (object));

  switch (prop_id)
    {
    case PROP_BASELINE_POSITION:
      g_value_set_enum (value, gtk_center_layout_get_baseline_position (GTK_CENTER_LAYOUT (layout)));
      break;

    case PROP_ORIENTATION:
      g_value_set_enum (value, gtk_center_layout_get_orientation (GTK_CENTER_LAYOUT (layout)));
      break;

    case PROP_START_WIDGET:
      g_value_set_object (value, self->start_widget);
      break;

    case PROP_CENTER_WIDGET:
      g_value_set_object (value, self->center_widget);
      break;

    case PROP_END_WIDGET:
      g_value_set_object (value, self->end_widget);
      break;

    case PROP_SHRINK_CENTER_LAST:
      g_value_set_boolean (value, gtk_center_layout_get_shrink_center_last (GTK_CENTER_LAYOUT (layout)));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_center_box_dispose (GObject *object)
{
  GtkCenterBox *self = GTK_CENTER_BOX (object);

  g_clear_pointer (&self->start_widget, gtk_widget_unparent);
  g_clear_pointer (&self->center_widget, gtk_widget_unparent);
  g_clear_pointer (&self->end_widget, gtk_widget_unparent);

  G_OBJECT_CLASS (gtk_center_box_parent_class)->dispose (object);
}

static void
gtk_center_box_class_init (GtkCenterBoxClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
  gpointer iface;

  object_class->set_property = gtk_center_box_set_property;
  object_class->get_property = gtk_center_box_get_property;
  object_class->dispose = gtk_center_box_dispose;

  /**
   * GtkCenterBox:baseline-position:
   *
   * The position of the baseline aligned widget if extra space is available.
   */

  props[PROP_BASELINE_POSITION] =
      g_param_spec_enum ("baseline-position", NULL, NULL,
                         GTK_TYPE_BASELINE_POSITION,
                         GTK_BASELINE_POSITION_CENTER,
                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /**
   * GtkCenterBox:start-widget:
   *
   * The widget that is placed at the start position.
   *
   * In vertical orientation, the start position is at the top.
   * In horizontal orientation, the start position is at the leading
   * edge with respect to the text direction.
   *
   * Since: 4.10
   */

  props[PROP_START_WIDGET] =
      g_param_spec_object ("start-widget", NULL, NULL,
                           GTK_TYPE_WIDGET,
                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /**
   * GtkCenterBox:center-widget:
   *
   * The widget that is placed at the center position.
   *
   * Since: 4.10
   */

  props[PROP_CENTER_WIDGET] =
      g_param_spec_object ("center-widget", NULL, NULL,
                           GTK_TYPE_WIDGET,
                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /**
   * GtkCenterBox:end-widget:
   *
   * The widget that is placed at the end position.
   *
   * In vertical orientation, the end position is at the bottom.
   * In horizontal orientation, the end position is at the trailing
   * edge with respect to the text direction.
   *
   * Since: 4.10
   */

  props[PROP_END_WIDGET] =
      g_param_spec_object ("end-widget", NULL, NULL,
                           GTK_TYPE_WIDGET,
                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /**
   * GtkCenterBox:shrink-center-last:
   *
   * Whether to shrink the center widget after other children.
   *
   * By default, when there's no space to give all three children their
   * natural widths, the start and end widgets start shrinking and the
   * center child keeps natural width until they reach minimum width.
   *
   * If false, start and end widgets keep natural width and the
   * center widget starts shrinking instead.
   *
   * Since: 4.12
   */

  props[PROP_SHRINK_CENTER_LAST] =
      g_param_spec_boolean ("shrink-center-last", NULL, NULL,
                            TRUE,
                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /* GtkOrientable */
  iface = g_type_default_interface_peek (GTK_TYPE_ORIENTABLE);
  props[PROP_ORIENTATION] =
      g_param_spec_override ("orientation",
                             g_object_interface_find_property (iface, "orientation"));

  g_object_class_install_properties (object_class, LAST_PROP, props);

  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CENTER_LAYOUT);
  gtk_widget_class_set_css_name (widget_class, I_("box"));
  gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC);
}

static void
gtk_center_box_init (GtkCenterBox *self)
{
  self->start_widget = NULL;
  self->center_widget = NULL;
  self->end_widget = NULL;
}

/**
 * gtk_center_box_new:
 *
 * Creates a new `GtkCenterBox`.
 *
 * Returns: the new `GtkCenterBox`
 */

GtkWidget *
gtk_center_box_new (void)
{
  return GTK_WIDGET (g_object_new (GTK_TYPE_CENTER_BOX, NULL));
}

/**
 * gtk_center_box_set_start_widget:
 * @self: a center box
 * @child: (nullable): the new start widget
 *
 * Sets the start widget.
 *
 * To remove the existing start widget, pass `NULL`.
 */

void
gtk_center_box_set_start_widget (GtkCenterBox *self,
                                 GtkWidget    *child)
{
  GtkLayoutManager *layout_manager;

  g_return_if_fail (GTK_IS_CENTER_BOX (self));
  g_return_if_fail (child == NULL || self->start_widget == child || gtk_widget_get_parent (child) == NULL);

  if (self->start_widget == child)
    return;

  if (self->start_widget)
    gtk_widget_unparent (self->start_widget);

  self->start_widget = child;
  if (child)
    gtk_widget_insert_after (child, GTK_WIDGET (self), NULL);

  layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
  gtk_center_layout_set_start_widget (GTK_CENTER_LAYOUT (layout_manager), child);

  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_START_WIDGET]);
}

/**
 * gtk_center_box_set_center_widget:
 * @self: a center box
 * @child: (nullable): the new center widget
 *
 * Sets the center widget.
 *
 * To remove the existing center widget, pass `NULL`.
 */

void
gtk_center_box_set_center_widget (GtkCenterBox *self,
                                  GtkWidget    *child)
{
  GtkLayoutManager *layout_manager;

  g_return_if_fail (GTK_IS_CENTER_BOX (self));
  g_return_if_fail (child == NULL || self->center_widget == child || gtk_widget_get_parent (child) == NULL);

  if (self->center_widget == child)
    return;

  if (self->center_widget)
    gtk_widget_unparent (self->center_widget);

  self->center_widget = child;
  if (child)
    gtk_widget_insert_after (child, GTK_WIDGET (self), self->start_widget);

  layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
  gtk_center_layout_set_center_widget (GTK_CENTER_LAYOUT (layout_manager), child);

  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CENTER_WIDGET]);
}

/**
 * gtk_center_box_set_end_widget:
 * @self: a center box
 * @child: (nullable): the new end widget
 *
 * Sets the end widget.
 *
 * To remove the existing end widget, pass `NULL`.
 */

void
gtk_center_box_set_end_widget (GtkCenterBox *self,
                               GtkWidget    *child)
{
  GtkLayoutManager *layout_manager;

  g_return_if_fail (GTK_IS_CENTER_BOX (self));
  g_return_if_fail (child == NULL || self->end_widget == child || gtk_widget_get_parent (child) == NULL);

  if (self->end_widget == child)
    return;

  if (self->end_widget)
    gtk_widget_unparent (self->end_widget);

  self->end_widget = child;
  if (child)
    gtk_widget_insert_before (child, GTK_WIDGET (self), NULL);

  layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
  gtk_center_layout_set_end_widget (GTK_CENTER_LAYOUT (layout_manager), child);

  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_END_WIDGET]);
}

/**
 * gtk_center_box_get_start_widget:
 * @self: a center box
 *
 * Gets the start widget.
 *
 * Returns: (transfer none) (nullable): the start widget
 */

GtkWidget *
gtk_center_box_get_start_widget (GtkCenterBox *self)
{
  return self->start_widget;
}

/**
 * gtk_center_box_get_center_widget:
 * @self: a center box
 *
 * Gets the center widget.
 *
 * Returns: (transfer none) (nullable): the center widget
 */

GtkWidget *
gtk_center_box_get_center_widget (GtkCenterBox *self)
{
  return self->center_widget;
}

/**
 * gtk_center_box_get_end_widget:
 * @self: a center box
 *
 * Gets the end widget.
 *
 * Returns: (transfer none) (nullable): the end widget
 */

GtkWidget *
gtk_center_box_get_end_widget (GtkCenterBox *self)
{
  return self->end_widget;
}

/**
 * gtk_center_box_set_baseline_position:
 * @self: a center box
 * @position: the baseline position
 *
 * Sets the baseline position of a center box.
 *
 * This affects only horizontal boxes with at least one baseline
 * aligned child. If there is more vertical space available than
 * requested, and the baseline is not allocated by the parent then
 * @position is used to allocate the baseline with respect to the
 * extra space available.
 */

void
gtk_center_box_set_baseline_position (GtkCenterBox        *self,
                                      GtkBaselinePosition  position)
{
  GtkBaselinePosition current_position;
  GtkLayoutManager *layout;

  g_return_if_fail (GTK_IS_CENTER_BOX (self));

  layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
  current_position = gtk_center_layout_get_baseline_position (GTK_CENTER_LAYOUT (layout));
  if (current_position != position)
    {
      gtk_center_layout_set_baseline_position (GTK_CENTER_LAYOUT (layout), position);
      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_BASELINE_POSITION]);
      gtk_widget_queue_resize (GTK_WIDGET (self));
    }
}

/**
 * gtk_center_box_get_baseline_position:
 * @self: a center box
 *
 * Gets the baseline position of the center box.
 *
 * See [method@Gtk.CenterBox.set_baseline_position].
 *
 * Returns: the baseline position
 */

GtkBaselinePosition
gtk_center_box_get_baseline_position (GtkCenterBox *self)
{
  GtkLayoutManager *layout;

  g_return_val_if_fail (GTK_IS_CENTER_BOX (self), GTK_BASELINE_POSITION_CENTER);

  layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));

  return gtk_center_layout_get_baseline_position (GTK_CENTER_LAYOUT (layout));
}

/**
 * gtk_center_box_set_shrink_center_last:
 * @self: a cener box
 * @shrink_center_last: whether to shrink the center widget after others
 *
 * Sets whether to shrink the center widget after other children.
 *
 * By default, when there's no space to give all three children their
 * natural widths, the start and end widgets start shrinking and the
 * center child keeps natural width until they reach minimum width.
 *
 * If @shrink_center_last is false, start and end widgets keep natural
 * width and the center widget starts shrinking instead.
 *
 * Since: 4.12
 */

void
gtk_center_box_set_shrink_center_last (GtkCenterBox *self,
                                       gboolean      shrink_center_last)
{
  GtkLayoutManager *layout;
  gboolean current_shrink_center_last;

  g_return_if_fail (GTK_IS_CENTER_BOX (self));

  shrink_center_last = !!shrink_center_last;

  layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
  current_shrink_center_last = gtk_center_layout_get_shrink_center_last (GTK_CENTER_LAYOUT (layout));
  if (current_shrink_center_last != shrink_center_last)
    {
      gtk_center_layout_set_shrink_center_last (GTK_CENTER_LAYOUT (layout), shrink_center_last);
      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SHRINK_CENTER_LAST]);
      gtk_widget_queue_allocate (GTK_WIDGET (self));
    }
}

/**
 * gtk_center_box_get_shrink_center_last:
 * @self: a center box
 *
 * Gets whether the center widget shrinks after other children.
 *
 * Returns: whether to shrink the center widget after others
 *
 * Since: 4.12
 */

gboolean
gtk_center_box_get_shrink_center_last (GtkCenterBox *self)
{
  GtkLayoutManager *layout;

  g_return_val_if_fail (GTK_IS_CENTER_BOX (self), FALSE);

  layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));

  return gtk_center_layout_get_shrink_center_last (GTK_CENTER_LAYOUT (layout));
}

Messung V0.5 in Prozent
C=97 H=91 G=93

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik