gtkruler.c 12.3 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GTK - The GIMP Toolkit
 * 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
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * 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/. 
 */

Elliot Lee's avatar
Elliot Lee committed
27
#include "gtkruler.h"
28
#include "gtkintl.h"
Elliot Lee's avatar
Elliot Lee committed
29

30
enum {
31 32 33 34 35
  PROP_0,
  PROP_LOWER,
  PROP_UPPER,
  PROP_POSITION,
  PROP_MAX_SIZE
36
};
Elliot Lee's avatar
Elliot Lee committed
37 38 39 40 41 42 43 44 45 46

static void gtk_ruler_class_init    (GtkRulerClass  *klass);
static void gtk_ruler_init          (GtkRuler       *ruler);
static void gtk_ruler_realize       (GtkWidget      *widget);
static void gtk_ruler_unrealize     (GtkWidget      *widget);
static void gtk_ruler_size_allocate (GtkWidget      *widget,
				     GtkAllocation  *allocation);
static gint gtk_ruler_expose        (GtkWidget      *widget,
				     GdkEventExpose *event);
static void gtk_ruler_make_pixmap   (GtkRuler       *ruler);
47 48 49 50 51 52 53 54
static void gtk_ruler_set_property  (GObject        *object,
				     guint            prop_id,
				     const GValue   *value,
				     GParamSpec     *pspec);
static void gtk_ruler_get_property  (GObject        *object,
				     guint           prop_id,
				     GValue         *value,
				     GParamSpec     *pspec);
Elliot Lee's avatar
Elliot Lee committed
55

56 57
static GtkWidgetClass *parent_class;

58
static const GtkRulerMetric ruler_metrics[] =
Elliot Lee's avatar
Elliot Lee committed
59 60 61 62 63 64 65
{
  {"Pixels", "Pi", 1.0, { 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000 }, { 1, 5, 10, 50, 100 }},
  {"Inches", "In", 72.0, { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }, { 1, 2, 4, 8, 16 }},
  {"Centimeters", "Cn", 28.35, { 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000 }, { 1, 5, 10, 50, 100 }},
};


Manish Singh's avatar
Manish Singh committed
66
GType
67
gtk_ruler_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
68
{
Manish Singh's avatar
Manish Singh committed
69
  static GType ruler_type = 0;
Elliot Lee's avatar
Elliot Lee committed
70 71 72

  if (!ruler_type)
    {
Manish Singh's avatar
Manish Singh committed
73
      static const GTypeInfo ruler_info =
Elliot Lee's avatar
Elliot Lee committed
74 75
      {
	sizeof (GtkRulerClass),
Manish Singh's avatar
Manish Singh committed
76 77 78 79 80 81 82 83
	NULL,		/* base_init */
	NULL,		/* base_finalize */
	(GClassInitFunc) gtk_ruler_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkRuler),
	0,		/* n_preallocs */
	(GInstanceInitFunc) gtk_ruler_init,
Elliot Lee's avatar
Elliot Lee committed
84 85
      };

Manish Singh's avatar
Manish Singh committed
86 87
      ruler_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkRuler",
					   &ruler_info, 0);
Elliot Lee's avatar
Elliot Lee committed
88 89 90 91 92 93 94 95
    }

  return ruler_type;
}

