📄 gtkspinbutton.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GtkSpinButton widget for GTK+ * Copyright (C) 1998 Lars Hamann and Stefan Jeske * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * 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/. */#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <locale.h>#include "gdk/gdkkeysyms.h"#include "gtkspinbutton.h"#include "gtkmain.h"#include "gtksignal.h"#define MIN_SPIN_BUTTON_WIDTH 30#define ARROW_SIZE 11#define SPIN_BUTTON_INITIAL_TIMER_DELAY 200#define SPIN_BUTTON_TIMER_DELAY 20#define MAX_TEXT_LENGTH 256#define MAX_TIMER_CALLS 5#define EPSILON 1e-5enum { ARG_0, ARG_ADJUSTMENT, ARG_CLIMB_RATE, ARG_DIGITS, ARG_SNAP_TO_TICKS, ARG_NUMERIC, ARG_WRAP, ARG_UPDATE_POLICY, ARG_SHADOW_TYPE, ARG_VALUE};static void gtk_spin_button_class_init (GtkSpinButtonClass *klass);static void gtk_spin_button_init (GtkSpinButton *spin_button);static void gtk_spin_button_finalize (GtkObject *object);static void gtk_spin_button_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);static void gtk_spin_button_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);static void gtk_spin_button_map (GtkWidget *widget);static void gtk_spin_button_unmap (GtkWidget *widget);static void gtk_spin_button_realize (GtkWidget *widget);static void gtk_spin_button_unrealize (GtkWidget *widget);static void gtk_spin_button_size_request (GtkWidget *widget, GtkRequisition *requisition);static void gtk_spin_button_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static void gtk_spin_button_paint (GtkWidget *widget, GdkRectangle *area);static void gtk_spin_button_draw (GtkWidget *widget, GdkRectangle *area);static gint gtk_spin_button_expose (GtkWidget *widget, GdkEventExpose *event);static gint gtk_spin_button_button_press (GtkWidget *widget, GdkEventButton *event);static gint gtk_spin_button_button_release (GtkWidget *widget, GdkEventButton *event);static gint gtk_spin_button_motion_notify (GtkWidget *widget, GdkEventMotion *event);static gint gtk_spin_button_enter_notify (GtkWidget *widget, GdkEventCrossing *event);static gint gtk_spin_button_leave_notify (GtkWidget *widget, GdkEventCrossing *event);static gint gtk_spin_button_focus_out (GtkWidget *widget, GdkEventFocus *event);static void gtk_spin_button_draw_arrow (GtkSpinButton *spin_button, guint arrow);static gint gtk_spin_button_timer (GtkSpinButton *spin_button);static void gtk_spin_button_value_changed (GtkAdjustment *adjustment, GtkSpinButton *spin_button); static gint gtk_spin_button_key_press (GtkWidget *widget, GdkEventKey *event);static gint gtk_spin_button_key_release (GtkWidget *widget, GdkEventKey *event);static void gtk_spin_button_activate (GtkEditable *editable);static void gtk_spin_button_snap (GtkSpinButton *spin_button, gfloat val);static void gtk_spin_button_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position);static void gtk_spin_button_real_spin (GtkSpinButton *spin_button, gfloat step);static GtkEntryClass *parent_class = NULL;GtkTypegtk_spin_button_get_type (void){ static guint spin_button_type = 0; if (!spin_button_type) { static const GtkTypeInfo spin_button_info = { "GtkSpinButton", sizeof (GtkSpinButton), sizeof (GtkSpinButtonClass), (GtkClassInitFunc) gtk_spin_button_class_init, (GtkObjectInitFunc) gtk_spin_button_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; spin_button_type = gtk_type_unique (GTK_TYPE_ENTRY, &spin_button_info); } return spin_button_type;}static voidgtk_spin_button_class_init (GtkSpinButtonClass *class){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkEditableClass *editable_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; editable_class = (GtkEditableClass*) class; parent_class = gtk_type_class (GTK_TYPE_ENTRY); gtk_object_add_arg_type ("GtkSpinButton::adjustment", GTK_TYPE_ADJUSTMENT, GTK_ARG_READWRITE, ARG_ADJUSTMENT); gtk_object_add_arg_type ("GtkSpinButton::climb_rate", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_CLIMB_RATE); gtk_object_add_arg_type ("GtkSpinButton::digits", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_DIGITS); gtk_object_add_arg_type ("GtkSpinButton::snap_to_ticks", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SNAP_TO_TICKS); gtk_object_add_arg_type ("GtkSpinButton::numeric", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_NUMERIC); gtk_object_add_arg_type ("GtkSpinButton::wrap", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_WRAP); gtk_object_add_arg_type ("GtkSpinButton::update_policy", GTK_TYPE_SPIN_BUTTON_UPDATE_POLICY, GTK_ARG_READWRITE, ARG_UPDATE_POLICY); gtk_object_add_arg_type ("GtkSpinButton::shadow_type", GTK_TYPE_SHADOW_TYPE, GTK_ARG_READWRITE, ARG_SHADOW_TYPE); gtk_object_add_arg_type ("GtkSpinButton::value", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_VALUE); object_class->set_arg = gtk_spin_button_set_arg; object_class->get_arg = gtk_spin_button_get_arg; object_class->finalize = gtk_spin_button_finalize; widget_class->map = gtk_spin_button_map; widget_class->unmap = gtk_spin_button_unmap; widget_class->realize = gtk_spin_button_realize; widget_class->unrealize = gtk_spin_button_unrealize; widget_class->size_request = gtk_spin_button_size_request; widget_class->size_allocate = gtk_spin_button_size_allocate; widget_class->draw = gtk_spin_button_draw; widget_class->expose_event = gtk_spin_button_expose; widget_class->button_press_event = gtk_spin_button_button_press; widget_class->button_release_event = gtk_spin_button_button_release; widget_class->motion_notify_event = gtk_spin_button_motion_notify; widget_class->key_press_event = gtk_spin_button_key_press; widget_class->key_release_event = gtk_spin_button_key_release; widget_class->enter_notify_event = gtk_spin_button_enter_notify; widget_class->leave_notify_event = gtk_spin_button_leave_notify; widget_class->focus_out_event = gtk_spin_button_focus_out; editable_class->insert_text = gtk_spin_button_insert_text; editable_class->activate = gtk_spin_button_activate;}static voidgtk_spin_button_set_arg (GtkObject *object, GtkArg *arg, guint arg_id){ GtkSpinButton *spin_button; spin_button = GTK_SPIN_BUTTON (object); switch (arg_id) { GtkAdjustment *adjustment; case ARG_ADJUSTMENT: adjustment = GTK_VALUE_POINTER (*arg); if (!adjustment) adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); gtk_spin_button_set_adjustment (spin_button, adjustment); break; case ARG_CLIMB_RATE: gtk_spin_button_configure (spin_button, spin_button->adjustment, GTK_VALUE_FLOAT (*arg), spin_button->digits); break; case ARG_DIGITS: gtk_spin_button_configure (spin_button, spin_button->adjustment, spin_button->climb_rate, GTK_VALUE_UINT (*arg)); break; case ARG_SNAP_TO_TICKS: gtk_spin_button_set_snap_to_ticks (spin_button, GTK_VALUE_BOOL (*arg)); break; case ARG_NUMERIC: gtk_spin_button_set_numeric (spin_button, GTK_VALUE_BOOL (*arg)); break; case ARG_WRAP: gtk_spin_button_set_wrap (spin_button, GTK_VALUE_BOOL (*arg)); break; case ARG_UPDATE_POLICY: gtk_spin_button_set_update_policy (spin_button, GTK_VALUE_ENUM (*arg)); break; case ARG_SHADOW_TYPE: gtk_spin_button_set_shadow_type (spin_button, GTK_VALUE_ENUM (*arg)); break; case ARG_VALUE: gtk_spin_button_set_value (spin_button, GTK_VALUE_FLOAT (*arg)); break; default: break; }}static voidgtk_spin_button_get_arg (GtkObject *object, GtkArg *arg, guint arg_id){ GtkSpinButton *spin_button; spin_button = GTK_SPIN_BUTTON (object); switch (arg_id) { case ARG_ADJUSTMENT: GTK_VALUE_POINTER (*arg) = spin_button->adjustment; break; case ARG_CLIMB_RATE: GTK_VALUE_FLOAT (*arg) = spin_button->climb_rate; break; case ARG_DIGITS: GTK_VALUE_UINT (*arg) = spin_button->digits; break; case ARG_SNAP_TO_TICKS: GTK_VALUE_BOOL (*arg) = spin_button->snap_to_ticks; break; case ARG_NUMERIC: GTK_VALUE_BOOL (*arg) = spin_button->numeric; break; case ARG_WRAP: GTK_VALUE_BOOL (*arg) = spin_button->wrap; break; case ARG_UPDATE_POLICY: GTK_VALUE_ENUM (*arg) = spin_button->update_policy; break; case ARG_SHADOW_TYPE: GTK_VALUE_ENUM (*arg) = spin_button->shadow_type; break; case ARG_VALUE: GTK_VALUE_FLOAT (*arg) = spin_button->adjustment->value; break; default: arg->type = GTK_TYPE_INVALID; break; }}static voidgtk_spin_button_init (GtkSpinButton *spin_button){ spin_button->adjustment = NULL; spin_button->panel = NULL; spin_button->shadow_type = GTK_SHADOW_NONE; spin_button->timer = 0; spin_button->ev_time = 0; spin_button->climb_rate = 0.0; spin_button->timer_step = 0.0; spin_button->update_policy = GTK_UPDATE_ALWAYS; spin_button->in_child = 2; spin_button->click_child = 2; spin_button->button = 0; spin_button->need_timer = FALSE; spin_button->timer_calls = 0; spin_button->digits = 0; spin_button->numeric = FALSE; spin_button->wrap = FALSE; spin_button->snap_to_ticks = FALSE; gtk_spin_button_set_adjustment (spin_button, (GtkAdjustment*) gtk_adjustment_new (0, 0, 0, 0, 0, 0));}static voidgtk_spin_button_finalize (GtkObject *object){ g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (object)); gtk_object_unref (GTK_OBJECT (GTK_SPIN_BUTTON (object)->adjustment)); GTK_OBJECT_CLASS (parent_class)->finalize (object);}static voidgtk_spin_button_map (GtkWidget *widget){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget)) { GTK_WIDGET_CLASS (parent_class)->map (widget); gdk_window_show (GTK_SPIN_BUTTON (widget)->panel); }}static voidgtk_spin_button_unmap (GtkWidget *widget){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); if (GTK_WIDGET_MAPPED (widget)) { gdk_window_hide (GTK_SPIN_BUTTON (widget)->panel); GTK_WIDGET_CLASS (parent_class)->unmap (widget); }}static voidgtk_spin_button_realize (GtkWidget *widget){ GtkSpinButton *spin; GdkWindowAttr attributes; gint attributes_mask; guint real_width; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); spin = GTK_SPIN_BUTTON (widget); real_width = widget->allocation.width; widget->allocation.width -= ARROW_SIZE + 2 * widget->style->klass->xthickness; gtk_widget_set_events (widget, gtk_widget_get_events (widget) | GDK_KEY_RELEASE_MASK); GTK_WIDGET_CLASS (parent_class)->realize (widget); widget->allocation.width = real_width; attributes.window_type = GDK_WINDOW_CHILD; 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_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; attributes.x = (widget->allocation.x + widget->allocation.width - ARROW_SIZE - 2 * widget->style->klass->xthickness); attributes.y = widget->allocation.y + (widget->allocation.height - widget->requisition.height) / 2; attributes.width = ARROW_SIZE + 2 * widget->style->klass->xthickness; attributes.height = widget->requisition.height; spin->panel = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (spin->panel, widget); gtk_style_set_background (widget->style, spin->panel, GTK_STATE_NORMAL);}static voidgtk_spin_button_unrealize (GtkWidget *widget){ GtkSpinButton *spin; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); spin = GTK_SPIN_BUTTON (widget); GTK_WIDGET_CLASS (parent_class)->unrealize (widget); if (spin->panel) { gdk_window_set_user_data (spin->panel, NULL); gdk_window_destroy (spin->panel); spin->panel = NULL; }}static voidgtk_spin_button_size_request (GtkWidget *widget, GtkRequisition *requisition){ g_return_if_fail (widget != NULL); g_return_if_fail (requisition != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); requisition->width = MIN_SPIN_BUTTON_WIDTH + ARROW_SIZE + 2 * widget->style->klass->xthickness;}static voidgtk_spin_button_size_allocate (GtkWidget *widget, GtkAllocation *allocation){ GtkAllocation child_allocation; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); g_return_if_fail (allocation != NULL); child_allocation = *allocation; child_allocation.width -= ARROW_SIZE + 2 * widget->style->klass->xthickness; GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, &child_allocation); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) { child_allocation.width = ARROW_SIZE + 2 * widget->style->klass->xthickness; child_allocation.height = widget->requisition.height; child_allocation.x = (allocation->x + allocation->width - ARROW_SIZE - 2 * widget->style->klass->xthickness); child_allocation.y = allocation->y + (allocation->height - widget->requisition.height) / 2; gdk_window_move_resize (GTK_SPIN_BUTTON (widget)->panel, child_allocation.x, child_allocation.y, child_allocation.width, child_allocation.height); }}static voidgtk_spin_button_paint (GtkWidget *widget, GdkRectangle *area){ GtkSpinButton *spin; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SPIN_BUTTON (widget)); spin = GTK_SPIN_BUTTON (widget); if (GTK_WIDGET_DRAWABLE (widget)) { if (spin->shadow_type != GTK_SHADOW_NONE) gtk_paint_box (widget->style, spin->panel, GTK_STATE_NORMAL, spin->shadow_type, area, widget, "spinbutton", 0, 0, ARROW_SIZE + 2 * widget->style->klass->xthickness, widget->requisition.height); else { gdk_window_set_back_pixmap (spin->panel, NULL, TRUE); gdk_window_clear_area (spin->panel, area->x, area->y, area->width, area->height); } gtk_spin_button_draw_arrow (spin, GTK_ARROW_UP); gtk_spin_button_draw_arrow (spin, GTK_ARROW_DOWN); GTK_WIDGET_CLASS (parent_class)->draw (widget, area); }}static voidgtk_spin_button_draw (GtkWidget *widget, GdkRectangle *area){ g_return_if_fail (widget != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -