mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 01:43:24 +00:00

because it confuses gtk-doc and breaks some links. Also change the "Index of new symbols in GIMP 2.x" sections to be what seems to be the modern standard (looked at the GLib and GTK+ docs), and update some other stuff.
367 lines
12 KiB
C
367 lines
12 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpframe.c
|
|
* Copyright (C) 2004 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* This library 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 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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 library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "gimpwidgetstypes.h"
|
|
|
|
#include "gimpframe.h"
|
|
|
|
|
|
/**
|
|
* SECTION: gimpframe
|
|
* @title: GimpFrame
|
|
* @short_description: A widget providing a HIG-compliant subclass
|
|
* of #GtkFrame.
|
|
*
|
|
* A widget providing a HIG-compliant subclass of #GtkFrame.
|
|
**/
|
|
|
|
|
|
#define DEFAULT_LABEL_SPACING 6
|
|
#define DEFAULT_LABEL_BOLD TRUE
|
|
|
|
#define GIMP_FRAME_INDENT_KEY "gimp-frame-indent"
|
|
#define GIMP_FRAME_IN_EXPANDER_KEY "gimp-frame-in-expander"
|
|
|
|
|
|
static void gimp_frame_size_request (GtkWidget *widget,
|
|
GtkRequisition *requisition);
|
|
static void gimp_frame_size_allocate (GtkWidget *widget,
|
|
GtkAllocation *allocation);
|
|
static void gimp_frame_style_set (GtkWidget *widget,
|
|
GtkStyle *previous);
|
|
static gboolean gimp_frame_expose_event (GtkWidget *widget,
|
|
GdkEventExpose *event);
|
|
static void gimp_frame_child_allocate (GtkFrame *frame,
|
|
GtkAllocation *allocation);
|
|
static void gimp_frame_label_widget_notify (GtkFrame *frame);
|
|
static gint gimp_frame_get_indent (GtkWidget *widget);
|
|
static gint gimp_frame_get_label_spacing (GtkFrame *frame);
|
|
|
|
|
|
G_DEFINE_TYPE (GimpFrame, gimp_frame, GTK_TYPE_FRAME)
|
|
|
|
#define parent_class gimp_frame_parent_class
|
|
|
|
|
|
static void
|
|
gimp_frame_class_init (GimpFrameClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
widget_class->size_request = gimp_frame_size_request;
|
|
widget_class->size_allocate = gimp_frame_size_allocate;
|
|
widget_class->style_set = gimp_frame_style_set;
|
|
widget_class->expose_event = gimp_frame_expose_event;
|
|
|
|
gtk_widget_class_install_style_property (widget_class,
|
|
g_param_spec_boolean ("label-bold",
|
|
NULL, NULL,
|
|
DEFAULT_LABEL_BOLD,
|
|
G_PARAM_READABLE));
|
|
gtk_widget_class_install_style_property (widget_class,
|
|
g_param_spec_int ("label-spacing",
|
|
NULL, NULL,
|
|
0,
|
|
G_MAXINT,
|
|
DEFAULT_LABEL_SPACING,
|
|
G_PARAM_READABLE));
|
|
}
|
|
|
|
|
|
static void
|
|
gimp_frame_init (GimpFrame *frame)
|
|
{
|
|
g_signal_connect (frame, "notify::label-widget",
|
|
G_CALLBACK (gimp_frame_label_widget_notify),
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
gimp_frame_size_request (GtkWidget *widget,
|
|
GtkRequisition *requisition)
|
|
{
|
|
GtkFrame *frame = GTK_FRAME (widget);
|
|
GtkWidget *label_widget = gtk_frame_get_label_widget (frame);
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
|
|
GtkRequisition child_requisition;
|
|
gint border_width;
|
|
|
|
if (label_widget && gtk_widget_get_visible (label_widget))
|
|
{
|
|
gtk_widget_size_request (label_widget, requisition);
|
|
}
|
|
else
|
|
{
|
|
requisition->width = 0;
|
|
requisition->height = 0;
|
|
}
|
|
|
|
requisition->height += gimp_frame_get_label_spacing (frame);
|
|
|
|
if (child && gtk_widget_get_visible (child))
|
|
{
|
|
gint indent = gimp_frame_get_indent (widget);
|
|
|
|
gtk_widget_size_request (child, &child_requisition);
|
|
|
|
requisition->width = MAX (requisition->width,
|
|
child_requisition.width + indent);
|
|
requisition->height += child_requisition.height;
|
|
}
|
|
|
|
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
|
|
|
|
requisition->width += 2 * border_width;
|
|
requisition->height += 2 * border_width;
|
|
}
|
|
|
|
static void
|
|
gimp_frame_size_allocate (GtkWidget *widget,
|
|
GtkAllocation *allocation)
|
|
{
|
|
GtkFrame *frame = GTK_FRAME (widget);
|
|
GtkWidget *label_widget = gtk_frame_get_label_widget (frame);
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
|
|
GtkAllocation child_allocation;
|
|
|
|
gtk_widget_set_allocation (widget, allocation);
|
|
|
|
gimp_frame_child_allocate (frame, &child_allocation);
|
|
|
|
if (child && gtk_widget_get_visible (child))
|
|
gtk_widget_size_allocate (child, &child_allocation);
|
|
|
|
if (label_widget && gtk_widget_get_visible (label_widget))
|
|
{
|
|
GtkAllocation label_allocation;
|
|
GtkRequisition label_requisition;
|
|
gint border_width;
|
|
|
|
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
|
|
|
|
gtk_widget_get_child_requisition (label_widget, &label_requisition);
|
|
|
|
label_allocation.x = allocation->x + border_width;
|
|
label_allocation.y = allocation->y + border_width;
|
|
label_allocation.width = MAX (label_requisition.width,
|
|
allocation->width - 2 * border_width);
|
|
label_allocation.height = label_requisition.height;
|
|
|
|
gtk_widget_size_allocate (label_widget, &label_allocation);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_frame_child_allocate (GtkFrame *frame,
|
|
GtkAllocation *child_allocation)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (frame);
|
|
GtkWidget *label_widget = gtk_frame_get_label_widget (frame);
|
|
GtkAllocation allocation;
|
|
gint border_width;
|
|
gint spacing = 0;
|
|
gint indent = gimp_frame_get_indent (widget);
|
|
|
|
gtk_widget_get_allocation (widget, &allocation);
|
|
|
|
border_width = gtk_container_get_border_width (GTK_CONTAINER (frame));
|
|
|
|
if (label_widget && gtk_widget_get_visible (label_widget))
|
|
{
|
|
GtkRequisition child_requisition;
|
|
|
|
gtk_widget_get_child_requisition (label_widget, &child_requisition);
|
|
spacing += child_requisition.height;
|
|
}
|
|
|
|
spacing += gimp_frame_get_label_spacing (frame);
|
|
|
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
|
child_allocation->x = border_width + indent;
|
|
else
|
|
child_allocation->x = border_width;
|
|
|
|
child_allocation->y = border_width + spacing;
|
|
child_allocation->width = MAX (1,
|
|
allocation.width - 2 * border_width - indent);
|
|
child_allocation->height = MAX (1,
|
|
allocation.height -
|
|
child_allocation->y - border_width);
|
|
|
|
child_allocation->x += allocation.x;
|
|
child_allocation->y += allocation.y;
|
|
}
|
|
|
|
static void
|
|
gimp_frame_style_set (GtkWidget *widget,
|
|
GtkStyle *previous)
|
|
{
|
|
/* font changes invalidate the indentation */
|
|
g_object_set_data (G_OBJECT (widget), GIMP_FRAME_INDENT_KEY, NULL);
|
|
|
|
/* for "label_bold" */
|
|
gimp_frame_label_widget_notify (GTK_FRAME (widget));
|
|
}
|
|
|
|
static gboolean
|
|
gimp_frame_expose_event (GtkWidget *widget,
|
|
GdkEventExpose *event)
|
|
{
|
|
if (gtk_widget_is_drawable (widget))
|
|
{
|
|
GtkWidgetClass *widget_class = g_type_class_peek_parent (parent_class);
|
|
|
|
return widget_class->expose_event (widget, event);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gimp_frame_label_widget_notify (GtkFrame *frame)
|
|
{
|
|
GtkWidget *label_widget = gtk_frame_get_label_widget (frame);
|
|
|
|
if (label_widget)
|
|
{
|
|
GtkLabel *label = NULL;
|
|
|
|
if (GTK_IS_LABEL (label_widget))
|
|
{
|
|
gfloat xalign, yalign;
|
|
|
|
label = GTK_LABEL (label_widget);
|
|
|
|
gtk_frame_get_label_align (frame, &xalign, &yalign);
|
|
gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign);
|
|
}
|
|
else if (GTK_IS_BIN (label_widget))
|
|
{
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (label_widget));
|
|
|
|
if (GTK_IS_LABEL (child))
|
|
label = GTK_LABEL (child);
|
|
}
|
|
|
|
if (label)
|
|
{
|
|
PangoAttrList *attrs = pango_attr_list_new ();
|
|
PangoAttribute *attr;
|
|
gboolean bold;
|
|
|
|
gtk_widget_style_get (GTK_WIDGET (frame), "label_bold", &bold, NULL);
|
|
|
|
attr = pango_attr_weight_new (bold ?
|
|
PANGO_WEIGHT_BOLD :
|
|
PANGO_WEIGHT_NORMAL);
|
|
attr->start_index = 0;
|
|
attr->end_index = -1;
|
|
pango_attr_list_insert (attrs, attr);
|
|
|
|
gtk_label_set_attributes (label, attrs);
|
|
|
|
pango_attr_list_unref (attrs);
|
|
}
|
|
}
|
|
}
|
|
|
|
static gint
|
|
gimp_frame_get_indent (GtkWidget *widget)
|
|
{
|
|
gint width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
GIMP_FRAME_INDENT_KEY));
|
|
|
|
if (! width)
|
|
{
|
|
PangoLayout *layout;
|
|
|
|
/* the HIG suggests to use four spaces so do just that */
|
|
layout = gtk_widget_create_pango_layout (widget, " ");
|
|
pango_layout_get_pixel_size (layout, &width, NULL);
|
|
g_object_unref (layout);
|
|
|
|
g_object_set_data (G_OBJECT (widget),
|
|
GIMP_FRAME_INDENT_KEY, GINT_TO_POINTER (width));
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
static gint
|
|
gimp_frame_get_label_spacing (GtkFrame *frame)
|
|
{
|
|
GtkWidget *label_widget = gtk_frame_get_label_widget (frame);
|
|
gint spacing = 0;
|
|
|
|
if ((label_widget && gtk_widget_get_visible (label_widget)) ||
|
|
(g_object_get_data (G_OBJECT (frame), GIMP_FRAME_IN_EXPANDER_KEY)))
|
|
{
|
|
gtk_widget_style_get (GTK_WIDGET (frame),
|
|
"label_spacing", &spacing,
|
|
NULL);
|
|
}
|
|
|
|
return spacing;
|
|
}
|
|
|
|
/**
|
|
* gimp_frame_new:
|
|
* @label: text to set as the frame's title label (or %NULL for no title)
|
|
*
|
|
* Creates a #GimpFrame widget. A #GimpFrame is a HIG-compliant
|
|
* variant of #GtkFrame. It doesn't render a frame at all but
|
|
* otherwise behaves like a frame. The frame's title is rendered in
|
|
* bold and the frame content is indented four spaces as suggested by
|
|
* the GNOME HIG (see http://developer.gnome.org/projects/gup/hig/).
|
|
*
|
|
* Return value: a new #GimpFrame widget
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
GtkWidget *
|
|
gimp_frame_new (const gchar *label)
|
|
{
|
|
GtkWidget *frame;
|
|
gboolean expander = FALSE;
|
|
|
|
/* somewhat hackish, should perhaps be an object property of GimpFrame */
|
|
if (label && strcmp (label, "<expander>") == 0)
|
|
{
|
|
expander = TRUE;
|
|
label = NULL;
|
|
}
|
|
|
|
frame = g_object_new (GIMP_TYPE_FRAME,
|
|
"label", label,
|
|
NULL);
|
|
|
|
if (expander)
|
|
g_object_set_data (G_OBJECT (frame),
|
|
GIMP_FRAME_IN_EXPANDER_KEY, (gpointer) TRUE);
|
|
|
|
return frame;
|
|
}
|