¸®´ª½º ±âŸ ÀÚ·á |
---|
Á¦¸ñ | gtk °Á #12 1998/07/10 (17:35) |
À̸§ | ±èÈ¿¿ø |
¹øÈ£ | 96 |
Á¶È¸ | 308 |
º»¹® |
*** *** 19-4.3. Dial WidgetÀÇ ±â¿ø *** Áö»óÀÇ ¸ðµç µ¿¹°µéÀÌ ÁøÈëÅÁ¿¡¼ óÀ½À¸·Î ±â¾î³ª¿Â ¾ç¼·ùÀÇ º¯Á¾µéÀÎ °Íó·³, Gtk widgetµéµµ ¸ÕÀú ¸¸µé¾îÁø widgetÀÇ º¯Çü¿¡¼ Ãâ¹ßÇÏ´Â °æÇâÀÌ ÀÖ´Ù. ±×·¡¼, ÀÌ Àý(section)ÀÌ "Creating a Widget from Scratch"¶ó´Â Á¦¸ñÀ¸·Î µÇ¾î ÀÖÀ½¿¡µµ, Dial widgetÀº ½ÇÁ¦·Î Range widgetÀÇ Äڵ忡¼ Ãâ¹ßÇÑ´Ù. ÀÌ´Â ¿ª½Ã Range widget¿¡¼ ÆÄ»ýµÈ Scale widgetµé°ú ¶È°°Àº ÀÎÅÍÆäÀ̽º¸¦, ¿ì¸®ÀÇ Dial widgetÀÌ °¡Áú ¼ö ÀÖ´Ù¸é ¸ÚÁú °ÍÀ̶ó´Â »ý°¢¿¡¼´Ù. ¶ÇÇÑ ¸¸¾à ¿©·¯ºÐÀÌ ¾îÇà Á¦ÀÛÀÚÀÇ °üÁ¡¿¡¼ scale widgetµéÀÇ ÀÛ¿ë¿¡ ´ëÇØ Àͼ÷ÇÏÁö ¾Ê´Ù¸é, ¸ÕÀú ±×µé¿¡ ´ëÇØ ¾Ë¾Æ º¸´Â °Íµµ ÁÁÀº »ý°¢ÀÏ °ÍÀÌ´Ù. *** *** 19-4.4. ±âÃÊ *** ¿ì¸® widgetÀÇ »ó´ç ºÎºÐÀº Tictactoe widget°ú ²Ï À¯»çÇÏ°Ô º¸ÀÏ °ÍÀÌ´Ù. ¸ÕÀú Çì´õ ÆÄÀÏÀ» º¸ÀÚ. /* 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 * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __GTK_DIAL_H__ #define __GTK_DIAL_H__ #include <gdk/gdk.h> #include <gtk/gtkadjustment.h> #include <gtk/gtkwidget.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define GTK_DIAL(obj) GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial) #define GTK_DIAL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass) #define GTK_IS_DIAL(obj) GTK_CHECK_TYPE (obj, gtk_dial_get_type ()) typedef struct _GtkDial GtkDial; typedef struct _GtkDialClass GtkDialClass; struct _GtkDial { GtkWidget widget; /* policy¸¦ ¾÷µ¥ÀÌÆ®ÇÑ´Ù(GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]). */ guint policy : 2; /* ÇöÀç ´·¯Áø ¹öÆ°, ´¸®Áö ¾Ê¾Ò´Ù¸é 0. */ guint8 button; /* ´ÙÀÌ¾ó ±¸¼º¿ä¼ÒµéÀÇ Ä¡¼ö. */ gint radius; gint pointer_width; /* ¾÷µ¥ÀÌÆ® ŸÀ̸ÓÀÇ ID, ¾÷µ¥ÀÌÆ®°¡ ¾øÀ¸¸é 0. */ guint32 timer; /* ÇöÀçÀÇ °¢µµ. */ gfloat angle; /* Adjustment°¡ ÀúÀåÇÑ ÀÌÀü °ªµé·Î, ¿ì¸®°¡ ¾î¶² º¯È¸¦ ¾Ë¾Æ³¾ ¼ö ÀÖ´Ù. */ gfloat old_value; gfloat old_lower; gfloat old_upper; /* ´ÙÀ̾óÀÇ µ¥ÀÌÅ͸¦ ÀúÀåÇÏ´Â adjustment object´Ù. */ GtkAdjustment *adjustment; }; struct _GtkDialClass { GtkWidgetClass parent_class; }; GtkWidget* gtk_dial_new (GtkAdjustment *adjustment); guint gtk_dial_get_type (void); GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial); void gtk_dial_set_update_policy (GtkDial *dial, GtkUpdateType policy); void gtk_dial_set_adjustment (GtkDial *dial, GtkAdjustment *adjustment); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __GTK_DIAL_H__ */ ÀÌ°ÍÀÌ ÀÌ widgetÀÇ ÀüºÎ°¡ ¾Æ´Ï°í µ¥ÀÌÅÍ ±¸Á¶Ã¼¿¡ ÇʵåµéÀÌ ´õ ÀÖÁö¸¸, ´Ù¸¥ °Íµé ¶ÇÇÑ ¿©±â º¸ÀÎ °Í°ú ºñ½ÁÇÏ´Ù. ÀÌÁ¦ Çì´õÆÄÀÏÀ» Æ÷ÇÔ(include)ÇÏ°í, ¸î °³ÀÇ »ó¼ö(constant)¸¦ ¼±¾ðÇÏ°í, widget¿¡ ´ëÇÑ Á¤º¸¸¦ Á¦°øÇÏ°í ±×°ÍÀ» ÃʱâÈÇØ ÁÖ´Â ÇÔ¼öµéÀÌ ÀÖ´Ù. #include <math.h> #include <stdio.h> #include <gtk/gtkmain.h> #include <gtk/gtksignal.h> #include "gtkdial.h" #define SCROLL_DELAY_LENGTH 300 #define DIAL_DEFAULT_SIZE 100 /* ¾Õ ºÎºÐÀÇ ¼±¾ðµé */ [ °ø°£À» ¾Æ³¢±â À§ÇØ »ý·«µÊ. ] /* ·ÎÄà µ¥ÀÌÅÍ */ static GtkWidgetClass *parent_class = NULL; guint gtk_dial_get_type () { static guint dial_type = 0; if (!dial_type) { GtkTypeInfo dial_info = { "GtkDial", sizeof (GtkDial), sizeof (GtkDialClass), (GtkClassInitFunc) gtk_dial_class_init, (GtkObjectInitFunc) gtk_dial_init, (GtkArgFunc) NULL, }; dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info); } return dial_type; } static void gtk_dial_class_init (GtkDialClass *class) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; parent_class = gtk_type_class (gtk_widget_get_type ()); object_class->destroy = gtk_dial_destroy; widget_class->realize = gtk_dial_realize; widget_class->expose_event = gtk_dial_expose; widget_class->size_request = gtk_dial_size_request; widget_class->size_allocate = gtk_dial_size_allocate; widget_class->button_press_event = gtk_dial_button_press; widget_class->button_release_event = gtk_dial_button_release; widget_class->motion_notify_event = gtk_dial_motion_notify; } static void gtk_dial_init (GtkDial *dial) { dial->button = 0; dial->policy = GTK_UPDATE_CONTINUOUS; dial->timer = 0; dial->radius = 0; dial->pointer_width = 0; dial->angle = 0.0; dial->old_value = 0.0; dial->old_lower = 0.0; dial->old_upper = 0.0; dial->adjustment = NULL; } GtkWidget* gtk_dial_new (GtkAdjustment *adjustment) { GtkDial *dial; dial = gtk_type_new (gtk_dial_get_type ()); if (!adjustment) adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); gtk_dial_set_adjustment (dial, adjustment); return GTK_WIDGET (dial); } static void gtk_dial_destroy (GtkObject *object) { GtkDial *dial; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_DIAL (object)); dial = GTK_DIAL (object); if (dial->adjustment) gtk_object_unref (GTK_OBJECT (dial->adjustment)); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } ÀÌ°Ç ÇÕ¼º widgetÀÌ ¾Æ´Ï¹Ç·Î ¿©±â¼ÀÇ init()ÇÔ¼ö´Â Tictactoe widget¿¡ ´ëÇؼº¸´Ù ´õ ÀûÀº ÀÛ¾÷À» ÇàÇÑ´Ù. ±×¸®°í ÀÎÀÚ¸¦ °¡Áö°Ô µÇ¾úÀ¸¹Ç·Î new() ÇÔ¼ö´Â ´õ ¸¹Àº ÀÛ¾÷À» ÇÑ´Ù. ¶ÇÇÑ, ¿ì¸®°¡ Adjustment object¸¦ ÇâÇÑ Æ÷ÀÎÅ͸¦ ÀúÀåÇÒ ¶§¸¶´Ù ±×°ÍÀÇ reference count¸¦ Áõ°¡½ÃÅ´À» ±â¾ïÇ϶ó. (ÀÌ°ÍÀ» ´õÀÌ»ó ÀÌ¿ëÇÏÁö ¾ÊÀ» ¶§´Â ¹Ý´ë·Î °¨¼Ò½ÃŲ´Ù.) ±×·¡¼ GTK´Â ±×°ÍÀÌ ¾ÈÀüÇÏ°Ô Æı«µÉ ¼ö ÀÖµµ·Ï Æ®·¢À» À¯ÁöÇÒ ¼ö ÀÖ´Ù. WidgetÀÇ ¿É¼ÇÀ» ´Ù·ê ¼ö ÀÖ´Â ¸î °³ÀÇ ÇÔ¼öµµ ÀÖ´Ù. GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial) { g_return_val_if_fail (dial != NULL, NULL); g_return_val_if_fail (GTK_IS_DIAL (dial), NULL); return dial->adjustment; } void gtk_dial_set_update_policy (GtkDial *dial, GtkUpdateType policy) { g_return_if_fail (dial != NULL); g_return_if_fail (GTK_IS_DIAL (dial)); dial->policy = policy; } void gtk_dial_set_adjustment (GtkDial *dial, GtkAdjustment *adjustment) { g_return_if_fail (dial != NULL); g_return_if_fail (GTK_IS_DIAL (dial)); if (dial->adjustment) { gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial); gtk_object_unref (GTK_OBJECT (dial->adjustment)); } dial->adjustment = adjustment; gtk_object_ref (GTK_OBJECT (dial->adjustment)); gtk_signal_connect (GTK_OBJECT (adjustment), "changed", (GtkSignalFunc) gtk_dial_adjustment_changed, (gpointer) dial); gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", (GtkSignalFunc) gtk_dial_adjustment_value_changed, (gpointer) dial); dial->old_value = adjustment->value; dial->old_lower = adjustment->lower; dial->old_upper = adjustment->upper; gtk_dial_update (dial); } *** *** 19-4.5. gtk_dial_realize() *** ÀÌÁ¦ »õ·Î¿î ŸÀÔÀÇ ÇÔ¼öµéÀ» ¸¸³ªº¸ÀÚ. ¸ÕÀú, XÀ©µµ¸¦ ¸¸µå´Â ÀÛ¾÷À» ÇØÁÖ´Â ÇÔ¼ö´Ù. ÇÔ¼ö gdk_window_new()·Î ÇÑ ¸¶½ºÅ©°¡ ³Ñ°ÜÁø °ÍÀ» ÁÖ¸ñÇ϶ó. ÀÌ°ÍÀº GdkWindowAttr ±¸Á¶Ã¼ÀÇ ¾î´À Çʵ尡 ½ÇÁ¦·Î µ¥ÀÌÅ͸¦ °¡Áú °ÍÀÎÁö ¼³Á¤ÇØ ÁÖ´Â °ÍÀÌ´Ù. ³ª¸ÓÁö ÇʵåµéÀº µðÆúÆ® °ªÀ¸·Î ä¿öÁö°Ô µÈ´Ù. ¶ÇÇÑ ´«¿©°Ü ºÁµÑ ¸¸ÇÑ °ÍÀº widgetÀÇ À̺¥Æ® ¸¶½ºÅ©°¡ ¼³Á¤µÇ´Â ¹æ¹ýÀÌ´Ù. ¿ì¸®´Â gtk_widget_get_ events()·Î½á ÀÌ widget¿¡ ´ëÇØ »ç¿ëÀÚ°¡ ¼³Á¤ÇØ ³õÀº À̺¥Æ® ¸¶½ºÅ©¸¦ º¹±¸ÇØ ÁÙ ¼ö ÀÖ´Ù(gtk_widget_set_events()·Î, ±×¸®°í ¿ì¸®°¡ ¿øÇÏ´Â À̺¥Æ®¸¦ ´õÇØ ÁØ´Ù). À©µµ¸¦ ¸¸µé¾ú´Ù¸é, ¿ì¸®´Â ±×°ÍÀÇ ½ºÅ¸ÀÏ°ú ¹è°æÀ» ¼¼ÆÃÇÏ°í, ±×¸®°í ±× widgetÀ» ÇâÇÑ Æ÷ÀÎÅ͸¦ GdkWindowÀÇ user data Çʵ忡 ³õ´Â´Ù. ÀÌ ¸¶Áö¸· ´Ü°è´Â GTK°¡ ÀûÀýÇÑ widgetÀ¸·Î ÀÌ À©µµ¿¡ ´ëÇÑ À̺¥Æ®¸¦ ÀüÆÄÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. static void gtk_dial_realize (GtkWidget *widget) { GtkDial *dial; GdkWindowAttr attributes; gint attributes_mask; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_DIAL (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); dial = GTK_DIAL (widget); 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.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_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_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; widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_user_data (widget->window, widget); gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); } *** *** 19.4.6. Å©±â °áÁ¤ *** ¾î¶² widgetÀ» Æ÷ÇÔÇÑ À©µµ°¡ óÀ½ º¸¿©Áö°Ô µÇ±â¿¡ ¾Õ¼, ±×¸®°í À©µµÀÇ layoutÀÌ º¯ÇßÀ» ¶§µµ ¾ðÁ¦³ª, GTK´Â ±×°ÍÀÇ ±â´ëµÈ Å©±â´ë·Î °¢ child widgetÀ» ¿ä±¸ÇÑ´Ù. ÀÌ ¿äûÀº ÇÔ¼ö gtk_dial_size_request()¿¡ ÀÇÇØ ´Ù·ç¾îÁø´Ù. ¿ì¸® widgetÀº ÄÁÅ×ÀÌ³Ê widgetÀÌ ¾Æ´Ï°í ¶Ç Å©±â¿¡ ´ëÇØ ¾î¶² Á¦ÇÑ Á¶°Çµµ ¾øÀ¸¹Ç·Î, ¿ì¸®´Â ´ÜÁö ÇÕ´çÇÑ µðÆúÆ® °ªÀ» ¸®ÅÏÇØ ÁØ´Ù. static void gtk_dial_size_request (GtkWidget *widget, GtkRequisition *requisition) { requisition->width = DIAL_DEFAULT_SIZE; requisition->height = DIAL_DEFAULT_SIZE; } ¸ðµç widgetµéÀÌ ÀÌ»óÀûÀÎ Å©±â·Î ¿äûµÈ ÈÄ, À©µµÀÇ layoutÀÌ °è»êµÇ°í °¢ child widgetÀº ±×°ÍÀÇ ½ÇÁ¦ Å©±â·Î ÅëÁö¹Þ´Â´Ù. º¸Åë ÀÌ°ÍÀº ÃÖ¼ÒÇÑ ¿äûµÈ Å©±â¸¸Å µÈ´Ù. ÇÏÁö¸¸ »ç¿ëÀÚ°¡ À©µµ¸¦ resizeÇÏ´Â °æ¿ìó·³, °£È¤ ¿äûµÈ Å©±âº¸´Ù ÀÛ¾ÆÁú ¶§µµ ÀÖ´Ù. Å©±âÀÇ ÅëÁö(notification)´Â ÇÔ¼ö gtk_dial_size_ allocate()·Î ´Ù·é´Ù. ¾ÕÀ¸·ÎÀÇ ÀÌ¿ëÀ» À§ÇØ ÀϺΠ±¸¼º ¿ä¼Ò Á¶°¢µéÀÇ Å©±â¸¦ °è»êÇÒ »Ó ¾Æ´Ï¶ó, À̵é ÇÔ¼öµéÀº »õ·Î¿î À§Ä¡¿Í Å©±â·Î widgetÀÇ XÀ©µµ¸¦ ¿Å°Ü ÁÖ´Â ¿ªÇÒÀ» ÇÑ´Ù´Â °ÍÀ» ±â¾ïÇÏÀÚ. static void gtk_dial_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkDial *dial; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_DIAL (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) { dial = GTK_DIAL (widget); gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); dial->radius = MAX(allocation->width,allocation->height) * 0.45; dial->pointer_width = dial->radius / 5; } } *** *** 19-4.7. gtk_dial_expose() *** ¾Õ¿¡¼ ¾ð±ÞÇßµíÀÌ, ÀÌ widgetÀÇ ¸ðµç ±×¸®±â ÀÛ¾÷Àº expose À̺¥Æ®¿¡ ´ëÇÑ Çڵ鷯¿¡¼ ÇàÇØÁø´Ù. ¿©±â¼ ÁÖ¸ñÇÒ °ÍÀº ÇÑ °¡Áö »ÓÀÌ´Ù. WidgetÀÇ ½ºÅ¸ÀÏ¿¡ ÀúÀåµÈ »ö±òµé¿¡ µû¶ó 3Â÷¿øÀ¸·Î ±×¸²ÀÚ Áø Æ÷ÀÎÅ͸¦ ±×¸®±â À§ÇØ, gtk_draw_ polygonÀ» ÀÌ¿ëÇÑ´Ù´Â °ÍÀÌ´Ù. static gint gtk_dial_expose (GtkWidget *widget, GdkEventExpose *event) { GtkDial *dial; GdkPoint points[3]; gdouble s,c; gdouble theta; gint xc, yc; gint tick_length; gint i; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (event->count > 0) return FALSE; dial = GTK_DIAL (widget); gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height); xc = widget->allocation.width/2; yc = widget->allocation.height/2; /* ½Ã°è ´«±ÝÀ» ±×¸°´Ù. */ for (i=0; i<25; i++) { theta = (i*M_PI/18. - M_PI/6.); s = sin(theta); c = cos(theta); tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2; gdk_draw_line (widget->window, widget->style->fg_gc[widget->state], xc + c*(dial->radius - tick_length), yc - s*(dial->radius - tick_length), xc + c*dial->radius, yc - s*dial->radius); } /* Æ÷ÀÎÅ͸¦ ±×¸°´Ù. */ s = sin(dial->angle); c = cos(dial->angle); points[0].x = xc + s*dial->pointer_width/2; points[0].y = yc + c*dial->pointer_width/2; points[1].x = xc + c*dial->radius; points[1].y = yc - s*dial->radius; points[2].x = xc - s*dial->pointer_width/2; points[2].y = yc - c*dial->pointer_width/2; gtk_draw_polygon (widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, points, 3, TRUE); return FALSE; } *** *** 19-4.8. À̺¥Æ® ´Ù·ç±â *** WidgetÀÇ Äڵ忡¼ ³ª¸ÓÁö ÄÚµå´Â ´Ù¾çÇÑ ÇüÅÂÀÇ À̺¥Æ®¸¦ ´Ù·é´Ù. ¶ÇÇÑ ÀÌ°ÍÀº ¼ö¸¹Àº GTK ¾îÇÃµé »çÀÌ¿¡¼ ±×´ÙÁö Å« Â÷ÀÌ°¡ ³ªÁö ¾Ê´Â´Ù. À̺¥Æ®´Â Å©°Ô µÎ°¡Áö ÇüÅ·Π³ª´ ¼ö ÀÖ´Ù. ¸ÕÀú »ç¿ëÀÚ°¡ widget À§¿¡¼ ¸¶¿ì½º¸¦ Ŭ¸¯Çϰųª Æ÷ÀÎÅ͸¦ À̵¿½ÃÅ°·Á°í µå·¡±×¸¦ ÇÒ ¼ö ÀÖ´Ù. ±×¸®°í ¿ÜºÎÀûÀÎ »óȲ¿¡ ÀÇÇØ, Adjustment objectÀÇ °ªÀÌ º¯ÇØ ¹ö¸± °æ¿ì°¡ ÀÖ´Ù. »ç¿ëÀÚ°¡ widget À§¿¡¼ Ŭ¸¯À» Çϸé, ¿ì¸®´Â Ŭ¸¯ÀÌ ÀûÀýÈ÷ Æ÷ÀÎÅÍ ±Ùó¿¡¼ ÀÌ·ç¾îÁ³´ÂÁö üũÇÏ°í, ¸¸¾à ±×·¸´Ù¸é widget ±¸Á¶Ã¼ÀÇ ¹öÆ° Çʵ忡 ±× ´·ÁÁø ¹öÆ°À» ÀúÀåÇÏ°í, ±×¸®°í gtk_grab_add() È£Ãâ·Î½á ¸ðµç ¸¶¿ì½º À̺¥Æ®¸¦ Àâ¾Æ æ´Ù. µÚµû¸£´Â ¸¶¿ì½ºÀÇ µ¿ÀÛÀº Á¦¾î°ªµéÀÌ ´Ù½Ã °è»êµÇ¾îÁö°Ô ÇÑ´Ù(gtk_dial_ update_mouseÇÔ¼ö·Î½á). ¼¼ÆÃµÈ policy¿¡ µû¶ó, "value_changed" À̺¥Æ®´Â ´Ù¸£°Ô ¹ß»ýÇÑ´Ù. Áï GTK_UPDATE_CONTINUOUSÀÏ °æ¿ì¿£ ¿¬¼ÓÀûÀ¸·Î °è¼Ó ¹ß»ýÇÏ°í, GTK_ UPDATE_DELAYEDÀÏ °æ¿ì¿£ ÇÔ¼ö gtk_timeout_add()·Î ´õÇØÁö´Â ŸÀ̸Ӹ¸Å Áö¿¬µÇ¸ç ¹ß»ýÇϸç, GTK_UPDATE_DISCONTINUOUSÀÏ °æ¿ì¿£ ¹öÆ°ÀÌ releaseµÇ´Â ¼ø°£¿¡¸¸ ¹ß»ý ÇÑ´Ù. static gint gtk_dial_button_press (GtkWidget *widget, GdkEventButton *event) { GtkDial *dial; gint dx, dy; double s, c; double d_parallel; double d_perpendicular; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); dial = GTK_DIAL (widget); /* ¹öÆ°ÀÇ ´¸²ÀÌ Æ÷ÀÎÅÍ ¿µ¿ª ³»ºÎ¿¡¼ ÀÌ·ç¾îÁ³³ª üũÇÑ´Ù. * ÀÌ°ÍÀº Æ÷ÀÎÅÍÀÇ À§Ä¡¿Í ¸¶¿ì½º°¡ ´·¯Áø À§Ä¡ÀÇ ¼öÁ÷ ¹× ¼öÆò °Å¸®¸¦ * °è»êÇÔÀ¸·Î½á ÀÌ·ç¾îÁø´Ù. */ dx = event->x - widget->allocation.width / 2; dy = widget->allocation.height / 2 - event->y; s = sin(dial->angle); c = cos(dial->angle); d_parallel = s*dy + c*dx; d_perpendicular = fabs(s*dx - c*dy); if (!dial->button && (d_perpendicular < dial->pointer_width/2) && (d_parallel > - dial->pointer_width)) { gtk_grab_add (widget); dial->button = event->button; gtk_dial_update_mouse (dial, event->x, event->y); } return FALSE; } static gint gtk_dial_button_release (GtkWidget *widget, GdkEventButton *event) { GtkDial *dial; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); dial = GTK_DIAL (widget); if (dial->button == event->button) { gtk_grab_remove (widget); dial->button = 0; if (dial->policy == GTK_UPDATE_DELAYED) gtk_timeout_remove (dial->timer); if ((dial->policy != GTK_UPDATE_CONTINUOUS) && (dial->old_value != dial->adjustment->value)) gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } return FALSE; } static gint gtk_dial_motion_notify (GtkWidget *widget, GdkEventMotion *event) { GtkDial *dial; GdkModifierType mods; gint x, y, mask; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); dial = GTK_DIAL (widget); if (dial->button != 0) { x = event->x; y = event->y; if (event->is_hint || (event->window != widget->window)) gdk_window_get_pointer (widget->window, &x, &y, &mods); switch (dial->button) { case 1: mask = GDK_BUTTON1_MASK; break; case 2: mask = GDK_BUTTON2_MASK; break; case 3: mask = GDK_BUTTON3_MASK; break; default: mask = 0; break; } if (mods & mask) gtk_dial_update_mouse (dial, x,y); } return FALSE; } static gint gtk_dial_timer (GtkDial *dial) { g_return_val_if_fail (dial != NULL, FALSE); g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE); if (dial->policy == GTK_UPDATE_DELAYED) gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); return FALSE; } static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y) { gint xc, yc; gfloat old_value; g_return_if_fail (dial != NULL); g_return_if_fail (GTK_IS_DIAL (dial)); xc = GTK_WIDGET(dial)->allocation.width / 2; yc = GTK_WIDGET(dial)->allocation.height / 2; old_value = dial->adjustment->value; dial->angle = atan2(yc-y, x-xc); if (dial->angle < -M_PI/2.) dial->angle += 2*M_PI; if (dial->angle < -M_PI/6) dial->angle = -M_PI/6; if (dial->angle > 7.*M_PI/6.) dial->angle = 7.*M_PI/6.; dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) * (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.); if (dial->adjustment->value != old_value) { if (dial->policy == GTK_UPDATE_CONTINUOUS) { gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } else { gtk_widget_draw (GTK_WIDGET(dial), NULL); if (dial->policy == GTK_UPDATE_DELAYED) { if (dial->timer) gtk_timeout_remove (dial->timer); dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH, (GtkFunction) gtk_dial_timer, (gpointer) dial); } } } } ±×¸®°í ¿ÜºÎ ¿äÀο¡ ÀÇÇÑ AdjustmentÀÇ º¯ÈµéÀº 'changed'¿Í 'value_changed' ½Ã±×³ÎÀ» ÅëÇØ ¿ì¸® widget¿¡ Àü´ÞµÇ´Â °ÍÀÌ´Ù. ÀÌ·± ÇÔ¼öµéÀ» À§ÇÑ Çڵ鷯µéÀº gtk_dial_update()¸¦ È£ÃâÇؼ, ÀÎÀÚµéÀ» È®ÀÎÇÏ°í, »õ·Î¿î Æ÷ÀÎÅÍ °¢µµ¸¦ °è»ê ÇÏ°í, ±×¸®°í widgetÀ» ´Ù½Ã ±×·ÁÁØ´Ù(gtk_widget_draw()¸¦ È£ÃâÇؼ). static void gtk_dial_update (GtkDial *dial) { gfloat new_value; g_return_if_fail (dial != NULL); g_return_if_fail (GTK_IS_DIAL (dial)); new_value = dial->adjustment->value; if (new_value < dial->adjustment->lower) new_value = dial->adjustment->lower; if (new_value > dial->adjustment->upper) new_value = dial->adjustment->upper; if (new_value != dial->adjustment->value) { dial->adjustment->value = new_value; gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed"); } dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. / (dial->adjustment->upper - dial->adjustment->lower); gtk_widget_draw (GTK_WIDGET(dial), NULL); } static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment, gpointer data) { GtkDial *dial; g_return_if_fail (adjustment != NULL); g_return_if_fail (data != NULL); dial = GTK_DIAL (data); if ((dial->old_value != adjustment->value) || (dial->old_lower != adjustment->lower) || (dial->old_upper != adjustment->upper)) { gtk_dial_update (dial); dial->old_value = adjustment->value; dial->old_lower = adjustment->lower; dial->old_upper = adjustment->upper; } } static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) { GtkDial *dial; g_return_if_fail (adjustment != NULL); g_return_if_fail (data != NULL); dial = GTK_DIAL (data); if (dial->old_value != adjustment->value) { gtk_dial_update (dial); dial->old_value = adjustment->value; } } *** *** 19-4.9. °¡´ÉÇÑ ±â´ÉÇâ»óµé *** ¿ì¸®°¡ ºÃµíÀÌ Dial widgetÀº ¾à 670ÁÙÀÇ Äڵ带 °¡Áö°í ÀÖ´Ù. ƯÈ÷ ÀÌ ÄÚµå ±æÀÌÀÇ ´ëºÎºÐÀÌ Çì´õ¿Í º¸ÀÏ·¯ÆÇ(boiler plate)À̱⠶§¹®¿¡, ¿ì¸®´Â ÀÌ ±ä ÄÚµå ¿¡¼ ²Ï ¸¹Àº °ÍÀ» ¹è¿ï ¼ö ÀÖ¾ú´Ù. ±×·¯³ª ÀÌ widget¿¡ ´ëÇØ °¡´ÉÇÑ ¸î °¡Áö ±â´É°³¼±ÀÌ ÀÖ´Ù. o ÀÌ widgetÀ» ½ÇÁ¦·Î ±¸ÇöÇØ º¸¸é, Æ÷ÀÎÅÍ°¡ µå·¡±×µÇ¸é¼ ¾à°£ÀÇ ¹ø½°Å¸²ÀÌ ÀÖÀ½À» ¹ß°ßÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ÀÌ°ÍÀº Æ÷ÀÎÅÍ°¡ À̵¿ÇÒ ¶§¸¶´Ù redrawµÇ±â ÀÌÀü¿¡ widget Àüü°¡ Áö¿öÁö±â ¶§¹®ÀÌ´Ù. ÀÌ ¹®Á¦¸¦ ÇØ°áÇÏ´Â °¡Àå ÁÁÀº ¹æ¹ýÀº º¸ÀÌÁö ¾Ê´Â(offscreen) ÇȽº¸Ê¿¡ ±×·ÁÁÖ°í, ±×¸®°í´Â ÃÖÁ¾ °á°ú¹°À» ½ºÅ©¸° À§·Î ´Ü¹ø¿¡ º¹»çÇØ ÁÖ´Â °ÍÀÌ´Ù. (ÁøÇื´ë(progress bar) widgetÀÌ ÀÌ·± ½ÄÀ¸·Î º¸¿©Á³¾ú´Ù.) o »ç¿ëÀÚ´Â °ªÀ» º¯È½ÃÅ°±â À§Çؼ up ¹× down È»ìǥŰ(arrow key)¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ¾î¾ß ÇÒ °ÍÀÌ´Ù. o ¿ì¸® widgetÀÌ Å©°Å³ª ÀÛÀº ÆøÀ¸·Î °ªÀ» Áõ°¨½Ãų ¼ö ÀÖ´Â ¹öÆ°À» °¡Áø´Ù¸é ±¦ÂúÀº ±â´ÉÀÌ µÉ °ÍÀÌ´Ù. À̸¦ À§ÇØ ³»ÀåµÈ ¹öÆ° widgetÀ» ÀÌ¿ëÇÏ´Â °Íµµ °¡´ÉÇÏ°ÚÁö¸¸, ¿ì¸®´Â ¶ÇÇÑ ÀÌ ¹öÆ°µéÀÌ °è¼Ó ´·¯Áø »óÅ¿¡¼ auto-repeat µÇµµ·Ï ÇÏ°í½Í´Ù, ½ºÅ©·Ñ¹Ù¿¡ ÀÖ´Â È»ìÇ¥µéó·³. ÀÌ·± ½ÄÀÇ µ¿ÀÛµéÀ» °®Ãß°Ô ÇØÁÖ´Â ´ëºÎºÐÀÇ ÄÚµå´Â GtkRange widget¿¡¼ ãÀ» ¼ö ÀÖ´Ù. o ´ÙÀ̾ó(Dial) widgetÀº ¾Õ¿¡¼ ¾ð±ÞµÈ ¹öÆ°µéÀÇ ¹Ù´Ú¿¡ À§Ä¡ÇÑ ÇϳªÀÇ child widgetÀ» °¡Áø, ÄÁÅ×ÀÌ³Ê widgetÀ¸·Î ¸¸µé¾îÁú ¼ö ÀÖ´Ù. ±×·¯¸é »ç¿ëÀÚ´Â ´ÙÀ̾óÀÇ ÇöÀç°ªÀ» º¸À̱â À§ÇØ ¿øÇÏ´Â ¶óº§À̳ª ¿£Æ®¸® widgetÀ» ´õÇØÁÙ ¼ö ÀÖ´Ù. *** *** 19-5. ´õ ¹è¿öº¸±â *** WidgetÀ» ¸¸µé±â À§ÇÑ ¼ö¸¹Àº Ç׸ñµé Áß ±ØÈ÷ ÀϺθ¸ÀÌ À§¿¡¼ ¼Ò°³µÇ¾ú´Ù. ÀÚ½ÅÀÇ widgetÀ» ¸¸µé·Á´Â ÀÌ¿¡°Ô, °¡Àå ÁÁÀº ¼Ò½º´Â GTK ±× ÀÚüÀÏ °ÍÀÌ´Ù. ¿©·¯ºÐÀÌ ¸¸µé·Á´Â widget¿¡ ´ëÇØ ½º½º·Î ¸î°¡Áö Áú¹®À» Çغ¸ÀÚ. ÀÌ°ÍÀº Container widgetÀΰ¡? ÀÌ°ÍÀº °ü·ÃµÈ À©µµ¸¦ °¡Áö°í Àִ°¡? ÀÌ°ÍÀº ÀÌ¹Ì Á¸ÀçÇÏ´Â widgetÀÇ º¯ÇüÀΰ¡? ±×¸®°í´Â À¯»çÇÑ widgetÀ» ã°í, º¯È¸¦ Áֱ⠽ÃÀÛÇÏ´Â °ÍÀÌ´Ù. Çà¿îÀ» ºó´Ù! |