ºñ·Ï GTK ¹èÆ÷ÆÇ¿¡ Æ÷ÇԵǾî ÀÖ´Â ¼ö¸¹Àº widgetµéÀÌ ´ëºÎºÐÀÇ ±âº»ÀûÀÎ
¿ä±¸»çÇ×À» ÃæÁ·½ÃÄÑ ÁÖÁö¸¸, ¾ðÁ¨°¡ ½º½º·Î »õ·Î¿î widgetÀ» ¸¸µé¾î¾ß ÇÒ ¶§°¡
¿Ã °ÍÀÌ´Ù. GTK°¡ widgetÀÇ »ó¼ÓÀ» ±¤¹üÀ§ÇÏ°Ô ÀÌ¿ëÇÏ°í ¶Ç ÀÌ ¸¸µé¾îÁ® ÀÖ´Â
widgetµéÀÌ ¿©·¯ºÐÀÇ ¿ä±¸¿¡ ±ÙÁ¢ÇÑ °ÍµéÀ̱⠶§¹®¿¡, À¯¿ëÇÏ°í »õ·Î¿î widgetÀ»
¸¸µå´Â °Íµµ ´ÜÁö ¸î ÁÙÀÇ ÄÚµå·Î½á °¡´ÉÇÒ ¼öµµ ÀÖ´Ù. ±×·¯³ª »õ·Î¿î widgetÀ»
¸¸µå´Â ÀÛ¾÷À» ½ÃÀÛÇϱâ Àü¿¡, ¸ÕÀú ´©±º°¡ ±×°ÍÀ» ÀÌ¹Ì ¸¸µé¾î ³õÁö ¾Ê¾Ò´ÂÁö
üũÇÏÀÚ. ÀÌ·¸°Ô Çؼ ³ë·ÂÀÇ Áߺ¹À» ¸·°í ¶Ç GTK widgetÀÇ °¹¼ö¸¦ ÃÖ¼ÒÇÑÀ¸·Î
À¯ÁöÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ¼·Î ´Ù¸¥ ¾îÇÃµé »çÀÌ¿¡¼ ÄÚµå¿Í ÀÎÅÍÆäÀ̽º ¸ðµÎÀÇ
ÅëÀϼºÀ» À¯ÁöÇÏ´Â °ÍÀÌ´Ù. ÀÌ·¸°Ô ÇÏ´Â ÇÑ°¡Áö ¹æ¹ýÀ¸·Î, ¸¸¾à ¿©·¯ºÐÀÌ
ÀڽŸ¸ÀÇ widgetÀ» ¿Ï¼ºÇÏ°Ô µÇ¸é, ±×°ÍÀ» ´Ù¸¥ »ç¶÷µé ¸ðµÎ ÀÌ¿ëÇÒ ¼ö ÀÖ°Ô
¼¼°è¿¡ ³Î¸® ¾Ë¸®ÀÚ. ÀÌ·¸°Ô ÇÒ ¼ö ÀÖ´Â °¡Àå ÁÁÀº Àå¼Ò´Â ¾Æ¸¶ gtk-list
ÀÏ
°ÍÀÌ´Ù.
¿¹Á¦µéÀÇ ¿ÏÀüÇÑ ¼Ò½º ÄÚµå´Â ´ç½ÅÀÌ ÀÌ ¹®¼¸¦ ±¸ÇÑ °÷À̳ª ¶Ç´Â ´ÙÀ½ Àå¼Ò¿¡¼ ±¸ÇÒ ¼ö ÀÖ´Ù.
http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial
»õ·Î¿î widgetÀ» ¸¸µå´Â µ¥ ÀÖ¾î¼, GTK objectµéÀÌ ¾î¶»°Ô µ¿ÀÛÇÏ´ÂÁö ÀÌÇØ ÇÏ´Â °ÍÀÌ Áß¿äÇÒ °ÍÀÌ´Ù. À̹ø ¼½¼ÇÀº ´ÜÁö ª¸·ÇÑ °³¿ä¸¸À» ¼Ò°³ÇÏ°íÀÚ ÇÑ´Ù. ÀÚ¼¼ÇÑ °ÍÀº Âü°í ¹®¼¸¦ º¸¶ó.
GTK widgetµéÀº °´Ã¼ÁöÇâÀû ¹æ¹ýÀ» ÁöÇâÇÑ´Ù. ±×·¯³ª, ±×µéÀº Ç¥ÁØ C·Î ¾²¿©Áø´Ù. ÀÌ°ÍÀº ÇöÀç ¼öÁØÀÇ C++ ÄÄÆÄÀÏ·¯¸¦ ¾²´Â °Íº¸´Ù À̽ļº°ú ¾ÈÁ¤¼ºÀ» Å©°Ô Çâ»ó½ÃŲ´Ù. ÇÏÁö¸¸ ÀÌ°ÍÀº widget ÀÛ¼ºÀÚ°¡ ¸î¸î ¼¼ºÎÀûÀÎ °÷¿¡ ÁÖÀǸ¦ ±â¿ï¿©¾ß¸¸ ÇÏ´Â °ÍÀ» ÀǹÌÇÑ´Ù. ÇÑ Å¬·¡½ºÀÇ widgetµé(¿¹¸¦ µéÀÚ¸é ¸ðµç Button widgetµé)ÀÇ instanceµé ¸ðµÎ¿¡ °øÅëÀûÀÎ Á¤º¸´Â class structure¿¡ ÀúÀåµÇ¾î ÀÖ´Ù. ÀÌ classÀÇ ½Ã±×³ÎµéÀº ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅÍ, Áï callback ÇÔ¼ö·Î ó¸® µÇ°í, C++¿¡¼ÀÇ virtual ÇÔ¼öó·³ ÇϳªÀÇ º¹»çº»¸¸ÀÌ Á¸ÀçÇØ ÁØ´Ù. »ó¼ÓÀ» Áö¿øÇϱâ À§Çؼ, class structureÀÇ Ã¹¹ø° Çʵå´Â parent class structureÀÇ copy°¡ µÇ¾î¾ß ÇÑ´Ù. GtkButtonÀ̶ó´Â class structureÀÇ ¼±¾ðÀº ÀÌ·¸°Ô µÈ´Ù.
struct _GtkButtonClass
{
GtkContainerClass parent_class;
void (* pressed) (GtkButton *button);
void (* released) (GtkButton *button);
void (* clicked) (GtkButton *button);
void (* enter) (GtkButton *button);
void (* leave) (GtkButton *button);
};
¹öÆ°ÀÌ ÇϳªÀÇ ÄÁÅ×À̳ʷΠ´Ù·ç¾îÁø´Ù¸é(¿¹¸¦µé¾î, resizeµÇ¾úÀ» ¶§), ±×°ÍÀÇ class structure´Â GtkContainerClass·Î ij½ºÆ®µÉ ¼ö ÀÖ°í, ¶Ç ½Ã±×³ÎµéÀ» ´Ù·ç±â À§ÇØ °ü·ÃµÈ ÇʵåµéÀÌ ¾²ÀÌ°Ô µÈ´Ù.
ÇϳªÀÇ instance basis¸¦ ±â¹ÝÀ¸·Î ÇÑ °¢°¢ÀÇ widgetµéÀ» À§ÇÑ ±¸Á¶Ã¼µµ ÀÖ´Ù. ÀÌ ±¸Á¶Ã¼´Â ¾î¶² widgetÀÇ °¢°¢ÀÇ instance¸¦ À§ÇÑ ¼·Î ´Ù¸¥ Á¤º¸¸¦ °¡Áö°í ÀÖ´Ù. ¿ì¸®´Â ÀÌ ±¸Á¶Ã¼¸¦ object structure¶ó°í ºÎ¸¦ °ÍÀÌ´Ù. ¹öÆ° Ŭ·¡½º¸¦ ¿¹·Î µç´Ù¸é ÀÌ·¸°Ô µÈ´Ù.
struct _GtkButton
{
GtkContainer container;
GtkWidget *child;
guint in_button : 1;
guint button_down : 1;
};
Class structure¿¡¼¿Í ¸¶Âù°¡Áö·Î ù¹ø° Çʵå´Â parent classÀÇ object structureÀÓÀ» ÁÖÀÇÇ϶ó. ±×·¡¼ ÀÌ ±¸Á¶Ã¼´Â ÇÊ¿äÇÒ °æ¿ì parent classÀÇ object·Î ij½ºÆ®µÉ ¼öµµ ÀÖ´Â °ÍÀÌ´Ù.
¿ì¸®°¡ ¸¸µé°íÀÚ ÇÏ´Â ¾î¶² widgetÀº ´ÜÁö ´Ù¸¥ GTK widgetµéÀÇ ÁýÇÕüÀÏ »ÓÀÏ ¼öµµ ÀÖ´Ù. ÀÌ·± widgetÀº ²À »õ·Î¿î °ÍÀ¸·Î ¸¸µé¾îÁ®¾ß ÇÒ °ÍÀº ¾Æ´ÏÁö¸¸, Àç»ç¿ë¼ºÀ» À§ÇØ »ç¿ëÀÚ ÀÎÅÍÆäÀ̽ºÀûÀÎ ¿ä¼ÒµéÀ» ÆÐŰ¡ÇÏ´Â µ¥ ÀÖ¾î Æí¸®ÇÑ ¹æ½ÄÀ» Á¦°øÇÑ´Ù. Ç¥ÁØ GTK ¹èÆ÷ÆÇ¿¡ ÀÖ´Â FileSelection°ú ColorSelection widgetÀÌ ¿¹°¡ µÉ °ÍÀÌ´Ù.
¿ì¸®°¡ ¿©±â¼ ¸¸µé·Á´Â ¿¹Á¦´Â Tictactoe widgetÀ¸·Î, Åä±Û¹öÆ°ÀÇ 3x3 ¹è¿ ¿¡¼ ¾î´À ÇÑ Çà ¶Ç´Â ¿ ¶Ç´Â ´ë°¢¼ººÐ ¸ðµÎ°¡ ´·¯Áö°Ô µÇ¸é ½Ã±×³ÎÀ» ³»º¸³½ ´Ù.
ÀüÇüÀûÀ¸·Î composite widgetÀÇ parent class´Â ±× composite widgetÀÇ ¸ðµç
¸â¹öµéÀ» °¡Áö°í ÀÖ´Â ÄÁÅ×ÀÌ³Ê Å¬·¡½ºÀÌ´Ù. ¿¹¸¦µé¾î, FileSelection widgetÀÇ
parent class´Â Dialog Ŭ·¡½ºÀÌ´Ù. ¿ì¸® ¹öÆ°µéÀº table ¾È¿¡ ´Ã¾î¼ ÀÖÀ» °Í
À̹ǷÎ, parent class·Î GtkTable Ŭ·¡½º°¡ µÇ´Â °ÍÀÌ ÀÚ¿¬½º·´´Ù. ºÒÇàÈ÷µµ,
ÀÌ°ÍÀº µ¿ÀÛÇÏÁö ¾Ê´Â´Ù. ÇÑ widgetÀ» ¸¸µå´Â °ÍÀº µÎ ÇÔ¼ö¿¡ ÀÇÇÑ °ÍÀ¸·Î
³ª´¶´Ù. WIDGETNAME_new()
ÇÔ¼ö¸¦ »ç¿ëÀÚ°¡ ºÎ¸£°í, ±×¸®°í
WIDGETNAME_init()
ÇÔ¼ö´Â _new()
ÇÔ¼öÀÇ ÀÎÀÚ·Î ÁÖ¾îÁø widgetµé¿¡
´ëÇÑ ±âº»ÀûÀÎ ÃʱâÈ ÀÛ¾÷À»
ÇÑ´Ù. Descendent widgetµéÀº ´ÜÁö ±×µéÀÇ parent widgetÀÇ _init()
ÇÔ¼ö¸¸
ºÎ¸£°Ô µÈ´Ù. ±×·¯³ª ÀÌ ÀÛ¾÷ ºÐÇÒÀº Å×ÀÌºí¿¡ ´ëÇؼ´Â Àß µ¿ÀÛÇÏÁö ¾Ê´Â´Ù.
Å×À̺íÀÇ °æ¿ì¿¡´Â ¸¸µé¾îÁú ¶§ Çà°ú ¿ÀÇ °¹¼ö¸¦ ¾Ë Çʿ伺ÀÌ Àֱ⠶§¹®ÀÌ´Ù.
±×·¸Áö ¾ÊÀ¸¸é ¿ì¸®´Â ÀÌ Tictactoe widget¿¡ ÀÖ´Â gtk_table_new()
ÀÇ ´ëºÎºÐÀÇ
±â´ÉµéÀ» Áߺ¹Çؼ ÀÌ¿ëÇÏ°Ô µÉ °ÍÀÌ´Ù. ±×·¯¹Ç·Î, ¿ì¸®´Â ´ë½Å ±×°ÍÀ» GtkVBox
·ÎºÎÅÍ À̲ø¾î³»¾î, ¿ì¸®ÀÇ Å×À̺íÀ» VBox ³»ºÎ·Î ºÙ¿©ÁÙ °ÍÀÌ´Ù.
°¢°¢ÀÇ widget class´Â public ÇÔ¼ö¿Í ±¸Á¶Ã¼ ¹× °´Ã¼ÀÇ ¼±¾ðµéÀÌ ÀÖ´Â Çì´õ ÆÄÀÏÀ» °¡Áö°í ÀÖ´Ù. ¿©±â¼ °£´ÜÈ÷ »ìÆ캸ÀÚ. Áߺ¹ Á¤ÀǸ¦ ÇÇÇϱâ À§Çؼ, ¿ì¸®´Â Çì´õÆÄÀÏ Àüü¸¦ ÀÌ·¸°Ô µÑ·¯½Ñ´Ù.
#ifndef __TICTACTOE_H__
#define __TICTACTOE_H__
.
.
.
#endif /* __TICTACTOE_H__ */
±×¸®°í C++ ÇÁ·Î±×·¥À» °í·ÁÇؼ À̰͵µ Ãß°¡ÇÑ´Ù.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
.
.
.
#ifdef __cplusplus
}
#endif /* __cplusplus */
ÇÔ¼ö¿Í ±¸Á¶Ã¼µé¿¡ ´ëÇØ, ¿ì¸®´Â Çì´õÆÄÀÏ ³»¿¡¼ ¼¼°¡Áö Ç¥ÁØÀûÀÎ ¸ÅÅ©·Î¸¦
¼±¾ðÇÑ´Ù. Áï TICTACTOE(obj)
, TICTACTOE_CLASS(klass)
,
IS_TICTACTOE(obj)
ÀÌ´Ù.
À̵éÀº ¾î¶² ÇÑ Æ÷ÀÎÅ͸¦ object ȤÀº class structure¿¡ ´ëÇÑ Æ÷ÀÎÅͷΠij½ºÆ®
ÇÏ°í, ¾î¶² object°¡ Tictactoe widgetÀÎÁö¸¦ üũÇÏ´Â ¿ªÇÒÀ» ÇÑ´Ù.
ÀÌ°ÍÀÌ ÃÖÁ¾ÀûÀÎ Çì´õÆÄÀÏÀÌ´Ù.
/* tictactoe.h */
#ifndef __TICTACTOE_H__
#define __TICTACTOE_H__
#include <gdk/gdk.h>
#include <gtk/gtkvbox.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define TICTACTOE(obj) GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
#define TICTACTOE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
#define IS_TICTACTOE(obj) GTK_CHECK_TYPE (obj, tictactoe_get_type ())
typedef struct _Tictactoe Tictactoe;
typedef struct _TictactoeClass TictactoeClass;
struct _Tictactoe
{
GtkVBox vbox;
GtkWidget *buttons[3][3];
};
struct _TictactoeClass
{
GtkVBoxClass parent_class;
void (* tictactoe) (Tictactoe *ttt);
};
guint tictactoe_get_type (void);
GtkWidget* tictactoe_new (void);
void tictactoe_clear (Tictactoe *ttt);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __TICTACTOE_H__ */
_get_type()
ÇÔ¼öÀÌÁ¦ ¿ì¸®ÀÇ widgetÀ» °è¼Ó ´Ùµë¾î º¸ÀÚ. ¸ðµç widgetµé¿¡ ´ëÇÑ ÇÙ½É(core)
ÇÔ¼ö´Â WIDGETNAME_get_type()
ÀÌ´Ù. ÀÌ ÇÔ¼ö´Â óÀ½ È£ÃâµÇ¾úÀ» ¶§, GTK¿¡°Ô
widget class¿¡ ´ëÇØ ¾Ë·ÁÁØ´Ù. ±×¸®°í widget class¸¦ ¸íÈ®È÷ ½Äº°ÇÏ´Â ID¸¦
ÃëÇÑ´Ù. °è¼Ó È£ÃâÇÏ¸é ¹Ù·Î ±× ID¸¦ ¸®ÅÏÇÑ´Ù.
guint
tictactoe_get_type ()
{
static guint ttt_type = 0;
if (!ttt_type)
{
GtkTypeInfo ttt_info =
{
"Tictactoe",
sizeof (Tictactoe),
sizeof (TictactoeClass),
(GtkClassInitFunc) tictactoe_class_init,
(GtkObjectInitFunc) tictactoe_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
}
return ttt_type;
}
±¸Á¶Ã¼ GtkTypeInfo´Â ´ÙÀ½°ú °°ÀÌ Á¤ÀǵǾú´Ù.
struct _GtkTypeInfo
{
gchar *type_name;
guint object_size;
guint class_size;
GtkClassInitFunc class_init_func;
GtkObjectInitFunc object_init_func;
GtkArgSetFunc arg_set_func;
GtkArgGetFunc arg_get_func;
};
ÀÌ ±¸Á¶Ã¼ÀÇ °¢ Çʵå´Â ¿ª½Ã º¸ÀÌ´Â ±×´ë·Î´Ù. ¿ì¸®´Â ¿©±â¼
arg_set_func
¿Í arg_get_func
Çʵå
¸¦ ¹«½ÃÇÒ °ÍÀÌ´Ù. ÀÌ°ÍÀº ÀÎÅÍÇÁ¸®ÅÍ ¾ð¾î¿¡¼ ºñ·ÔµÇ¾î widget ¿É¼ÇµéÀ»
Æí¸®ÇÏ°Ô ¼¼ÆÃÇÒ ¼ö ÀÖµµ·Ï ÇÏ´Â Áß¿äÇÑ ¿ªÇÒÀ» ÇÒ ¼ö ÀÖÁö¸¸, ¾ÆÁ÷Àº ´ë°³
°®Ãß¾îÁöÁö ¾Ê¾Ò´Ù. ÀÏ´Ü GTK°¡ ÀÌ ±¸Á¶Ã¼ÀÇ Á¦´ë·Î µÈ º¹»çº»À» °¡Áö°Ô µÇ¸é,
±×°ÍÀº Ưº°ÇÑ widget typeÀÇ object¸¦ ¸¸µå´Â ¹æ¹ýÀ» ¾Ë°Ô µÈ´Ù.
_class_init()
ÇÔ¼öWIDGETNAME_class_init()
ÇÔ¼ö´Â widgetÀÇ class structure¿¡ ÀÖ´Â ÇʵåµéÀ»
ÃʱâÈÇÏ°í, ±× Ŭ·¡½º¿¡ ´ëÇÑ ½Ã±×³Îµéµµ ¼Â¾÷ÇØ ÁØ´Ù. ¿ì¸®ÀÇ Tictactoe
widget¿¡ ´ëÇؼ ÀÌ°ÍÀº ÀÌ·¸°Ô º¸¿©Áø´Ù.
enum {
TICTACTOE_SIGNAL,
LAST_SIGNAL
};
static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
static void
tictactoe_class_init (TictactoeClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) class;
tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
class->tictactoe = NULL;
}
¿ì¸® widgetÀÌ °¡Áø À¯ÀÏÇÑ ½Ã±×³ÎÀº ``tictactoe'' ½Ã±×³Î·Î, ÀÌ°ÍÀº ÇÑ Çà, ¿, ȤÀº ´ë°¢ ¼ººÐÀÌ ¿ÏÀüÈ÷ ä¿öÁö¸é ¿ä±¸µÈ´Ù. ¸ðµç ÇÕ¼º widgetµéÀÌ ½Ã±×³Î À» ÇÊ¿ä·Î ÇÏ´Â °ÍÀº ¾Æ´Ï¸ç, µû¶ó¼ ¿©·¯ºÐÀÌ ÀÌ ºÎºÐÀ» óÀ½ Àаí ÀÖ´Â »óÅ ¶ó¸é ´ÙÀ½ ¼½¼Ç(section)À¸·Î ³Ñ¾î°¡µµ ÁÁ´Ù. ÀÌ ºÎºÐÀº ´Ù¼Ò º¹ÀâÇÒ °ÍÀ̱⠶§¹®ÀÌ´Ù.
ÀÌ ÇÔ¼ö¸¦ º¸ÀÚ.
gint gtk_signal_new (gchar *name,
GtkSignalRunType run_type,
gint object_type,
gint function_offset,
GtkSignalMarshaller marshaller,
GtkArgType return_val,
gint nparams,
...);
»õ·Î¿î ½Ã±×³ÎÀ» ¸¸µç´Ù. ¿©±â¿¡ ¾²ÀÎ ÀÎÀÚµéÀ» »ìÆ캸ÀÚ.
name
: ½Ã±×³ÎÀÇ À̸§run_type
: µðÆúÆ® Çڵ鷯°¡ »ç¿ëÀÚ Çڵ鷯º¸´Ù ¾Õ¼¼ ȤÀº
µÚµû¶ó ÀÛµ¿ÇÏ´ÂÁö °áÁ¤ÇÑ´Ù. ´Ù¸¥ °¡´É¼ºµéµµ ÀÖÁö¸¸, º¸Åë
ÀÌ°ÍÀº GTK_RUN_FIRST
¶Ç´Â GTK_RUN_LAST
°¡ µÈ´Ù.object_type
: ÀÌ ½Ã±×³ÎÀÌ Àû¿ëµÉ objectÀÇ ID. (ÀÌ objectÀÇ
descendents¿¡µµ Àû¿ëµÊ)function_offset
: µðÆúÆ® Çڵ鷯¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍÀÇ
class structure ³»¿¡¼ÀÇ ¿É¼Â.marshaller
: ½Ã±×³Î Çڵ鷯¸¦ ºÒ·¯³»±â À§ÇØ ¾²ÀÌ´Â ÇÔ¼ö.
½Ã±×³Î°ú »ç¿ëÀÚ µ¥ÀÌÅ͸¦ ¹ß»ýÇÑ object¸¸À» ÀÎÀÚ·Î °¡Áö´Â
½Ã±×³Î Çڵ鷯ÀÏ °æ¿ì, ¿ì¸®´Â ÀÌ¹Ì Á¦°øµÇ´Â marshaller ÇÔ¼öÀÎ
gtk_signal_default_marshaller
¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.return_val
: ¸®ÅÏ°ªÀÇ Å¸ÀÔ.nparams
: ½Ã±×³Î Çڵ鷯ÀÇ ÀÎÀÚ °¹¼ö. (À§¿¡¼ ¾ð±ÞµÈ µÎ µðÆúÆ®
ÀÎÀÚ ÀÌ¿ÜÀÇ ´Ù¸¥ °Íµé)ŸÀÔÀ» ¼³Á¤Çϱâ À§ÇØ, GtkType
À̶ó´Â enumerationÀÌ ¾²ÀδÙ.
typedef enum
{
GTK_TYPE_INVALID,
GTK_TYPE_NONE,
GTK_TYPE_CHAR,
GTK_TYPE_BOOL,
GTK_TYPE_INT,
GTK_TYPE_UINT,
GTK_TYPE_LONG,
GTK_TYPE_ULONG,
GTK_TYPE_FLOAT,
GTK_TYPE_DOUBLE,
GTK_TYPE_STRING,
GTK_TYPE_ENUM,
GTK_TYPE_FLAGS,
GTK_TYPE_BOXED,
GTK_TYPE_FOREIGN,
GTK_TYPE_CALLBACK,
GTK_TYPE_ARGS,
GTK_TYPE_POINTER,
/* it'd be great if the next two could be removed eventually */
GTK_TYPE_SIGNAL,
GTK_TYPE_C_CALLBACK,
GTK_TYPE_OBJECT
} GtkFundamentalType;
gtk_signal_new()
´Â ½Ã±×³Î¿¡ ´ëÇØ °íÀ¯ÇÑ Á¤¼ö ½Äº°ÀÚ¸¦ ¸®ÅÏÇÑ´Ù. ¿ì¸®´Â
À̵éÀ» tictactoe_signals
¹è¿¿¡ ÀúÀåÇÏ°í, enumeration·Î ÀÌ¿ëÇؼ À妽º¸¦
ÁØ´Ù. (°ü½ÀÀûÀ¸·Î enumerationÀÇ ¿ø¼ÒµéÀº ´ë¹®ÀÚ·Î ½Ã±×³ÎÀÇ À̸§À» ³ªÅ¸³»
Áö¸¸, ¿©±â¼ TICTACTOE()
¸ÅÅ©·Î¿Í Ãæµ¹ÇÒ ¼ö Àֱ⠶§¹®¿¡, ¿ì¸®´Â À̵éÀ»
TICTACTOE_SIGNAL
À̶ó°í ºÎ¸¥´Ù.)
½Ã±×³ÎÀ» ¸¸µé¾ú´Ù¸é, ÀÌÁ¦ GTK°¡ ÀÌ ½Ã±×³ÎµéÀ» Tictactoe Ŭ·¡½º¿¡ ¿¬°á½ÃÅ°
µµ·Ï ÇØ¾ß ÇÑ´Ù. ÀÌ ÀÛ¾÷Àº gtk_object_class_add_signals()
·Î ÇØÁØ´Ù. ±×¸®°í
¾Æ¹«·± µðÆúÆ® µ¿ÀÛÀÌ ¾ø´Ù´Â °É ³ªÅ¸³»±â À§ÇØ, ``tictactoe'' ½Ã±×³ÎÀ» À§ÇÑ µðÆúÆ®
Çڵ鷯¸¦ °¡¸®Å°°í ÀÖ´Â Æ÷ÀÎÅ͸¦ NULL·Î ¼¼ÆÃÇÑ´Ù.
_init()
ÇÔ¼ö°¢ widget Ŭ·¡½º´Â ¶ÇÇÑ object structure¸¦ ÃʱâÈÇØ ÁÙ ÇÔ¼ö¸¦ ÇÊ¿ä·Î ÇÑ´Ù. º¸Åë, ÀÌ ÇÔ¼ö´Â ±¸Á¶Ã¼ÀÇ ÇʵåµéÀ» µðÆúÆ® °ªÀ¸·Î ¼¼ÆÃÇÏ´Â ³ª¸§´ë·Î Á¦ÇÑµÈ ¿ªÇÒÀ» °¡Áö°í ÀÖ´Ù. ±×·¯³ª ÇÕ¼º widgetµéÀÇ °æ¿ì, ÀÌ ÇÔ¼öµéÀÌ ÀûÇÕÇÑ ¶Ç´Ù¸¥ widgetµéÀ» ¸¸µé¾î Áֱ⵵ ÇÑ´Ù.
static void
tictactoe_init (Tictactoe *ttt)
{
GtkWidget *table;
gint i,j;
table = gtk_table_new (3, 3, TRUE);
gtk_container_add (GTK_CONTAINER(ttt), table);
gtk_widget_show (table);
for (i=0;i<3; i++)
for (j=0;j<3; j++)
{
ttt->buttons[i][j] = gtk_toggle_button_new ();
gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
i, i+1, j, j+1);
gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
gtk_widget_show (ttt->buttons[i][j]);
}
}
¸ðµç widgetµé(GtkBinó·³ ´Þ¸® ¼³¸íµÉ ¼ö ¾ø´Â base widgetµéÀº Á¦¿Ü)ÀÌ
°¡Áö°í ÀÖ¾î¾ß ÇÒ ÇÔ¼ö°¡ Çϳª ´õ ÀÖ´Ù. ¹Ù·Î ±× ÇØ´çÇϴ ŸÀÔÀÇ object¸¦
¸¸µé±â À§ÇÑ ÇÔ¼ö´Ù. ÀÌ°ÍÀº °ü·Ê»ó WIDGETNAME_new()
°¡ µÈ´Ù. Tictactoe
widget¿¡´Â ÇØ´çÇÏÁö ¾ÊÁö¸¸, ÀϺΠwidgetµéÀº ÀÌ ÇÔ¼öµéÀÌ ÀÎÀÚ¸¦ °¡Áö°í,
±×¸®°í ±× ÀÎÀÚ¸¦ Âü°íÇؼ ¾î¶² ¼Â¾÷À» ÇàÇϱ⵵ ÇÑ´Ù. ´Ù¸¥ µÎ ÇÔ¼ö´Â ¿ì¸®ÀÇ
Tictactoe widget¿¡ ´ëÇÑ Æ¯º°ÇÑ °ÍµéÀÌ´Ù.
tictactoe_clear()
´Â widget¿¡ ÀÖ´Â ¸ðµç ¹öÆ°À» up »óÅ·Π¸®¼ÂÇØ ÁØ´Ù.
¹öÆ° Åä±ÛÀ» À§ÇÑ ¿ì¸® ½Ã±×³Î Çڵ鷯°¡ ºÒÇÊ¿äÇÏ°Ô Á¶ÁصǴ °ÍÀ» ¸·¾ÆÁÖ±â À§ÇØ
gtk_signal_handler_block_by_data()
¸¦ ÀÌ¿ëÇÏ´Â °ÍÀ» ¸í½ÉÇÏÀÚ.
tictactoe_toggle()
Àº »ç¿ëÀÚ°¡ ¾î¶² ¹öÆ°À» Ŭ¸¯ÇßÀ» ¶§ ¿äûµÇ´Â ½Ã±×³Î
Çڵ鷯´Ù. ÀÌ°ÍÀº Åä±ÛµÈ ¹öÆ°À» Æ÷ÇÔÇØ ¾î¶² ¸Å·ÂÀûÀÎ ÄÞºñ(combination)°¡
ÀÌ·ç¾îÁö´ÂÁö üũÇÏ°í, ¸¸¾à ±×·¸´Ù¸é "tictactoe" ½Ã±×³ÎÀ» ¹ß»ý½ÃŲ´Ù.
GtkWidget*
tictactoe_new ()
{
return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
}
void
tictactoe_clear (Tictactoe *ttt)
{
int i,j;
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
FALSE);
gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
}
}
static void
tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
{
int i,k;
static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
{ 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
{ 0, 1, 2 }, { 0, 1, 2 } };
static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
{ 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
{ 0, 1, 2 }, { 2, 1, 0 } };
int success, found;
for (k=0; k<8; k++)
{
success = TRUE;
found = FALSE;
for (i=0;i<3;i++)
{
success = success &&
GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
found = found ||
ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
}
if (success && found)
{
gtk_signal_emit (GTK_OBJECT (ttt),
tictactoe_signals[TICTACTOE_SIGNAL]);
break;
}
}
}
±×¸®°í ¿ì¸®ÀÇ Tictactoe widgetÀ» ÀÌ¿ëÇÑ ¿¹Á¦ ÇÁ·Î±×·¥Àº ÃÖÁ¾ÀûÀ¸·Î ÀÌ°ÍÀÌ´Ù.
#include <gtk/gtk.h>
#include "tictactoe.h"
/* ¾î¶² Çà, ¿, ȤÀº ´ë°¢¼ººÐÀÌ ´Ù Â÷°Ô µÇ¸é ¿äûµÈ´Ù. */
void
win (GtkWidget *widget, gpointer data)
{
g_print ("Yay!\n");
tictactoe_clear (TICTACTOE (widget));
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *ttt;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (gtk_exit), NULL);
gtk_container_border_width (GTK_CONTAINER (window), 10);
/* Tictactoe widgetÀ» Çϳª ¸¸µç´Ù. */
ttt = tictactoe_new ();
gtk_container_add (GTK_CONTAINER (window), ttt);
gtk_widget_show (ttt);
/* ±×¸®°í ÀÌ°ÍÀÇ "tictactoe" ½Ã±×³Î¿¡ °áÇÕ½ÃÄÑ µÐ´Ù. */
gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
GTK_SIGNAL_FUNC (win), NULL);
gtk_widget_show (window);
gtk_main ();
return 0;
}
À̹ø ¼½¼Ç¿¡¼´Â widgetµéÀÌ ±× ÀڽŵéÀ» ¾î¶»°Ô ½ºÅ©¸°¿¡ º¸ÀÌ°Ô ÇÏ´ÂÁö, ±×¸®°í À̺¥Æ®¿Í »óÈ£ÀÛ¿ë ÇÏ´ÂÁö¸¦ ´õ °øºÎÇÒ °ÍÀÌ´Ù. ÀÌ¿¡ ´ëÇÑ ¿¹Á¦·Î ¿ì¸®´Â Æ÷ÀÎÅÍ°¡ ´Þ·ÁÀÖ´Â ¾Æ³¯·Î±× ´ÙÀ̾ó(analog dial) widgetÀ» ¸¸µé¾î¼, »ç¿ëÀÚ°¡ ±×°É ²ø¾î¼ °ªÀ» ¼¼ÆÃÇϵµ·Ï ÇÒ °ÍÀÌ´Ù.
½ºÅ©¸°¿¡ º¸¿©ÁÖ±â À§Çؼ ¸î°¡Áö ´Ü°è°¡ ÀÖ´Ù. WidgetÀÌ WIDGETNAME_new()
·Î½á ¸¸µé¾îÁö°í ³ª¼, ¸î°³ÀÇ ÇÔ¼ö°¡ ´õ ÇÊ¿äÇÏ´Ù.
WIDGETNAEME_realize()
°¡ XÀ©µµ¸¦ ¸¸µé¾îÁØ´Ù.WIDGETNAME_map()
Àº »ç¿ëÀÚ°¡ gtk_widget_show()
¸¦ È£ÃâÇÑ ÀÌÈÄ¿¡
¿äûµÈ´Ù. ÀÌ´Â widgetÀÌ ½ÇÁ¦·Î ½ºÅ©¸° À§¿¡ ±×·ÁÁö´Â(mapped) °ÍÀ» È®ÀÎÇÑ´Ù.
ÄÁÅ×ÀÌ³Ê Å¬·¡½ºÀÇ °æ¿ì, ÀÏüÀÇ child widgetµéÀ» ¸ÅÇÎÇϱâ À§ÇÑ È£Ãâ ¶ÇÇÑ
ÇÊ¿äÇÏ´Ù.WIDGETNAME_draw()
´Â widget ȤÀº ±×°ÍÀÇ ancestor¿¡ ´ëÇØ
gtk_widget_draw()
°¡ È£ÃâµÇ¾úÀ» ¶§ ¿äûµÇ´Â °ÍÀÌ´Ù. ÀÌ°ÍÀº widgetÀ» ½ºÅ©¸°¿¡ ±×¸®±â À§ÇØ
½ÇÁ¦ ±×¸®´Â ÇÔ¼ö¸¦ È£ÃâÇØ ÁØ´Ù. ÄÁÅ×ÀÌ³Ê widgetÀÇ °æ¿ì¿£ ±×°ÍÀÇ child
widgetµéÀ» À§ÇØ gtk_widget_draw()
µµ È£ÃâÇØ Áà¾ß ÇÑ´Ù.WIDGETNAME_expose()
´Â expose À̺¥Æ®¸¦ À§ÇÑ Çڵ鷯´Ù.
ÀÌ°ÍÀº ½ºÅ©¸°¿¡
exposeµÈ ¿µ¿ªÀ» ±×·ÁÁÖ±â À§ÇØ ÇÊ¿äÇÑ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. ÄÁÅ×ÀÌ³Ê widget
ÀÇ °æ¿ì, ÀÌ ÇÔ¼ö´Â ÀڽŸ¸ÀÇ À©µµ¸¦ °¡ÁöÁö ¾Ê´Â child widgetµé¿¡ ´ëÇØ
expose À̺¥Æ®¸¦ ¹ß»ý½ÃÄÑÁØ´Ù. (¸¸¾à ±×µéÀÌ À©µµ¸¦ °¡Áø´Ù¸é, ÇÊ¿äÇÑ
expose À̺¥Æ®¸¦ X°¡ ¹ß»ý½ÃŲ´Ù.)»ó´çÈ÷ À¯»çÇÑ ¸¶Áö¸·ÀÇ µÎ ÇÔ¼ö¿¡ ÁÖÀÇÇØ¾ß ÇÒ °ÍÀÌ´Ù. »ç½Ç ¸¹Àº ŸÀÔÀÇ
widgetµéÀº µÎ °æ¿ìÀÇ Â÷ÀÌÁ¡À» ±×´ÙÁö ±¸º°ÇÏÁö ¾Ê´Â´Ù. Widget Ŭ·¡½ºÀÇ
µðÆúÆ® draw()
ÇÔ¼ö´Â ´ÜÁö ´Ù½Ã ±×·ÁÁø ¿µ¿ª¿¡ ´ëÇØ Á¾ÇÕÀûÀÎ expose À̺¥Æ®¸¦
¹ß»ý½Ãų »ÓÀÌ´Ù. ±×·¯³ª ¾î¶² ŸÀÔÀÇ widgetÀº µÎ ÇÔ¼ö¸¦ ±¸º°ÇÔÀ¸·Î½á ÀÛ¾÷À»
ÃÖ¼ÒÈÇϱ⵵ ÇÑ´Ù. ¿¹¸¦µé¾î ¿©·¯ °³ÀÇ XÀ©µµ¸¦ °¡Áø widgetÀº ¿µÇâÀ» ¹ÞÀº
(affected) À©µµ¸¸À» ´Ù½Ã ±×·ÁÁÙ ¼ö Àִµ¥, ÀÌ°ÍÀº ´Ü¼øÈ÷ draw()
À» È£ÃâÇÏ´Â
°ÍÀ¸·Î´Â ºÒ°¡´ÉÇÑ ÀÏÀÌ´Ù.
ÄÁÅ×ÀÌ³Ê widgetµéÀº ¼·ÎÀÇ Â÷ÀÌÁ¡¿¡ ´ëÇØ ÀÚ±â ÀÚ½ÅÀº »ó°üÇÏÁö ¾ÊÁö¸¸,
±×µéÀÇ child widgetµéÀº ¼·Î¸¦ ºÐ¸íÈ÷ ±¸º°ÇØ¾ß ÇϹǷÎ, °£´ÜÈ÷ µðÆúÆ® draw()
ÇÔ¼ö¸¦ °¡Áú ¼ö ¾ø´Ù. ÇÏÁö¸¸, µÎ ÇÔ¼ö »çÀÌ¿¡¼ ±×¸®´Â Äڵ带 Áߺ¹ÇÏ´Â °ÍÀº
³¶ºñ´Ù. ÀÌ·± widgetµéÀº °ü½À»ó WIDGETNAME_paint()
¶ó°í ºÒ¸®´Â ÇÔ¼ö¸¦
°¡Áø´Ù. ÀÌ ÇÔ¼öµéÀº widgetÀ» ½ÇÁ¦·Î ±×¸®´Â ¿ªÇÒÀ» Çϸç, draw()
¹×
expose()
ÇÔ¼ö¿¡ ÀÇÇØ ºÒ¸®¾îÁö°Ô µÈ´Ù.
¿ì¸®ÀÇ ¿¹Á¦¿¡¼´Â dial widgetÀÌ ÄÁÅ×À̳ʰ¡ ¾Æ´Ï¸ç ¿ÀÁ÷ ÇϳªÀÇ À©µµ¸¸ °¡Áö
±â ¶§¹®¿¡, ¿ì¸®´Â °£´ÜÇÏ°Ô ¹®Á¦¸¦ ÇØ°áÇÒ ¼ö ÀÖ´Ù. Áï µðÆúÆ® draw()
¸¦ ÀÌ¿ë
ÇÏ°í ¶Ç expose()
ÇÔ¼ö¸¸À» °®Ãá´Ù.
Áö»óÀÇ ¸ðµç µ¿¹°µéÀÌ ÁøÈëÅÁ¿¡¼ óÀ½À¸·Î ±â¾î³ª¿Â ¾ç¼·ùÀÇ º¯Á¾µéÀÎ °Íó·³, Gtk widgetµéµµ ¸ÕÀú ¸¸µé¾îÁø widgetÀÇ º¯Çü¿¡¼ Ãâ¹ßÇÏ´Â °æÇâÀÌ ÀÖ´Ù. ±×·¡¼, ÀÌ Àý(section)ÀÌ "Creating a Widget from Scratch"¶ó´Â Á¦¸ñÀ¸·Î µÇ¾î ÀÖÀ½¿¡µµ, Dial widgetÀº ½ÇÁ¦·Î Range widgetÀÇ Äڵ忡¼ Ãâ¹ßÇÑ´Ù. ÀÌ´Â ¿ª½Ã Range widget¿¡¼ ÆÄ»ýµÈ Scale widgetµé°ú ¶È°°Àº ÀÎÅÍÆäÀ̽º¸¦, ¿ì¸®ÀÇ Dial widgetÀÌ °¡Áú ¼ö ÀÖ´Ù¸é ¸ÚÁú °ÍÀ̶ó´Â »ý°¢¿¡¼´Ù. ¶ÇÇÑ ¸¸¾à ¿©·¯ºÐÀÌ ¾îÇà Á¦ÀÛÀÚÀÇ °üÁ¡¿¡¼ scale widgetµéÀÇ ÀÛ¿ë¿¡ ´ëÇØ Àͼ÷ÇÏÁö ¾Ê´Ù¸é, ¸ÕÀú ±×µé¿¡ ´ëÇØ ¾Ë¾Æ º¸´Â °Íµµ ÁÁÀº »ý°¢ÀÏ °ÍÀÌ´Ù.
¿ì¸® 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);
}
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);
}
¾î¶² 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;
}
}
¾Õ¿¡¼ ¾ð±ÞÇßµíÀÌ, ÀÌ 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;
}
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;
}
}
¿ì¸®°¡ ºÃµíÀÌ Dial widgetÀº ¾à 670ÁÙÀÇ Äڵ带 °¡Áö°í ÀÖ´Ù. ƯÈ÷ ÀÌ ÄÚµå ±æÀÌÀÇ ´ëºÎºÐÀÌ Çì´õ¿Í º¸ÀÏ·¯ÆÇ(boiler plate)À̱⠶§¹®¿¡, ¿ì¸®´Â ÀÌ ±ä ÄÚµå ¿¡¼ ²Ï ¸¹Àº °ÍÀ» ¹è¿ï ¼ö ÀÖ¾ú´Ù. ±×·¯³ª ÀÌ widget¿¡ ´ëÇØ °¡´ÉÇÑ ¸î °¡Áö ±â´É°³¼±ÀÌ ÀÖ´Ù.
WidgetÀ» ¸¸µé±â À§ÇÑ ¼ö¸¹Àº Ç׸ñµé Áß ±ØÈ÷ ÀϺθ¸ÀÌ À§¿¡¼ ¼Ò°³µÇ¾ú´Ù. ÀÚ½ÅÀÇ widgetÀ» ¸¸µé·Á´Â ÀÌ¿¡°Ô, °¡Àå ÁÁÀº ¼Ò½º´Â GTK ±× ÀÚüÀÏ °ÍÀÌ´Ù. ¿©·¯ºÐÀÌ ¸¸µé·Á´Â widget¿¡ ´ëÇØ ½º½º·Î ¸î°¡Áö Áú¹®À» Çغ¸ÀÚ. ÀÌ°ÍÀº Container widgetÀΰ¡? ÀÌ°ÍÀº °ü·ÃµÈ À©µµ¸¦ °¡Áö°í Àִ°¡? ÀÌ°ÍÀº ÀÌ¹Ì Á¸ÀçÇÏ´Â widgetÀÇ º¯ÇüÀΰ¡? ±×¸®°í´Â À¯»çÇÑ widgetÀ» ã°í, º¯È¸¦ Áֱ⠽ÃÀÛÇÏ´Â °ÍÀÌ´Ù. Çà¿îÀ» ºó´Ù!