static void
gtk_ruler_class_init (GtkRulerClass *class)
{
96
  GObjectClass   *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
97 98
  GtkWidgetClass *widget_class;

99
  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
100 101
  widget_class = (GtkWidgetClass*) class;

Manish Singh's avatar
Manish Singh committed
102
  parent_class = g_type_class_peek_parent (class);
103
  
104 105
  gobject_class->set_property = gtk_ruler_set_property;
  gobject_class->get_property = gtk_ruler_get_property;
106

Elliot Lee's avatar
Elliot Lee committed
107 108 109 110 111 112 113
  widget_class->realize = gtk_ruler_realize;
  widget_class->unrealize = gtk_ruler_unrealize;
  widget_class->size_allocate = gtk_ruler_size_allocate;
  widget_class->expose_event = gtk_ruler_expose;

  class->draw_ticks = NULL;
  class->draw_pos = NULL;
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  g_object_class_install_property (gobject_class,
                                   PROP_LOWER,
                                   g_param_spec_double ("lower",
							_("Lower"),
							_("Lower limit of ruler"),
							-G_MAXDOUBLE,
							G_MAXDOUBLE,
							0.0,
							G_PARAM_READWRITE));  

  g_object_class_install_property (gobject_class,
                                   PROP_UPPER,
                                   g_param_spec_double ("upper",
							_("Upper"),
							_("Upper limit of ruler"),
							-G_MAXDOUBLE,
							G_MAXDOUBLE,
							0.0,
							G_PARAM_READWRITE));  

  g_object_class_install_property (gobject_class,
                                   PROP_POSITION,
                                   g_param_spec_double ("position",
							_("Position"),
							_("Position of mark on the ruler"),
							-G_MAXDOUBLE,
							G_MAXDOUBLE,
							0.0,
							G_PARAM_READWRITE));  

  g_object_class_install_property (gobject_class,
                                   PROP_MAX_SIZE,
                                   g_param_spec_double ("max_size",
							_("Max Size"),
							_("Maximum size of the ruler"),
							-G_MAXDOUBLE,
							G_MAXDOUBLE,
							0.0,
							G_PARAM_READWRITE));  
Elliot Lee's avatar
Elliot Lee committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
}

static void
gtk_ruler_init (GtkRuler *ruler)
{
  ruler->backing_store = NULL;
  ruler->non_gr_exp_gc = NULL;
  ruler->xsrc = 0;
  ruler->ysrc = 0;
  ruler->slider_size = 0;
  ruler->lower = 0;
  ruler->upper = 0;
  ruler->position = 0;
  ruler->max_size = 0;

  gtk_ruler_set_metric (ruler, GTK_PIXELS);
}

