gtkmisc.c 11.5 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 54 55
/**
 * 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>
 * 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.
 * </note>
 */


56
struct _GtkMiscPrivate
57 58 59 60 61 62 63 64
{
  gfloat        xalign;
  gfloat        yalign;

  guint16       xpad;
  guint16       ypad;
};

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

Manish Singh's avatar
Manish Singh committed
73 74 75 76 77 78 79 80 81 82 83
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);


Matthias Clasen's avatar
Matthias Clasen committed
84
G_DEFINE_ABSTRACT_TYPE (GtkMisc, gtk_misc, GTK_TYPE_WIDGET)
Elliot Lee's avatar
Elliot Lee committed
85 86 87 88

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

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

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

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

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

  g_object_class_install_property (gobject_class,
                                   PROP_XPAD,
                                   g_param_spec_int ("xpad",
123 124
						     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
125 126 127
						     0,
						     G_MAXINT,
						     0,
128
						     GTK_PARAM_READWRITE));
Alexander Larsson's avatar
Alexander Larsson committed
129 130 131 132

  g_object_class_install_property (gobject_class,
                                   PROP_YPAD,
                                   g_param_spec_int ("ypad",
133 134
						     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
135 136 137
						     0,
						     G_MAXINT,
						     0,
138
						     GTK_PARAM_READWRITE));
139

140
  g_type_class_add_private (class, sizeof (GtkMiscPrivate));
Elliot Lee's avatar
Elliot Lee committed
141 142 143 144 145
}

