gtkmisc.c 11.4 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 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
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
26 27
#include "gtkcontainer.h"
#include "gtkmisc.h"
Alexander Larsson's avatar
Alexander Larsson committed
28
#include "gtkintl.h"
29
#include "gtkprivate.h"
Elliot Lee's avatar
Elliot Lee committed
30 31


32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/**
 * SECTION:gtkmisc
 * @Short_description: Base class for widgets with alignments and padding
 * @Title: GtkMisc
 *
 * The #GtkMisc widget is an abstract widget which is not useful itself, but
 * is used to derive subclasses which have alignment and padding attributes.
 *
 * The horizontal and vertical padding attributes allows extra space to be
 * added around the widget.
 *
 * The horizontal and vertical alignment attributes enable the widget to be
 * positioned within its allocated area. Note that if the widget is added to
 * a container in such a way that it expands automatically to fill its
 * allocated area, the alignment settings will not alter the widgets position.
 *
 * Note that the desired effect can in most cases be achieved by using the
 * #GtkWidget:halign, #GtkWidget:valign and #GtkWidget:margin properties
 * on the child widget, so GtkMisc should not be used in new code.
 */


54
struct _GtkMiscPrivate
55 56 57 58 59 60 61 62
{
  gfloat        xalign;
  gfloat        yalign;

  guint16       xpad;
  guint16       ypad;
};

63
enum {
Alexander Larsson's avatar
Alexander Larsson committed
64 65 66 67 68
  PROP_0,
  PROP_XALIGN,
  PROP_YALIGN,
  PROP_XPAD,
  PROP_YPAD
69 70
};

Manish Singh's avatar
Manish Singh committed
71 72 73 74 75 76 77 78 79 80 81
static void gtk_misc_realize      (GtkWidget    *widget);
static void gtk_misc_set_property (GObject         *object,
				   guint            prop_id,
				   const GValue    *value,
				   GParamSpec      *pspec);
static void gtk_misc_get_property (GObject         *object,
				   guint            prop_id,
				   GValue          *value,
				   GParamSpec      *pspec);


82
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkMisc, gtk_misc, GTK_TYPE_WIDGET)
Elliot Lee's avatar
Elliot Lee committed
83 84 85 86