172
static void
173 174 175 176
gtk_ruler_set_property (GObject      *object,
 			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
177 178 179
{
  GtkRuler *ruler = GTK_RULER (object);

180
  switch (prop_id)
181
    {
182 183
    case PROP_LOWER:
      gtk_ruler_set_range (ruler, g_value_get_double (value), ruler->upper,
184 185
			   ruler->position, ruler->max_size);
      break;
186 187
    case PROP_UPPER:
      gtk_ruler_set_range (ruler, ruler->lower, g_value_get_double (value),
188 189
			   ruler->position, ruler->max_size);
      break;
190
    case PROP_POSITION:
191
      gtk_ruler_set_range (ruler, ruler->lower, ruler->upper,
192
			   g_value_get_double (value), ruler->max_size);
193
      break;
194
    case PROP_MAX_SIZE:
195
      gtk_ruler_set_range (ruler, ruler->lower, ruler->upper,
196
			   ruler->position,  g_value_get_double (value));
197 198 199 200 201
      break;
    }
}

static void
202 203 204 205
gtk_ruler_get_property (GObject      *object,
			guint         prop_id,
			GValue       *value,
			GParamSpec   *pspec)
206 207 208
{
  GtkRuler *ruler = GTK_RULER (object);
  
209
  switch (prop_id)
210
    {
211 212
    case PROP_LOWER:
      g_value_set_double (value, ruler->lower);
213
      break;
214 215
    case PROP_UPPER:
      g_value_set_double (value, ruler->upper);
216
      break;
217 218
    case PROP_POSITION:
      g_value_set_double (value, ruler->position);
219
      break;
220 221
    case PROP_MAX_SIZE:
      g_value_set_double (value, ruler->max_size);
222 223
      break;
    default:
224
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
225 226 227 228
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
229 230 231 232 233 234
void
gtk_ruler_set_metric (GtkRuler      *ruler,
		      GtkMetricType  metric)
{
  g_return_if_fail (GTK_IS_RULER (ruler));

235
  ruler->metric = (GtkRulerMetric *) &ruler_metrics[metric];
Elliot Lee's avatar
Elliot Lee committed
236 237 238 239 240

  if (GTK_WIDGET_DRAWABLE (ruler))
    gtk_widget_queue_draw (GTK_WIDGET (ruler));
}

241 242 243 244
/**
 * gtk_ruler_get_metric:
 * @ruler: a #GtkRuler
 *
245
 * Gets the units used for a #GtkRuler. See gtk_ruler_set_metric().
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
 *
 * Return value: the units currently used for @ruler
 **/
GtkMetricType
gtk_ruler_get_metric (GtkRuler *ruler)
{
  gint i;

  g_return_val_if_fail (GTK_IS_RULER (ruler), 0);

  for (i = 0; i < G_N_ELEMENTS (ruler_metrics); i++)
    if (ruler->metric == &ruler_metrics[i])
      return i;

  g_assert_not_reached ();

  return 0;
}

Elliot Lee's avatar
Elliot Lee committed
265 266
void
gtk_ruler_set_range (GtkRuler *ruler,
267 268 269 270
		     gdouble   lower,
		     gdouble   upper,
		     gdouble   position,
		     gdouble   max_size)
Elliot Lee's avatar
Elliot Lee committed
271 272 273
{
  g_return_if_fail (GTK_IS_RULER (ruler));

Hans Breuer's avatar
Hans Breuer committed
274
  g_object_freeze_notify (G_OBJECT (ruler));
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
  if (ruler->lower != lower)
    {
      ruler->lower = lower;
      g_object_notify (G_OBJECT (ruler), "lower");
    }
  if (ruler->upper != upper)
    {
      ruler->upper = upper;
      g_object_notify (G_OBJECT (ruler), "upper");
    }
  if (ruler->position != position)
    {
      ruler->position = position;
      g_object_notify (G_OBJECT (ruler), "position");
    }
  if (ruler->max_size != max_size)
    {
      ruler->max_size = max_size;
      g_object_notify (G_OBJECT (ruler), "max_size");
    }
Hans Breuer's avatar
Hans Breuer committed
295
  g_object_thaw_notify (G_OBJECT (ruler));
Elliot Lee's avatar
Elliot Lee committed
296 297 298 299 300

  if (GTK_WIDGET_DRAWABLE (ruler))
    gtk_widget_queue_draw (GTK_WIDGET (ruler));
}

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
/**
 * gtk_ruler_get_range:
 * @ruler: a #GtkRuler
 * @lower: location to store lower limit of the ruler, or %NULL
 * @upper: location to store upper limit of the ruler, or %NULL
 * @position: location to store the current position of the mark on the ruler, or %NULL
 * @max_size: location to store the maximum size of the ruler used when calculating
 *            the space to leave for the text, or %NULL.
 *
 * Retrieves values indicating the range and current position of a #GtkRuler.
 * See gtk_ruler_set_range().
 **/
void
gtk_ruler_get_range (GtkRuler *ruler,
		     gdouble  *lower,
		     gdouble  *upper,
		     gdouble  *position,
		     gdouble  *max_size)
{
  g_return_if_fail (GTK_IS_RULER (ruler));

  if (lower)
    *lower = ruler->lower;
  if (upper)
    *upper = ruler->upper;
  if (position)
    *position = ruler->position;
  if (max_size)
    *max_size = ruler->max_size;
}

Elliot Lee's avatar
Elliot Lee committed
332 333 334 335 336
void
gtk_ruler_draw_ticks (GtkRuler *ruler)
{
  g_return_if_fail (GTK_IS_RULER (ruler));

337 338
  if (GTK_RULER_GET_CLASS (ruler)->draw_ticks)
    GTK_RULER_GET_CLASS (ruler)->draw_ticks (ruler);
Elliot Lee's avatar
Elliot Lee committed
339 340 341 342 343 344 345
}

void
gtk_ruler_draw_pos (GtkRuler *ruler)
{
  g_return_if_fail (GTK_IS_RULER (ruler));

346 347
  if (GTK_RULER_GET_CLASS (ruler)->draw_pos)
     GTK_RULER_GET_CLASS (ruler)->draw_pos (ruler);
Elliot Lee's avatar
Elliot Lee committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
}


static void
gtk_ruler_realize (GtkWidget *widget)
{
  GtkRuler *ruler;
  GdkWindowAttr attributes;
  gint attributes_mask;

  ruler = GTK_RULER (widget);
  GTK_WIDGET_SET_FLAGS (ruler, GTK_REALIZED);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = widget->allocation.x;
  attributes.y = widget->allocation.y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget);
  attributes.event_mask |= (GDK_EXPOSURE_MASK |
			    GDK_POINTER_MOTION_MASK |
			    GDK_POINTER_MOTION_HINT_MASK);

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

376
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
Elliot Lee's avatar
Elliot Lee committed
377 378 379 380 381 382 383 384 385 386 387
  gdk_window_set_user_data (widget->window, ruler);

  widget->style = gtk_style_attach (widget->style, widget->window);
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);

  gtk_ruler_make_pixmap (ruler);
}

static void
gtk_ruler_unrealize (GtkWidget *widget)
{
388
  GtkRuler *ruler = GTK_RULER (widget);
Elliot Lee's avatar
Elliot Lee committed
389 390

  if (ruler->backing_store)
Manish Singh's avatar
Manish Singh committed
391
    g_object_unref (ruler->backing_store);
Elliot Lee's avatar
Elliot Lee committed
392
  if (ruler->non_gr_exp_gc)
Manish Singh's avatar
Manish Singh committed
393
    g_object_unref (ruler->non_gr_exp_gc);
Elliot Lee's avatar
Elliot Lee committed
394 395 396

  ruler->backing_store = NULL;
  ruler->non_gr_exp_gc = NULL;
397 398 399

  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
Elliot Lee's avatar
Elliot Lee committed
400 401 402 403 404 405
}

static void
gtk_ruler_size_allocate (GtkWidget     *widget,
			 GtkAllocation *allocation)
{
406
  GtkRuler *ruler = GTK_RULER (widget);
Elliot Lee's avatar
Elliot Lee committed
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430

  widget->allocation = *allocation;

  if (GTK_WIDGET_REALIZED (widget))
    {
      gdk_window_move_resize (widget->window,
			      allocation->x, allocation->y,
			      allocation->width, allocation->height);

      gtk_ruler_make_pixmap (ruler);
    }
}

static gint
gtk_ruler_expose (GtkWidget      *widget,
		  GdkEventExpose *event)
{
  GtkRuler *ruler;

  if (GTK_WIDGET_DRAWABLE (widget))
    {
      ruler = GTK_RULER (widget);

      gtk_ruler_draw_ticks (ruler);
431
      
Manish Singh's avatar
Manish Singh committed
432 433 434 435 436 437
      gdk_draw_drawable (widget->window,
			 ruler->non_gr_exp_gc,
			 ruler->backing_store,
			 0, 0, 0, 0,
			 widget->allocation.width,
			 widget->allocation.height);
438
      
Elliot Lee's avatar
Elliot Lee committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
      gtk_ruler_draw_pos (ruler);
    }

  return FALSE;
}

static void
gtk_ruler_make_pixmap (GtkRuler *ruler)
{
  GtkWidget *widget;
  gint width;
  gint height;

  widget = GTK_WIDGET (ruler);

  if (ruler->backing_store)
    {
Manish Singh's avatar
Manish Singh committed
456
      gdk_drawable_get_size (ruler->backing_store, &width, &height);
Elliot Lee's avatar
Elliot Lee committed
457 458 459 460
      if ((width == widget->allocation.width) &&
	  (height == widget->allocation.height))
	return;

Manish Singh's avatar
Manish Singh committed
461
      g_object_unref (ruler->backing_store);
Elliot Lee's avatar
Elliot Lee committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
    }

  ruler->backing_store = gdk_pixmap_new (widget->window,
					 widget->allocation.width,
					 widget->allocation.height,
					 -1);

  ruler->xsrc = 0;
  ruler->ysrc = 0;

  if (!ruler->non_gr_exp_gc)
    {
      ruler->non_gr_exp_gc = gdk_gc_new (widget->window);
      gdk_gc_set_exposures (ruler->non_gr_exp_gc, FALSE);
    }
}