X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkhscale.c;h=4b407ccf59f3dec20ba94612106e5a18148b3a7c;hb=10862a344aa8fb44e6045343ddf65eb0d14cc1b2;hp=c8442fb70cf6c59a2f546496fa6a305cb538fbfe;hpb=2f9aee8d7f0d164412a459d26970ea3151f875be;p=~andy%2Fgtk diff --git a/gtk/gtkhscale.c b/gtk/gtkhscale.c index c8442fb70..4b407ccf5 100644 --- a/gtk/gtkhscale.c +++ b/gtk/gtkhscale.c @@ -1,5 +1,5 @@ /* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * Copyright (C) 2001 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,603 +24,213 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include +#include #include +#include #include "gtkhscale.h" -#include "gtksignal.h" -#include "gdk/gdkkeysyms.h" - -#define SCALE_CLASS(w) GTK_SCALE_GET_CLASS (w) -#define RANGE_CLASS(w) GTK_RANGE_GET_CLASS (w) - -enum { - ARG_0, - ARG_ADJUSTMENT -}; - -static void gtk_hscale_class_init (GtkHScaleClass *klass); -static void gtk_hscale_init (GtkHScale *hscale); -static void gtk_hscale_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_hscale_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_hscale_realize (GtkWidget *widget); -static void gtk_hscale_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_hscale_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void gtk_hscale_pos_trough (GtkHScale *hscale, - gint *x, - gint *y, - gint *w, - gint *h); -static void gtk_hscale_pos_background (GtkHScale *hscale, - gint *x, - gint *y, - gint *w, - gint *h); -static void gtk_hscale_draw_slider (GtkRange *range); -static void gtk_hscale_draw_value (GtkScale *scale); -static void gtk_hscale_draw (GtkWidget *widget, - GdkRectangle *area); -static gint gtk_hscale_trough_keys (GtkRange *range, - GdkEventKey *key, - GtkScrollType *scroll, - GtkTroughType *pos); -static void gtk_hscale_clear_background (GtkRange *range); - -GtkType -gtk_hscale_get_type (void) -{ - static GtkType hscale_type = 0; - - if (!hscale_type) - { - static const GtkTypeInfo hscale_info = - { - "GtkHScale", - sizeof (GtkHScale), - sizeof (GtkHScaleClass), - (GtkClassInitFunc) gtk_hscale_class_init, - (GtkObjectInitFunc) gtk_hscale_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - hscale_type = gtk_type_unique (GTK_TYPE_SCALE, &hscale_info); - } - - return hscale_type; -} +#include "gtkintl.h" +#include "gtkalias.h" + +static gboolean gtk_hscale_expose (GtkWidget *widget, + GdkEventExpose *event); + +static void gtk_hscale_get_layout_offsets (GtkScale *scale, + gint *x, + gint *y); + +G_DEFINE_TYPE (GtkHScale, gtk_hscale, GTK_TYPE_SCALE) static void gtk_hscale_class_init (GtkHScaleClass *class) { - GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkRangeClass *range_class; GtkScaleClass *scale_class; - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - range_class = (GtkRangeClass*) class; - scale_class = (GtkScaleClass*) class; - - gtk_object_add_arg_type ("GtkHScale::adjustment", - GTK_TYPE_ADJUSTMENT, - GTK_ARG_READWRITE, - ARG_ADJUSTMENT); - - object_class->set_arg = gtk_hscale_set_arg; - object_class->get_arg = gtk_hscale_get_arg; - - widget_class->realize = gtk_hscale_realize; - widget_class->size_request = gtk_hscale_size_request; - widget_class->size_allocate = gtk_hscale_size_allocate; - widget_class->draw = gtk_hscale_draw; - - range_class->slider_update = gtk_range_default_hslider_update; - range_class->trough_click = gtk_range_default_htrough_click; - range_class->motion = gtk_range_default_hmotion; - range_class->draw_slider = gtk_hscale_draw_slider; - range_class->trough_keys = gtk_hscale_trough_keys; - range_class->clear_background = gtk_hscale_clear_background; - - scale_class->draw_value = gtk_hscale_draw_value; -} + widget_class = GTK_WIDGET_CLASS (class); + range_class = GTK_RANGE_CLASS (class); + scale_class = GTK_SCALE_CLASS (class); -static void -gtk_hscale_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) -{ - GtkHScale *hscale; - - hscale = GTK_HSCALE (object); - - switch (arg_id) - { - case ARG_ADJUSTMENT: - gtk_range_set_adjustment (GTK_RANGE (hscale), GTK_VALUE_POINTER (*arg)); - break; - default: - break; - } -} + range_class->slider_detail = "hscale"; -static void -gtk_hscale_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) -{ - GtkHScale *hscale; + scale_class->get_layout_offsets = gtk_hscale_get_layout_offsets; - hscale = GTK_HSCALE (object); - - switch (arg_id) - { - case ARG_ADJUSTMENT: - GTK_VALUE_POINTER (*arg) = GTK_RANGE (hscale); - break; - default: - arg->type = GTK_TYPE_INVALID; - break; - } + widget_class->expose_event = gtk_hscale_expose; } static void gtk_hscale_init (GtkHScale *hscale) { - GTK_WIDGET_SET_FLAGS (hscale, GTK_NO_WINDOW); + GtkRange *range; + + range = GTK_RANGE (hscale); + + range->orientation = GTK_ORIENTATION_HORIZONTAL; + range->flippable = TRUE; } GtkWidget* gtk_hscale_new (GtkAdjustment *adjustment) { - GtkWidget *hscale; - - hscale = gtk_widget_new (GTK_TYPE_HSCALE, - "adjustment", adjustment, - NULL); - - GTK_RANGE (hscale) -> flippable = 1; - - return hscale; -} + return g_object_new (GTK_TYPE_HSCALE, "adjustment", adjustment, NULL); +} + +/** + * gtk_hscale_new_with_range: + * @min: minimum value + * @max: maximum value + * @step: step increment (tick size) used with keyboard shortcuts + * + * Creates a new horizontal scale widget that lets the user input a + * number between @min and @max (including @min and @max) with the + * increment @step. @step must be nonzero; it's the distance the + * slider moves when using the arrow keys to adjust the scale value. + * + * Note that the way in which the precision is derived works best if @step + * is a power of ten. If the resulting precision is not suitable for your + * needs, use gtk_scale_set_digits() to correct it. + * + * Return value: a new #GtkHScale + **/ +GtkWidget* +gtk_hscale_new_with_range (gdouble min, + gdouble max, + gdouble step) +{ + GtkObject *adj; + GtkScale *scale; + gint digits; + g_return_val_if_fail (min < max, NULL); + g_return_val_if_fail (step != 0.0, NULL); -static void -gtk_hscale_realize (GtkWidget *widget) -{ - GtkRange *range; - GdkWindowAttr attributes; - gint attributes_mask; - gint x, y, w, h; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_HSCALE (widget)); + adj = gtk_adjustment_new (min, min, max, step, 10 * step, 0); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - range = GTK_RANGE (widget); - - widget->window = gtk_widget_get_parent_window (widget); - gdk_window_ref (widget->window); - - gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &w, &h); - - attributes.x = x; - attributes.y = y; - attributes.width = w; - attributes.height = h; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - - attributes.event_mask = gtk_widget_get_events (widget) | - (GDK_EXPOSURE_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK); - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - range->trough = gdk_window_new (widget->window, &attributes, attributes_mask); - - attributes.width = SCALE_CLASS (range)->slider_length; - attributes.height = RANGE_CLASS (range)->slider_width; - attributes.event_mask |= (GDK_BUTTON_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK); - - range->slider = gdk_window_new (range->trough, &attributes, attributes_mask); - - widget->style = gtk_style_attach (widget->style, widget->window); - - gdk_window_set_user_data (range->trough, widget); - gdk_window_set_user_data (range->slider, widget); - - gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE); - gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL); - - gtk_range_slider_update (GTK_RANGE (widget)); - - gdk_window_show (range->slider); -} + scale = g_object_new (GTK_TYPE_HSCALE, + "adjustment", adj, + NULL); -static void -gtk_hscale_draw (GtkWidget *widget, - GdkRectangle *area) -{ - GtkRange *range; - GdkRectangle tmp_area; - GdkRectangle child_area; - gint x, y, width, height; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_RANGE (widget)); - g_return_if_fail (area != NULL); - - if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) - { - range = GTK_RANGE (widget); - - gtk_hscale_pos_background (GTK_HSCALE (widget), &x, &y, &width, &height); - - tmp_area.x = x; - tmp_area.y = y; - tmp_area.width = width; - tmp_area.height = height; - - if (gdk_rectangle_intersect (area, &tmp_area, &child_area)) - gtk_range_draw_background (range); - - gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height); - - tmp_area.x = x; - tmp_area.y = y; - tmp_area.width = width; - tmp_area.height = height; - - if (gdk_rectangle_intersect (area, &tmp_area, &child_area)) - { - gtk_range_draw_trough (range); - gtk_range_draw_slider (range); - gtk_range_draw_step_forw (range); - gtk_range_draw_step_back (range); - } - } -} + if (fabs (step) >= 1.0 || step == 0.0) + digits = 0; + else { + digits = abs ((gint) floor (log10 (fabs (step)))); + if (digits > 5) + digits = 5; + } -static void -gtk_hscale_clear_background (GtkRange *range) -{ - GtkWidget *widget; - gint x, y, width, height; - - g_return_if_fail (range != NULL); + gtk_scale_set_digits (scale, digits); - widget = GTK_WIDGET (range); - - gtk_hscale_pos_background (GTK_HSCALE (range), &x, &y, &width, &height); - - gtk_widget_queue_clear_area (GTK_WIDGET (range), - x, y, width, height); + return GTK_WIDGET (scale); } -static void -gtk_hscale_size_request (GtkWidget *widget, - GtkRequisition *requisition) +static gboolean +gtk_hscale_expose (GtkWidget *widget, + GdkEventExpose *event) { GtkScale *scale; - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_HSCALE (widget)); - g_return_if_fail (requisition != NULL); - scale = GTK_SCALE (widget); - - requisition->width = (SCALE_CLASS (scale)->slider_length + - widget->style->xthickness) * 2; - requisition->height = (RANGE_CLASS (scale)->slider_width + - widget->style->ythickness * 2); - + + /* We need to chain up _first_ so the various geometry members of + * GtkRange struct are updated. + */ + if (GTK_WIDGET_CLASS (gtk_hscale_parent_class)->expose_event) + GTK_WIDGET_CLASS (gtk_hscale_parent_class)->expose_event (widget, event); + if (scale->draw_value) { - gint value_width, value_height; - gtk_scale_get_value_size (scale, &value_width, &value_height); - - if ((scale->value_pos == GTK_POS_LEFT) || - (scale->value_pos == GTK_POS_RIGHT)) - { - requisition->width += value_width + SCALE_CLASS (scale)->value_spacing; - if (requisition->height < value_height) - requisition->height = value_height; - } - else if ((scale->value_pos == GTK_POS_TOP) || - (scale->value_pos == GTK_POS_BOTTOM)) - { - if (requisition->width < value_width) - requisition->width = value_width; - requisition->height += value_height; - } - } -} + PangoLayout *layout; + gint x, y; + GtkStateType state_type; + + layout = gtk_scale_get_layout (scale); + gtk_scale_get_layout_offsets (scale, &x, &y); + + state_type = GTK_STATE_NORMAL; + if (!GTK_WIDGET_IS_SENSITIVE (scale)) + state_type = GTK_STATE_INSENSITIVE; + + gtk_paint_layout (widget->style, + widget->window, + state_type, + FALSE, + NULL, + widget, + "hscale", + x, y, + layout); -static void -gtk_hscale_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkRange *range; - GtkScale *scale; - gint width, height; - gint x, y; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_HSCALE (widget)); - g_return_if_fail (allocation != NULL); - - widget->allocation = *allocation; - if (GTK_WIDGET_REALIZED (widget)) - { - range = GTK_RANGE (widget); - scale = GTK_SCALE (widget); - - gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height); - - gdk_window_move_resize (range->trough, - x, y, width, height); - gtk_range_slider_update (GTK_RANGE (widget)); } + + return FALSE; } -static void -gtk_hscale_pos_trough (GtkHScale *hscale, - gint *x, - gint *y, - gint *w, - gint *h) +static void +gtk_hscale_get_layout_offsets (GtkScale *scale, + gint *x, + gint *y) { GtkWidget *widget; - GtkScale *scale; - - g_return_if_fail (hscale != NULL); - g_return_if_fail (GTK_IS_HSCALE (hscale)); - g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL)); - - widget = GTK_WIDGET (hscale); - scale = GTK_SCALE (hscale); - - *w = widget->allocation.width; - *h = (RANGE_CLASS (scale)->slider_width + - widget->style->ythickness * 2); - - if (scale->draw_value) - { - gint value_width, value_height; - gtk_scale_get_value_size (scale, &value_width, &value_height); - - *x = 0; - *y = 0; + GtkRange *range; + PangoLayout *layout; + PangoRectangle logical_rect; + gint value_spacing; + + widget = GTK_WIDGET (scale); + layout = gtk_scale_get_layout (scale); - switch (scale->value_pos) - { - case GTK_POS_LEFT: - *x += value_width + SCALE_CLASS (scale)->value_spacing; - *y = (widget->allocation.height - *h) / 2; - *w -= *x; - break; - case GTK_POS_RIGHT: - *w -= value_width + SCALE_CLASS (scale)->value_spacing; - *y = (widget->allocation.height - *h) / 2; - break; - case GTK_POS_TOP: - *y = (value_height + (widget->allocation.height - widget->requisition.height) / 2); - break; - case GTK_POS_BOTTOM: - *y = (widget->allocation.height - widget->requisition.height) / 2; - break; - } - } - else + if (!layout) { *x = 0; - *y = (widget->allocation.height - *h) / 2; + *y = 0; + + return; } - *x += 1; - *w -= 2; - - *x += widget->allocation.x; - *y += widget->allocation.y; -} -static void -gtk_hscale_pos_background (GtkHScale *hscale, - gint *x, - gint *y, - gint *w, - gint *h) -{ - GtkWidget *widget; - GtkScale *scale; - - gint tx, ty, twidth, theight; - - g_return_if_fail (hscale != NULL); - g_return_if_fail (GTK_IS_HSCALE (hscale)); - g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL)); - - gtk_hscale_pos_trough (hscale, &tx, &ty, &twidth, &theight); - - widget = GTK_WIDGET (hscale); - scale = GTK_SCALE (hscale); - - *x = widget->allocation.x; - *y = widget->allocation.y; - *w = widget->allocation.width; - *h = widget->allocation.height; - + gtk_widget_style_get (widget, "value-spacing", &value_spacing, NULL); + + range = GTK_RANGE (widget); + scale = GTK_SCALE (widget); + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + switch (scale->value_pos) { - case GTK_POS_LEFT: - *w -= twidth; - break; + case GTK_POS_LEFT: + *x = range->range_rect.x - value_spacing - logical_rect.width; + *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2; + break; + case GTK_POS_RIGHT: - *x += twidth; - *w -= twidth; + *x = range->range_rect.x + range->range_rect.width + value_spacing; + *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2; break; + case GTK_POS_TOP: - *h -= theight; + *x = range->slider_start + + (range->slider_end - range->slider_start - logical_rect.width) / 2; + *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width); + *y = range->range_rect.y - logical_rect.height - value_spacing; break; + case GTK_POS_BOTTOM: - *y += theight; - *h -= theight; + *x = range->slider_start + + (range->slider_end - range->slider_start - logical_rect.width) / 2; + *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width); + *y = range->range_rect.y + range->range_rect.height + value_spacing; break; - } - *w = MAX (*w, 0); - *h = MAX (*h, 0); -} -static void -gtk_hscale_draw_slider (GtkRange *range) -{ - GtkStateType state_type; - - g_return_if_fail (range != NULL); - g_return_if_fail (GTK_IS_HSCALE (range)); - - if (range->slider) - { - if ((range->in_child == RANGE_CLASS (range)->slider) || - (range->click_child == RANGE_CLASS (range)->slider)) - state_type = GTK_STATE_PRELIGHT; - else - state_type = GTK_STATE_NORMAL; - - gtk_paint_slider (GTK_WIDGET (range)->style, range->slider, state_type, - GTK_SHADOW_OUT, - NULL, GTK_WIDGET (range), "hscale", - 0, 0, -1, -1, - GTK_ORIENTATION_HORIZONTAL); + default: + g_return_if_reached (); + *x = 0; + *y = 0; + break; } -} - -static void -gtk_hscale_draw_value (GtkScale *scale) -{ - GtkStateType state_type; - GtkWidget *widget; - gchar buffer[32]; - gint width, height; - gint x, y; - - g_return_if_fail (scale != NULL); - g_return_if_fail (GTK_IS_HSCALE (scale)); - - widget = GTK_WIDGET (scale); - - if (scale->draw_value) - { - PangoLayout *layout; - PangoRectangle logical_rect; - - sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value); - layout = gtk_widget_create_pango_layout (widget, buffer); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - switch (scale->value_pos) - { - case GTK_POS_LEFT: - gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y); - gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height); - - x -= SCALE_CLASS (scale)->value_spacing + logical_rect.width; - y += (height - logical_rect.height) / 2; - break; - case GTK_POS_RIGHT: - gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y); - gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height); - - x += width + SCALE_CLASS (scale)->value_spacing; - y += (height - logical_rect.height) / 2; - break; - case GTK_POS_TOP: - gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL); - gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y); - gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL); - gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height); - - x += widget->allocation.x + (width - logical_rect.width) / 2; - x = CLAMP (x, widget->allocation.x, - widget->allocation.x + widget->allocation.width - logical_rect.width); - y -= logical_rect.height; - break; - case GTK_POS_BOTTOM: - gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL); - gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y); - gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL); - gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height); - - x += widget->allocation.x + (width - logical_rect.width) / 2; - x = CLAMP (x, widget->allocation.x, - widget->allocation.x + widget->allocation.width - logical_rect.width); - y += height; - break; - } - - state_type = GTK_STATE_NORMAL; - if (!GTK_WIDGET_IS_SENSITIVE (scale)) - state_type = GTK_STATE_INSENSITIVE; - -#if 0 - gtk_paint_string (GTK_WIDGET (scale)->style, - GTK_WIDGET (scale)->window, - state_type, - NULL, GTK_WIDGET (scale), "hscale", - x, y, buffer); -#endif - - gdk_draw_layout (GTK_WIDGET (scale)->window, - GTK_WIDGET (scale)->style->fg_gc [state_type], - x, y, layout); - g_object_unref (G_OBJECT (layout)); - } + *x += widget->allocation.x; + *y += widget->allocation.y; } -static gint -gtk_hscale_trough_keys (GtkRange *range, - GdkEventKey *key, - GtkScrollType *scroll, - GtkTroughType *pos) -{ - gint return_val = FALSE; - switch (key->keyval) - { - case GDK_Left: - return_val = TRUE; - if (key->state & GDK_CONTROL_MASK) - *scroll = GTK_SCROLL_PAGE_BACKWARD; - else - *scroll = GTK_SCROLL_STEP_BACKWARD; - break; - case GDK_Right: - return_val = TRUE; - if (key->state & GDK_CONTROL_MASK) - *scroll = GTK_SCROLL_PAGE_FORWARD; - else - *scroll = GTK_SCROLL_STEP_FORWARD; - break; - case GDK_Home: - return_val = TRUE; - *pos = GTK_TROUGH_START; - break; - case GDK_End: - return_val = TRUE; - *pos = GTK_TROUGH_END; - break; - } - return return_val; -} +#define __GTK_HSCALE_C__ +#include "gtkaliasdef.c"