static void
gtk_misc_class_init (GtkMiscClass *class)
{
Alexander Larsson's avatar
Alexander Larsson committed
87
  GObjectClass   *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
88 89
  GtkWidgetClass *widget_class;

Alexander Larsson's avatar
Alexander Larsson committed
90
  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
91 92
  widget_class = (GtkWidgetClass*) class;

Alexander Larsson's avatar
Alexander Larsson committed
93 94
  gobject_class->set_property = gtk_misc_set_property;
  gobject_class->get_property = gtk_misc_get_property;
95
  
Elliot Lee's avatar
Elliot Lee committed
96
  widget_class->realize = gtk_misc_realize;
Alexander Larsson's avatar
Alexander Larsson committed
97 98 99 100

  g_object_class_install_property (gobject_class,
                                   PROP_XALIGN,
                                   g_param_spec_float ("xalign",
101
						       P_("X align"),
102
						       P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
Alexander Larsson's avatar
Alexander Larsson committed
103 104 105
						       0.0,
						       1.0,
						       0.5,
106
						       GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
107 108 109 110

  g_object_class_install_property (gobject_class,
                                   PROP_YALIGN,
                                   g_param_spec_float ("yalign",
111 112
						       P_("Y align"),
						       P_("The vertical alignment, from 0 (top) to 1 (bottom)"),
Alexander Larsson's avatar
Alexander Larsson committed
113 114 115
						       0.0,
						       1.0,
						       0.5,
116
						       GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
117 118 119 120

  g_object_class_install_property (gobject_class,
                                   PROP_XPAD,
                                   g_param_spec_int ("xpad",
121 122
						     P_("X pad"),
						     P_("The amount of space to add on the left and right of the widget, in pixels"),
Alexander Larsson's avatar
Alexander Larsson committed
123 124 125
						     0,
						     G_MAXINT,
						     0,
126
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
127 128 129 130

  g_object_class_install_property (gobject_class,
                                   PROP_YPAD,
                                   g_param_spec_int ("ypad",
131 132
						     P_("Y pad"),
						     P_("The amount of space to add on the top and bottom of the widget, in pixels"),
Alexander Larsson's avatar
Alexander Larsson committed
133 134 135
						     0,
						     G_MAXINT,
						     0,
136
						     GTK_PARAM_READWRITE));
Elliot Lee's avatar
Elliot Lee committed
137 138 139 140 141
}

static void
gtk_misc_init (GtkMisc *misc)
{
142
  GtkMiscPrivate *priv;
143

144
  misc->priv = gtk_misc_get_instance_private (misc); 
145 146 147 148 149 150
  priv = misc->priv;

  priv->xalign = 0.5;
  priv->yalign = 0.5;
  priv->xpad = 0;
  priv->ypad = 0;
Elliot Lee's avatar
Elliot Lee committed
151 152
}

153
static void
Alexander Larsson's avatar
Alexander Larsson committed
154 155 156 157
gtk_misc_set_property (GObject      *object,
		       guint         prop_id,
		       const GValue *value,
		       GParamSpec   *pspec)
158
{
159
  GtkMisc *misc = GTK_MISC (object);
160
  GtkMiscPrivate *priv = misc->priv;
161

Alexander Larsson's avatar
Alexander Larsson committed
162
  switch (prop_id)
163
    {
Alexander Larsson's avatar
Alexander Larsson committed
164
    case PROP_XALIGN:
165
      gtk_misc_set_alignment (misc, g_value_get_float (value), priv->yalign);
166
      break;
Alexander Larsson's avatar
Alexander Larsson committed
167
    case PROP_YALIGN:
168
      gtk_misc_set_alignment (misc, priv->xalign, g_value_get_float (value));
169
      break;
Alexander Larsson's avatar
Alexander Larsson committed
170
    case PROP_XPAD:
171
      gtk_misc_set_padding (misc, g_value_get_int (value), priv->ypad);
172
      break;
Alexander Larsson's avatar
Alexander Larsson committed
173
    case PROP_YPAD:
174
      gtk_misc_set_padding (misc, priv->xpad, g_value_get_int (value));
175 176
      break;
    default:
Alexander Larsson's avatar
Alexander Larsson committed
177
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
178 179 180 181 182
      break;
    }
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
183 184 185 186
gtk_misc_get_property (GObject      *object,
		       guint         prop_id,
		       GValue       *value,
		       GParamSpec   *pspec)
187
{
188
  GtkMisc *misc = GTK_MISC (object);
189
  GtkMiscPrivate *priv = misc->priv;
190

Alexander Larsson's avatar
Alexander Larsson committed
191
  switch (prop_id)
192
    {
Alexander Larsson's avatar
Alexander Larsson committed
193
    case PROP_XALIGN:
194
      g_value_set_float (value, priv->xalign);
195
      break;
Alexander Larsson's avatar
Alexander Larsson committed
196
    case PROP_YALIGN:
197
      g_value_set_float (value, priv->yalign);
198
      break;
Alexander Larsson's avatar
Alexander Larsson committed
199
    case PROP_XPAD:
200
      g_value_set_int (value, priv->xpad);
201
      break;
Alexander Larsson's avatar
Alexander Larsson committed
202
    case PROP_YPAD:
203
      g_value_set_int (value, priv->ypad);
204 205
      break;
    default:
Alexander Larsson's avatar
Alexander Larsson committed
206
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
207 208 209 210
      break;
    }
}

211 212 213 214 215 216 217 218
/**
 * gtk_misc_set_alignment:
 * @misc: a #GtkMisc.
 * @xalign: the horizontal alignment, from 0 (left) to 1 (right).
 * @yalign: the vertical alignment, from 0 (top) to 1 (bottom).
 *
 * Sets the alignment of the widget.
 */
Elliot Lee's avatar
Elliot Lee committed
219 220 221 222 223
void
gtk_misc_set_alignment (GtkMisc *misc,
			gfloat   xalign,
			gfloat   yalign)
{
224
  GtkMiscPrivate *priv;
225 226
  GtkWidget *widget;

Elliot Lee's avatar
Elliot Lee committed
227 228
  g_return_if_fail (GTK_IS_MISC (misc));

229 230
  priv = misc->priv;

Elliot Lee's avatar
Elliot Lee committed
231 232 233 234 235 236 237 238 239 240
  if (xalign < 0.0)
    xalign = 0.0;
  else if (xalign > 1.0)
    xalign = 1.0;

  if (yalign < 0.0)
    yalign = 0.0;
  else if (yalign > 1.0)
    yalign = 1.0;

241
  if ((xalign != priv->xalign) || (yalign != priv->yalign))
Elliot Lee's avatar
Elliot Lee committed
242
    {
Matthias Clasen's avatar
Matthias Clasen committed
243
      g_object_freeze_notify (G_OBJECT (misc));
244
      if (xalign != priv->xalign)
Matthias Clasen's avatar
Matthias Clasen committed
245 246
	g_object_notify (G_OBJECT (misc), "xalign");

247
      if (yalign != priv->yalign)
Matthias Clasen's avatar
Matthias Clasen committed
248 249
	g_object_notify (G_OBJECT (misc), "yalign");

250 251
      priv->xalign = xalign;
      priv->yalign = yalign;
252
      
Elliot Lee's avatar
Elliot Lee committed
253
      /* clear the area that was allocated before the change
254
       */
255 256 257
      widget = GTK_WIDGET (misc);
      if (gtk_widget_is_drawable (widget))
        gtk_widget_queue_draw (widget);
Alexander Larsson's avatar
Alexander Larsson committed
258

259
      g_object_thaw_notify (G_OBJECT (misc));
Elliot Lee's avatar
Elliot Lee committed
260 261 262
    }
}

263 264 265
/**
 * gtk_misc_get_alignment:
 * @misc: a #GtkMisc
266 267
 * @xalign: (out) (allow-none): location to store X alignment of @misc, or %NULL
 * @yalign: (out) (allow-none): location to store Y alignment of @misc, or %NULL
268
 *
269 270
 * Gets the X and Y alignment of the widget within its allocation. 
 * See gtk_misc_set_alignment().
271 272 273 274 275 276
 **/
void
gtk_misc_get_alignment (GtkMisc *misc,
		        gfloat  *xalign,
			gfloat  *yalign)
{
277
  GtkMiscPrivate *priv;
278

279 280
  g_return_if_fail (GTK_IS_MISC (misc));

281 282
  priv = misc->priv;

283
  if (xalign)
284
    *xalign = priv->xalign;
285
  if (yalign)
286
    *yalign = priv->yalign;
287 288
}

289 290 291 292 293 294 295 296 297 298
/**
 * gtk_misc_set_padding:
 * @misc: a #GtkMisc.
 * @xpad: the amount of space to add on the left and right of the widget,
 *   in pixels.
 * @ypad: the amount of space to add on the top and bottom of the widget,
 *   in pixels.
 *
 * Sets the amount of space to add around the widget.
 */
Elliot Lee's avatar
Elliot Lee committed
299 300 301 302 303
void
gtk_misc_set_padding (GtkMisc *misc,
		      gint     xpad,
		      gint     ypad)
{
304
  GtkMiscPrivate *priv;
305

Elliot Lee's avatar
Elliot Lee committed
306
  g_return_if_fail (GTK_IS_MISC (misc));
307 308 309

  priv = misc->priv;

Elliot Lee's avatar
Elliot Lee committed
310 311 312 313
  if (xpad < 0)
    xpad = 0;
  if (ypad < 0)
    ypad = 0;
314 315

  if ((xpad != priv->xpad) || (ypad != priv->ypad))
Elliot Lee's avatar
Elliot Lee committed
316
    {
Matthias Clasen's avatar
Matthias Clasen committed
317
      g_object_freeze_notify (G_OBJECT (misc));
318
      if (xpad != priv->xpad)
Matthias Clasen's avatar
Matthias Clasen committed
319 320
	g_object_notify (G_OBJECT (misc), "xpad");

321
      if (ypad != priv->ypad)
Matthias Clasen's avatar
Matthias Clasen committed
322 323
	g_object_notify (G_OBJECT (misc), "ypad");

324 325 326
      priv->xpad = xpad;
      priv->ypad = ypad;

327
      if (gtk_widget_is_drawable (GTK_WIDGET (misc)))
Elliot Lee's avatar
Elliot Lee committed
328
	gtk_widget_queue_resize (GTK_WIDGET (misc));
Alexander Larsson's avatar
Alexander Larsson committed
329

330
      g_object_thaw_notify (G_OBJECT (misc));
Elliot Lee's avatar
Elliot Lee committed
331 332 333
    }
}

334 335 336
/**
 * gtk_misc_get_padding:
 * @misc: a #GtkMisc
337 338 339 340
 * @xpad: (out) (allow-none): location to store padding in the X
 *        direction, or %NULL
 * @ypad: (out) (allow-none): location to store padding in the Y
 *        direction, or %NULL
341
 *
342 343
 * Gets the padding in the X and Y directions of the widget. 
 * See gtk_misc_set_padding().
344 345 346 347 348 349
 **/
void
gtk_misc_get_padding (GtkMisc *misc,
		      gint    *xpad,
		      gint    *ypad)
{
350
  GtkMiscPrivate *priv;
351

352 353
  g_return_if_fail (GTK_IS_MISC (misc));

354 355
  priv = misc->priv;

356
  if (xpad)
357
    *xpad = priv->xpad;
358
  if (ypad)
359
    *ypad = priv->ypad;
360 361
}

Elliot Lee's avatar
Elliot Lee committed
362 363 364
static void
gtk_misc_realize (GtkWidget *widget)
{
365 366
  GtkAllocation allocation;
  GdkWindow *window;
Elliot Lee's avatar
Elliot Lee committed
367 368 369
  GdkWindowAttr attributes;
  gint attributes_mask;

370
  gtk_widget_set_realized (widget, TRUE);
Elliot Lee's avatar
Elliot Lee committed
371

372
  if (!gtk_widget_get_has_window (widget))
Elliot Lee's avatar
Elliot Lee committed
373
    {
374 375 376
      window = gtk_widget_get_parent_window (widget);
      gtk_widget_set_window (widget, window);
      g_object_ref (window);
Elliot Lee's avatar
Elliot Lee committed
377 378 379
    }
  else
    {
380 381
      gtk_widget_get_allocation (widget, &allocation);

Elliot Lee's avatar
Elliot Lee committed
382
      attributes.window_type = GDK_WINDOW_CHILD;
383 384 385 386
      attributes.x = allocation.x;
      attributes.y = allocation.y;
      attributes.width = allocation.width;
      attributes.height = allocation.height;
Elliot Lee's avatar
Elliot Lee committed
387 388 389
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
390
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
Elliot Lee's avatar
Elliot Lee committed
391

392 393
      window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
      gtk_widget_set_window (widget, window);
394
      gtk_widget_register_window (widget, window);
395
      gdk_window_set_background_pattern (window, NULL);
Elliot Lee's avatar
Elliot Lee committed
396 397
    }
}
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

/* Semi-private function used by gtk widgets inheriting from
 * GtkMisc that takes into account both css padding and border
 * and the padding specified with the GtkMisc properties.
 */
void
_gtk_misc_get_padding_and_border (GtkMisc   *misc,
                                  GtkBorder *border)
{
  GtkStyleContext *context;
  GtkStateFlags state;
  GtkBorder tmp;
  gint xpad, ypad;

  g_return_if_fail (GTK_IS_MISC (misc));

  context = gtk_widget_get_style_context (GTK_WIDGET (misc));
  state = gtk_widget_get_state_flags (GTK_WIDGET (misc));

  gtk_style_context_get_padding (context, state, border);

  gtk_misc_get_padding (misc, &xpad, &ypad);
420 421 422 423
  border->top += ypad;
  border->left += xpad;
  border->bottom += ypad;
  border->right += xpad;
424 425 426 427 428 429 430 431

  gtk_style_context_get_border (context, state, &tmp);
  border->top += tmp.top;
  border->right += tmp.right;
  border->bottom += tmp.bottom;
  border->left += tmp.left;
}