static void
gtk_misc_init (GtkMisc *misc)
{
146
  GtkMiscPrivate *priv;
147 148 149

  misc->priv = G_TYPE_INSTANCE_GET_PRIVATE (misc,
                                            GTK_TYPE_MISC,
150
                                            GtkMiscPrivate);
151 152 153 154 155 156
  priv = misc->priv;

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

159
static void
Alexander Larsson's avatar
Alexander Larsson committed
160 161 162 163
gtk_misc_set_property (GObject      *object,
		       guint         prop_id,
		       const GValue *value,
		       GParamSpec   *pspec)
164
{
165
  GtkMisc *misc = GTK_MISC (object);
166
  GtkMiscPrivate *priv = misc->priv;
167

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

static void
Alexander Larsson's avatar
Alexander Larsson committed
189 190 191 192
gtk_misc_get_property (GObject      *object,
		       guint         prop_id,
		       GValue       *value,
		       GParamSpec   *pspec)
193
{
194
  GtkMisc *misc = GTK_MISC (object);
195
  GtkMiscPrivate *priv = misc->priv;
196

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

217 218 219 220 221 222 223 224
/**
 * 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
225 226 227 228 229
void
gtk_misc_set_alignment (GtkMisc *misc,
			gfloat   xalign,
			gfloat   yalign)
{
230
  GtkMiscPrivate *priv;
231 232
  GtkWidget *widget;

Elliot Lee's avatar
Elliot Lee committed
233 234
  g_return_if_fail (GTK_IS_MISC (misc));

235 236
  priv = misc->priv;

Elliot Lee's avatar
Elliot Lee committed
237 238 239 240 241 242 243 244 245 246
  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;

247
  if ((xalign != priv->xalign) || (yalign != priv->yalign))
Elliot Lee's avatar
Elliot Lee committed
248
    {
Matthias Clasen's avatar
Matthias Clasen committed
249
      g_object_freeze_notify (G_OBJECT (misc));
250
      if (xalign != priv->xalign)
Matthias Clasen's avatar
Matthias Clasen committed
251 252
	g_object_notify (G_OBJECT (misc), "xalign");

253
      if (yalign != priv->yalign)
Matthias Clasen's avatar
Matthias Clasen committed
254 255
	g_object_notify (G_OBJECT (misc), "yalign");

256 257
      priv->xalign = xalign;
      priv->yalign = yalign;
258
      
Elliot Lee's avatar
Elliot Lee committed
259
      /* clear the area that was allocated before the change
260
       */
261 262 263
      widget = GTK_WIDGET (misc);
      if (gtk_widget_is_drawable (widget))
        gtk_widget_queue_draw (widget);
Alexander Larsson's avatar
Alexander Larsson committed
264

265
      g_object_thaw_notify (G_OBJECT (misc));
Elliot Lee's avatar
Elliot Lee committed
266 267 268
    }
}

269 270 271
/**
 * gtk_misc_get_alignment:
 * @misc: a #GtkMisc
272 273
 * @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
274
 *
275 276
 * Gets the X and Y alignment of the widget within its allocation. 
 * See gtk_misc_set_alignment().
277 278 279 280 281 282
 **/
void
gtk_misc_get_alignment (GtkMisc *misc,
		        gfloat  *xalign,
			gfloat  *yalign)
{
283
  GtkMiscPrivate *priv;
284

285 286
  g_return_if_fail (GTK_IS_MISC (misc));

287 288
  priv = misc->priv;

289
  if (xalign)
290
    *xalign = priv->xalign;
291
  if (yalign)
292
    *yalign = priv->yalign;
293 294
}

295 296 297 298 299 300 301 302 303 304
/**
 * 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
305 306 307 308 309
void
gtk_misc_set_padding (GtkMisc *misc,
		      gint     xpad,
		      gint     ypad)
{
310
  GtkMiscPrivate *priv;
311

Elliot Lee's avatar
Elliot Lee committed
312
  g_return_if_fail (GTK_IS_MISC (misc));
313 314 315

  priv = misc->priv;

Elliot Lee's avatar
Elliot Lee committed
316 317 318 319
  if (xpad < 0)
    xpad = 0;
  if (ypad < 0)
    ypad = 0;
320 321

  if ((xpad != priv->xpad) || (ypad != priv->ypad))
Elliot Lee's avatar
Elliot Lee committed
322
    {
Matthias Clasen's avatar
Matthias Clasen committed
323
      g_object_freeze_notify (G_OBJECT (misc));
324
      if (xpad != priv->xpad)
Matthias Clasen's avatar
Matthias Clasen committed
325 326
	g_object_notify (G_OBJECT (misc), "xpad");

327
      if (ypad != priv->ypad)
Matthias Clasen's avatar
Matthias Clasen committed
328 329
	g_object_notify (G_OBJECT (misc), "ypad");

330 331 332
      priv->xpad = xpad;
      priv->ypad = ypad;

333
      if (gtk_widget_is_drawable (GTK_WIDGET (misc)))
Elliot Lee's avatar
Elliot Lee committed
334
	gtk_widget_queue_resize (GTK_WIDGET (misc));
Alexander Larsson's avatar
Alexander Larsson committed
335

336
      g_object_thaw_notify (G_OBJECT (misc));
Elliot Lee's avatar
Elliot Lee committed
337 338 339
    }
}

340 341 342
/**
 * gtk_misc_get_padding:
 * @misc: a #GtkMisc
343 344 345 346
 * @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
347
 *
348 349
 * Gets the padding in the X and Y directions of the widget. 
 * See gtk_misc_set_padding().
350 351 352 353 354 355
 **/
void
gtk_misc_get_padding (GtkMisc *misc,
		      gint    *xpad,
		      gint    *ypad)
{
356
  GtkMiscPrivate *priv;
357

358 359
  g_return_if_fail (GTK_IS_MISC (misc));

360 361
  priv = misc->priv;

362
  if (xpad)
363
    *xpad = priv->xpad;
364
  if (ypad)
365
    *ypad = priv->ypad;
366 367
}

Elliot Lee's avatar
Elliot Lee committed
368 369 370
static void
gtk_misc_realize (GtkWidget *widget)
{
371 372
  GtkAllocation allocation;
  GdkWindow *window;
Elliot Lee's avatar
Elliot Lee committed
373 374 375
  GdkWindowAttr attributes;
  gint attributes_mask;

376
  gtk_widget_set_realized (widget, TRUE);
Elliot Lee's avatar
Elliot Lee committed
377

378
  if (!gtk_widget_get_has_window (widget))
Elliot Lee's avatar
Elliot Lee committed
379
    {
380 381 382
      window = gtk_widget_get_parent_window (widget);
      gtk_widget_set_window (widget, window);
      g_object_ref (window);
Elliot Lee's avatar
Elliot Lee committed
383 384 385
    }
  else
    {
386 387
      gtk_widget_get_allocation (widget, &allocation);

Elliot Lee's avatar
Elliot Lee committed
388
      attributes.window_type = GDK_WINDOW_CHILD;
389 390 391 392
      attributes.x = allocation.x;
      attributes.y = allocation.y;
      attributes.width = allocation.width;
      attributes.height = allocation.height;
Elliot Lee's avatar
Elliot Lee committed
393 394 395
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
396
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
Elliot Lee's avatar
Elliot Lee committed
397

398 399
      window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
      gtk_widget_set_window (widget, window);
400
      gtk_widget_register_window (widget, window);
401
      gdk_window_set_background_pattern (window, NULL);
Elliot Lee's avatar
Elliot Lee committed
402 403
    }
}
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425

/* 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);
426 427 428 429
  border->top += ypad;
  border->left += xpad;
  border->bottom += ypad;
  border->right += xpad;
430 431 432 433 434 435 436 437

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