· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Linuxdoc Sgml/Gtk Tutorial-TRANS

GTK 2.x Tutorial

GTK 2.x Tutorial

Ian Main imain@gtk.org, Tony Gale gale@gtk.org & the GTK team

1998³â 5¿ù 24ÀÏ ¼­ÁÖÅ liberta@cau.ac.kr, ÇÑÁöÈ£ hanjiho@penta.co.kr 1998³â 5¿ù 25ÀÏ

1. ¿Å±äÀÌÀÇ ¸»

Áö³­ 2¿ù ¸»ºÎÅÍ Á¶±Ý¾¿ ¹ø¿ªÇØ º» GTK TutorialÀÔ´Ï´Ù. Ãâó´Â GTK+ÀÇ °ø½Ä ȨÆäÀÌÁöÀÎ http://www.gtk.org/ÀÔ´Ï´Ù. ¹ø¿ªÀ» ´ëÃæ ³¡¸¶Ä£ Áö±Ý(3/??), ÀÌ TutorialÀº 1998/1/24 ³¯Â¥·Î ¿Ã¶ó¿Â °ÍÀÌ °¡Àå »õ·Î¿î °ÍÀ̳׿ä. ¹°·Ð ÀÌ ¹ø¿ª¹°µµ ±×°ÍÀ» ±âÁØÀ¸·Î Çß½À´Ï´Ù. ¶Ç ÀçÈ°¿ë¼º(?)À» À§ÇÏ¿© óÀ½ºÎÅÍ ³¡±îÁö ÀϹÝÀûÀÎ ÅؽºÆ®(plain text)ÀÇ Æ÷¸ËÀ» À¯ÁöÇß½À´Ï´Ù.

GTK+ TutorialÀº ¸ðµÎ 24°³ÀÇ Àå(Chapter)À¸·Î ÀÌ·ç¾îÁ³°í ¸¶Áö¸· ÀåÀÎ 24ÀåÀ» ºñ·ÔÇÑ ¸î¸îÀº ¿ÀÈ÷·Á ¿ø¹®À» ±×´ë·Î Âü°íÇÏ´Â °ÍÀÌ ÁÁÀ» °ÍÀ̶ó°í ÆÇ´Ü, °ÅÀÇ ¹ø¿ªÇÏÁö ¾Ê¾Ò½À´Ï´Ù. ±×¸®°í Á¦°¡ ¹ø¿ªÇß´Ù°í ÁÖÀå(?)ÇÏ´Â ³ª¸ÓÁö Àåµéµµ, ¿ø·¡ »ó½ÄÀÌÇÏÀÇ ¿µ¾î½Ç·Â°ú ¼öÁØÀÌÇÏÀÇ Xlib/Widget Programming °æÇèÀ¸·Î ÀÎÇØ ²Ï³ª ¾îÁö·´°Ô ¾µ ¼ö¹Û¿¡ ¾ø¾ú½À´Ï´Ù. ÇÏÁö¸¸ ³ª¸§´ë·Î ½Å°æÀº ½èÀ¸´Ï±ñ, ¾Ë¾Æ¼­ ¹Þ¾ÆµéÀÌ½Ã±æ ¹Ù¶ø´Ï´Ù. :) ¹ø¿ªÇÑ ³»¿ëÀÇ Á¤È®¼º¿¡ ´ëÇؼ­µµ Ã¥ÀÓ ¸ø Áý´Ï´Ù. ¶ÇÇÑ ´õ È¿°úÀûÀÎ ÀÌÇظ¦ À§Çؼ­ ¿¹Á¦¸¦ Á÷Á¢ ÄÄÆÄÀÏ/½ÇÇàÇØ º¸½Ç °ÍÀ» ±ÇÇÕ´Ï´Ù.

ÀÌ Tutorial ¹ø¿ª¹®À» º¸´Â µ¥ À־, ¾îÁö·¯¿òÀ» Á¶±ÝÀ̳ª¸¶ ´ú¾î µå¸®±â À§ÇØ ÀüüÀûÀÎ À±°ûÀ» ¼Ò°³ÇÕ´Ï´Ù.

¼Ò°³

GTK(GTK+)ÀÇ ¼³°è¿Í ¼Ò°³ÀÔ´Ï´Ù. ÀÌ¹Ì ³ª¿ì ¸®µ¿(go linux) ¹ø¿ª¹° °Ô½ÃÆÇ¿¡ ¿Ã¸° GTK+ FAQÀÌ Âü°í°¡ µÉ °ÍÀÔ´Ï´Ù.

½ÃÀÛÇϸ鼭

GTK ¾îÇÃÀÇ ÀüÇüÀûÀÎ ±¸Á¶¿Í, ±× À¯¸íÇÑ helloworld.c ÇÁ·Î±×·¥ÀÔ´Ï´Ù. ±×¸®°í ´Ùµé °ñÄ¡¾ÆÆÄ ÇÏ´Â ÄÄÆÄÀÏ ¿É¼Çµµ °£´ÜÈ÷ ¼³¸íµÇ¾î ÀÖÁÒ. Áß¿äÇÑ ÀÌ·Ð, Áï ½Ã±×³Î(signal)°ú ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅÍ(callback function)¸¦ GTK°¡ ÀÌ¿ëÇÏ´Â ¹æ½Ä¿¡ ´ëÇؼ­µµ ´Ù·ì´Ï´Ù.

¾ÕÀ¸·Î ³ª¾Æ°¡¸ç

helloworld.c¸¦ Á¶±Ý °³¼±Çϸ鼭 ÀÚ·áÇüµé¿¡ ´ëÇÑ ÀܼҸ® ÂɱÝ, ±×¸®°í ½Ã±×³Î Çڵ鷯¿¡ ´ëÇÑ º¸Ãæ¼³¸íÀÌ ÀÖ½À´Ï´Ù. ½Ã±×³Î, Áß¿äÇÑ °ÅÁÒ.

ÆÐÅ· Widget

ÆÐÅ·(packing)À̶ó´Â Áß¿äÇÑ °³³ä¿¡ ´ëÇØ(Àúµµ Áö±ßÁö±ßÇØÁ³½À´Ï´Ù` :) ¿¹Á¦¿Í ÇÔ²² ¼³¸íÇÏ°í ÀÖ½À´Ï´Ù. ÆÐÅ·Àº »ç°¢ÇüÀÇ ¾î¶² ¿µ¿ª¿¡ ¹º°¡¸¦ ³Ö¾î µÐ´Ù´Â Àǹ̷Î, GTK+ó·³ À©µµ, °´Ã¼¸¦ ´Ù·ç´Â °³¹ß¹æ½Ä¿¡¼­ ±²ÀåÈ÷ ±âº»ÀûÀÌ°í "ÀÚÁÖ ³ª¿À´Â" ³ðÀÔ´Ï´Ù. ¿©±â¼­´Â Çϳª¾¿ ÆÐÅ·Çϱâ À§ÇÑ ¹Ú½º(box)°³³ä°ú, ¿©·¯°³¸¦ ÇѲ¨¹ø¿¡ ÆÐÅ·Çϱâ À§ÇÑ Å×À̺í(table)°³³äÀ» Â÷·Ê´ë·Î ¼Ò°³ÇÕ´Ï´Ù.

WidgetÀÇ °³¿ä

FAQ¿¡¼­µµ ¾ð±ÞÇß°í, ÀÌ ¹®¼­ÀÇ º»¹®¿¡µµ ¿©·¯¹ø °­Á¶µÆÁö¸¸, GTK+Àº C¾ð¾îÀÇ typedef struct{...} WidgetObject; °°Àº ÀÌ¿ëÀ¸·Î "°´Ã¼ÁöÇâ±â¹ý"À» Ãß±¸ÇÏ°í ÀÖ½À´Ï´Ù. ¹°·Ð C++¿¡¼­ÀÇ public member functionÀ» Èä³»³»±â À§ÇØ return_type (*func_pointer)(parameters,...) À¸·Î ¼±¾ðµÇ´Â callback ÇÔ¼ö¸¦ ¾¹´Ï´Ù. ¿©±â¼­ func_pointerÀÇ Á¤Ã¼¸¦ ¾Ë°í, ±×¸®°í Àß ½á¸ÔÀ» ¼ö ÀÖÀ» Á¤µµÀÇ "C¾ð¾î ½Ç·Â(?)"¸¸ ÀÖ´Ù¸é GTK¸¦ °ñ·Á°¡¸ç ÀÌ±æ ¼ö ÀÖÀ» °Ì´Ï´Ù. GTK+Àº ÀÌ·¸°Ô ±×´ÙÁö ¾î·Á¿î °Ô ¾Æ´Õ´Ï´Ù. :) ÀÌ Àå¿¡¼­´Â GTK+ ObjectÀÇ ÀüºÎ³ª ´Ù¸§¾ø´Â widget¿¡ ´ëÇØ, ÀÏÁ¾ÀÇ °ø°Ý ÀÛÀü¼³¸íÀ» ÇØÁÖ°í ÀÖ½À´Ï´Ù. ÀÌ¹Ì ´Ù¸¥ Widget Áý´ÜÀ» ½áº» °æÇè ȤÀº ÃÖ¼ÒÇÑ Xlib¸¦ ´Ù·ïº» °æÇèÀÌ ÀÖ´Ù¸é C¾ð¾î¿¡ ´ÉÅëÇÑ °Í¸¸Å­À̳ª Å« µµ¿òÀÌ µÉ °ÍÀÔ´Ï´Ù. Âü, ÀÌ Àå¿¡´Â Gtk widget objectµéÀÇ °èÃþ±¸Á¶µµ ÁÙÁÙÀÌ ¼Ò°³µÇ¾î ÀÖ½À´Ï´Ù. ¸Å¿ì ¿ä±äÇÑ Á¤º¸ÁÒ.

¹öÆ° widget

¿ì¼± Á¦ÀÏ ¸¸¸¸ÇÑ widgetÀ¸·Î ¹öÆ°À» ÇØÄ¡¿ì°í ÀÖ½À´Ï´Ù. ±×³É ¹öÆ°, ÀÌ»Û ¹öÆ°(ÇȽº¸ÊÀÌ ºÙÀº *), ƯÀÌÇÑ ¹öÆ°(Åä±Û, üũ, ¶óµð¿À,..) µî ¿ì¸®°¡ À©µµ¿ë ÀÀ¿ë¾îÇõ鿡¼­ ¸¹ÀÌ ÀÌ¿ëÇØ ¿Â ¸ðµç(?) Á¾·ùÀÇ ¹öÆ°µéÀ» ÆÄÇìĨ´Ï´Ù.

´Ù¾çÇÑ widgetµé

ÀÚ±â È¥ÀÚ ¾²À̱⺸´Ù ´Ù¸¥ widgetÀ» ²Ù¹Ì±â À§ÇØ ¾²ÀÌ´Â °æÇâÀÌ ÀÖ´Â ¸î°¡Áö Àâ´ÙÇÑ widgetÀ» ¼Ò°³ÇÕ´Ï´Ù. ¶óº§(label), dz¼±µµ¿ò¸»(tooltip), ÁøÇà ¸·´ë(progress bar), ´ëÈ­»óÀÚ(dialog box), ÇȽº¸Ê(pixmap) µîÀÔ´Ï´Ù. ƯÈ÷ ÇȽº¸Ê¿¡ ´ëÇؼ­´Â ²Ï ±æ°í ÀÚ»óÇÏ°Ô(?) ´Ù·ð±º¿ä. TooltipÀ» dz¼±µµ¿ò¸»À̶ó°í Çؼ®ÇÑ °Ç, MacOS(ÇѱÛÆÇ)¿¡¼­ ±×·± °É dz¼±µµ¿ò¸»À̶ó ºÎ¸£´Â µ¥ Àͼ÷ÇØÁ³±â ¶§¹®ÀÔ´Ï´Ù. ¶Ç´Ù¸¥ Ç¥ÇöÀº ¸ô¶ó¿ä. :) ¶Ç, °£´ÜÇϸ鼭µµ °ÅÀÇ ¸ðµç ¾îÇõ鿡¼­ ¿ä±äÇÏ°Ô ¾²ÀÏ ÆÄÀϼ±Åà ¹Ú½º°¡ ¼Ò°³µÇ¾î ÀÖ½À´Ï´Ù. ±×³É '½¬¾î°¡´Â ÆäÀÌÁö' Á¤µµ µÉ µí Çϳ׿ä. :) ¿¹Á¦¸¦ ÄÄÆÄÀÏÇؼ­ ½ÇÇàÇØ º¸¸é, ¿Ö ³Êµµ³ªµµ ÅøŶ(toolkit)À» ã´ÂÁö ¾Ë ¼ö ÀÖÀ» °Ì´Ï´Ù.

ÄÁÅ×ÀÌ³Ê widget

³ëÆ®ºÏ(notebook)°ú ½ºÅ©·ÑµÈ À©µµ(scrolled window)¸¦ ´Ù·ì´Ï´Ù. À̵éÀº °á°úÀûÀ¸·Î º¸¿©Áö°Ô µÉ ´Ù¸¥ widgetµéÀ» Á¶Á÷ÀûÀ¸·Î °ü¸®ÇÏ´Â widget µéÀÔ´Ï´Ù. À¥½áÄ¡¿£Áø(Yahoo,Altavista,..)À¸·Î ÈçÇÑ ´Ü¾î, ¿¹¸¦µé¾î "girl"À» °Ë»öÇغ¸¸é ´Ùµé ¾Ë´Ù½ÃÇÇ ¹«Áö¸·ÁöÇÑ °¹¼öÀÇ ¸µÅ©°¡ ½ñ¾ÆÁöÁÒ? À̶§ È­¸éÀ» °ü¸®Çϱâ À§ÇØ À¥ºê¶ó¿ìÀú À©µµ´Â ½ºÅ©·ÑµË´Ï´Ù. Áï, ½ºÅ©·Ñ¹Ù(scroll bar)°¡ »ý±âÁÒ. ÇÏÁö¸¸ "girl"ÀÇ °æ¿ìó·³ ¼öõ ¼ö¸¸ °³ÀÇ ¸µÅ©¸¦ °¡Á³´Ù¸é ½ºÅ©·Ñ¹Ù ·Îµµ °¨´ç¸øÇÏÁÒ? ±×·¡¼­ ±× ÆäÀÌÁöÀÇ Á¦ÀÏ ¾Æ·¡ÂÊ¿¡ ³»·Á¿Íº¸¸é Àüü ¸µÅ©¸¦ 1ºÎÅÍ 20±îÁö, ±×¸®°í <´õ ÀÖÀ½(NEXT)>À̶ó´Â, ÆäÀÌÁö(page)·Î °ü¸®ÇÏ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ½À´Ï´Ù. ÀÌ·¸°Ô ÆäÀÌÁö¸¦ °ü¸®ÇÏ´Â °Ô ³ëÆ®ºÏÀÔ´Ï´Ù.

¸®½ºÆ® widget

ÆÄÀϸŴÏÀú(file manager)°¡ °¡Àå ÁÁÀº ¿¹°¡ µÇ°Ú³×¿ä. M$À©µµ±×ÀÇ Å½»ö±â(explorer)³ª TkDeskÀÇ ÆÄÀÏ°ü¸®Ã¢À» º¸¸é, °¢ ÆÄÀÏÀÇ À̸§°ú ¼Ó¼ºµéÀ» ¾ÆÀÌÅÛ(item)À¸·Î ÇÏ´Â ¸®½ºÆ®(list)·Î ÀÌ·ç¾îÁ® ÀÖ½À´Ï´Ù. ÀÌ Àå¿¡¼­ ´Ù·ç´Â °ÍÀº ÀÌ·± ¸®½ºÆ®¸¦ ¸¸µå´Â ¹æ¹ý°ú, ¸¶¿ì½º¹öÆ°ÀÇ Á¿ìŬ¸¯À» ÀûÀýÈ÷ ³¢¿ö¸ÂÃç ¼±ÅÃ(selection)À» °ü¸®ÇÏ´Â ¹æ¹ý µîÀÔ´Ï´Ù. °£´ÜÇÑ ¿¹Á¦ ÇÁ·Î±×·¥ÀÌ ÀÖÀ¸´Ï Âü°íÇϼ¼¿ä.

¸Þ´º widget

¸Þ´º(menu)¸¦ ¸¸µå´Â ¹æ¹ýÀ» ¼Ò°³ÇÏ°í ÀÖ½À´Ï´Ù. GTK+ ¿ª½Ã ÇϳªÀÇ ÅøŶÀ̴ϱñ ³ª¸§´ë·Î ¸Þ´º Çϳª ¸¸µé¾î ÁÖ´Â ÇÔ¼ö ÂëÀº Á¦°øÇÕ´Ï´Ù. ±×¸®°í ¼¶¼¼ÇÔ¿¡¼± ¾à°£ ¶³¾îÁöÁö¸¸, ¸Þ´º¸¦ ¿Õâ ´ë·®»ý»êÇØÁÖ´Â °øÀå(factory)µµ Á¦°øÇÕ´Ï´Ù. ¸Þ´º¿¡´Â Ç®´Ù¿î(pull-down)°ú Æ˾÷(pop-up) µÎ°¡Áö°¡ ÀÖÁÒ. ±×¸®°í ½¬¿î ¹æ¹ý°ú "´õ" ½¬¿î ¹æ¹ý(¸Þ´º°øÀå)À» °¢°¢ ÀÌÇØÇÒ ¼ö ÀÖµµ·Ï µÎ ¿¹Á¦ ÇÁ·Î±×·¥ÀÌ ¼Ò°³µÇ¾ú½À´Ï´Ù.

ÅؽºÆ® widget

¸¹Àº ¾çÀÇ ÅؽºÆ®¸¦ ´Ù·ê ¶§ Æí¸®ÇÑ ÅؽºÆ® widget¿¡ °üÇØ ¼³¸íÇÏ°í ÀÖ½À´Ï´Ù. ÀÌ widgetÀº ÀÏ¹Ý ÅؽºÆ® ¿¡µðÅͳª ºä¾î¿Í ºñ½ÁÇÑ ±â´ÉÀ» °®°í ÀÖ½À´Ï´Ù.

¹®¼­È­µÇÁö ¾ÊÀº widgetµé

'ÀÌ·± °Íµé¿¡ ´ëÇؼ­´Â ¾ÆÁ÷ Æ©Å丮¾óÀÌ ¾øÀ¸´Ï ´ç½ÅÀÌ ÇÑ ¹ø ¸¸µé¾î ºÁ!' -> ÀÌ·¯´Â±º¿ä. :) ´©°¡ º»º¸±â·Î Preview¶ó´Â widget¿¡ ´ëÇØ ½á³ù´Ù¸ç ±× ¹®¼­¸¦ ÀοëÇß´õ±º¿ä. ÇÏÁö¸¸ Àü ±× ºÎºÐÀ» °ú°¨È÷(?!) »èÁ¦ÇÏ°í ÀÌ Àå Àüü¸¦ ºñ¿öµ×½À´Ï´Ù. (Á˼۠*) www.gtk.org¿¡ ÀÖ´Â ¿ø¹®À» Âü°íÇϼ¼¿ä.

À̺¥Æ®¹Ú½º widget

gtk+970916.tar.gz ÀÌÈÄÀÇ ¹èÆ÷º»¿¡¼­¸¸ Áö¿øÇÏ´Â widgetÀ̶ó´Â±º¿ä. ¸Þ´ºµµ ¾Æ´Ï°í ¹öÆ°µµ ¾Æ´Ï°í, ¾î·µç °á°úÀûÀ¸·Î À¯¿ëÇÏ°Ô(?) ¾²Àδٳ׿ä. :)

WidgetÀÇ ¼Ó¼ºÀ» ¼¼ÆÃÇϱâ

Á¦¸ñÀº ±×·²µíÇÏÁö¸¸, ½ÇÁ¦·Î ÀÌ ÀåÀ» ¿­¾îº¸´Ï ÇÔ¼ö¿øÇü(prototype) ¸î °³ »ÓÀÌ´õ±º¿ä. ÇÏÁö¸¸ GTK+¿¡¼­µµ ¿ª½Ã ±ä ÇÔ¼öÀ̸§Àº ±× ÀÚü°¡ ¼³¸íÀÔ ´Ï´Ù. ù ºÎºÐ¿¡ ¹«½¼ ÀܼҸ®°¡ ÀÖ´øµ¥, ±×³É ÀÖ´Â ±×´ë·Î Çؼ®ÇØ µ×½À´Ï´Ù. °¢ widget objectµéÀÇ ¼Ó¼º(property)À» °ü¸®Çϱâ À§ÇÑ ÇÔ¼öµéÀÔ´Ï´Ù.

ŸÀӾƿô, ±×¸®°í I/O¿Í Idle ÇÔ¼öµé

ÁÖ¾îÁø ½Ã°£(milliseconds)¸¶´Ù È£ÃâµÇ´Â ÇÔ¼ö, ±×³É ´ë±âÇÏ´Â ÇÔ¼ö, µ¥ÀÌÅÍÀÇ À̵¿À» °¨½ÃÇÏ´Â(monitoring) ÇÔ¼ö µîÀÌ ¼Ò°³µÇ¾î ÀÖ½À´Ï´Ù. ¿¹Á¦´Â ¾øÁö¸¸ ´ëÃæ º¸¸é °¨ÀÌ ÀâÈú °Ì´Ï´Ù. ^^;

Selection °ü¸®Çϱâ

´ëºÎºÐÀÇ Å͹̳ÎÀ̳ª ¿¡µðÅÍ(editor)´Â ¸¶¿ì½º·Î º»¹®À» Âï ±ÜÀ¸¸é ±× ¼±ÅÃµÈ ¿µ¿ªÀÌ ¹ÝÀüµÇ°í, ¸Þ´º¿¡¼­ ±× ¿µ¿ª¿¡ ´ëÇØ Ä«ÇÇ(copy), ÄÆ(cut), ÆäÀ̽ºÆ®(paste) µîÀÇ ÀÛ¾÷À» ÇÒ ¼ö ÀÖ½À´Ï´Ù. ±×·±µ¥ ¾î¶² ¿¡µðÅÍ¿¡¼­ ¹º°¡ ±Ü¾î³õ°í °ð¹Ù·Î ´Ù¸¥ ¿¡µðÅÍÀÇ ¶Ç ÇÑ ¿µ¿ªÀ» ±ÜÀ¸¸é º¸Åë ¾î¶»°Ô µÇ´ø°¡¿ä? Á¦°¡ ±â¾ïÇÏ´Â °ÅÀÇ ¸ðµç ¾îÇÃÀÇ °æ¿ì, ¸ÕÀú ±Ü¾ú´ø ³»¿ëÀº '¹«½Ã'µÇ´õ±º¿ä. ÀÌ·± ¹®Á¦¸¦ selectionÀÌ °ü¸®ÇÕ´Ï´Ù. ±²ÀåÈ÷ ¾î·Á¿î ´Ü¾îµµ ÀÖ°í Çؼ­, °Ü¿ì ¹ø¿ªÇß½À´Ï´Ù. (¿ø¹®Àº ²Ï ÀоîÁÙ ¸¸ Çߴµ¥, Á¦°¡ ¹ø¿ªÇÑ °Ç ³ªµµ ÀбⰡ ½È³×¿ä. :)

glib

GTK+ FAQ¿¡¼­µµ °£´ÜÈ÷ ¹àÇûÁö¸¸, GTK+´Â ±âÁ¸ÀÇ libc°¡ ¾Æ´Ñ, glib¸¦ ÀÌ¿ëÇÕ´Ï´Ù. ´çÀå °¢ Ç÷§Æû¿¡¼­ ÀÌ »õ·Î¿î ¹öÀüÀÇ C ¶óÀ̺귯¸®¸¦ ¼³Ä¡ÇØ¾ß ÇÒ »Ó¸¸ ¾Æ´Ï¶ó, ¸î°¡Áö Ç¥ÁØÇÔ¼öµéÀÌ glib¿¡¼­ ¾î¶»°Ô º¯Çß´ÂÁö ´ëÃæ ¾Ë¾Æ³ö¾ß ÇÏ°ÚÁÒ. (ÀϹÝÀûÀÎ »ç¿ëÀÚ ÀÔÀå¿¡¼­´Â º°·Î º¯ÇÑ °Ô ¾ø½À´Ï´Ù, ¿ø·¡ printf°¡ g_print·Î ¹Ù²ï ½ÄÀ̴ϱñ¿ä. ;) ÀÌ Àå¿¡¼­´Â ±âÁ¸ÀÇ libc¿¡¼­´Â Á¦°øÇÏÁö ¾Ê´Â »õ·Î¿î °ÍµéÀ» À§ÁÖ·Î, °£´ÜÇÑ ¼³¸íÀ» ÇÏ°í ÀÖ½À´Ï´Ù. °¢ ÀÚ·áÇü¸¶´ÙÀÇ ±ØÇÑ°ª(extrema)°ú, ¾ÆÅ°ÅØÃÄ (architecture)¿¡ °ü°è¾øÀÌ typedefµÈ ÁÖ¿ä ÀÚ·áÇü(data type)µé, ±×¸®°í ¸»ÀÌ ³ª¿Â ±è¿¡ ÁÙÁÙÀÌ ¿¬°á¸®½ºÆ®(linked list)µµ ¼Ò°³ÇØ ³ù±º¿ä. ±âÁ¸ÀÇ ¸Þ¸ð¸® °ü¸® ÇÔ¼ö ´ë½Å ¾²¶ó¸é¼­ g_malloc/g_free¸¦ ºñ·ÔÇÑ, glibÆÇÀÇ ¸Þ¸ð¸®ÇÔ¼öµéµµ ÀÖÀ¸¸ç, ½Ã½ºÅÛ Å¸À̸Ó(timer)ÇÔ¼ö, ¹®ÀÚ¿­(string)ÇÔ¼ö±îÁö Àֳ׿ä. ±×¸®°í ³¡À¸·Î À¯Æ¿¸®Æ¼ ¹× ¿¡·¯ÇÔ¼öµéÀ» ¼Ò°³Çß½À´Ï´Ù.

GTKÀÇ rc ÆÄÀÏ

À¯´Ð½º °è¿­ÀÇ ¿î¿µÃ¼Á¦¸¦ ÀÌ¿ëÇÏ´Â ºÐÀ̶ó¸é ²Þ¿¡¼­µµ ÀÌ rcÆÄÀÏÀ» ÆíÁýÇÏÁö³ª ¾ÊÀ»Áö ¸ð¸£°Ú³×¿ä. ^^; ÀÌ Àå¿¡¼­´Â ¿ì¸®°¡ Àͼ÷ÇØÁø ¾îÇõéó·³, ¶È°°Àº ¹ÙÀ̳ʸ®(binary,executable)¸¦ °¢ »ç¿ëÀÚÀÇ ÀÔ¸À¿¡ ¸Â°Ô 'ȯ°æ¼³Á¤'À» Çؼ­ ÀÌ¿ëÇÒ ¼ö ÀÖ°Ô ÇÏ´Â °É ¼Ò°³ÇÕ´Ï´Ù. GTK+ÀÇ rcÆÄÀÏÀº ´Ù¸¥ ´ëºÎºÐÀÇ X¿ë ¾îÇõé°ú ºñ½ÁÇÑ, ÀÏ°ü¼º ÀÖ´Â ½Éº¼(simbol)À» ÀÌ¿ëÇÕ´Ï´Ù. ¸¶Áö¸· ºÎºÐ¿¡ ¿¹Á¦ rcÆÄÀÏÀÌ ÀÖÀ¸´Ï Âü°íÇϼ¼¿ä.

ÀڽŸ¸ÀÇ widget ¸¸µé±â

ÀÌ ÀåÀÇ ³»¿ëÀº "Creating Your Own Widgets", Áï "ÀڽŸ¸ÀÇ widget ¸¸µé±â" ÀÔ´Ï´Ù. ½ÇÁ¦ ÇÏ´Â ¿ªÇÒµµ ±×·¸Áö¸¸ À̸§µµ Tictactoe¶ó´Â widgetÀ» ÀÌ·¸°Ô Àú·¸°Ô ¸¸µé¾î °¡´Â °úÁ¤¿¡¼­ ¿©·¯°¡Áö ÁÖÀDz¨¸®/Âü°í²¨¸®¸¦ ´Ã¾î³õ¾Ò½À´Ï´Ù. WidgetÀ» ¸¸µç´Ù´Â °Ç ÀÌ¹Ì ÀÖ´Â widgetÀ» ÀÌ¿ëÇÏ´Â °Í°ú´Â ¶Ç´Ù¸¥ °³³äÀ¸·Î, ¸î°¡Áö Áý°í ³Ñ¾î°¥ °ÍÀÌ ÀÖ½À´Ï´Ù. ¿ì¼±, ÁøÂ¥ ÇãÇã¹úÆÇ¿¡¼­ ½ÃÀÛ ÇÏ´Â °Ô ¾Æ´Ï¶ó "¾îµð¼­ »ó¼Ó"¹ÞÀ» °ÍÀÎÁö¸¦, Áï ±×ÀÇ parent class¸¦ ¼±ÅÃÇØ¾ß ÇÕ´Ï´Ù. ±×¸®°í ÀÌ widgetÀÌ Ã³¸®ÇؾßÇÒ ½Ã±×³Î°ú À̺¥Æ®¿¡ ´ëÇؼ­µµ ¸ñÀû¿¡ ¸Â°Ô "Àß" ¼³Á¤ÇؾßÁÒ. ±×¸®°í ÀÌ ÀåÀÇ ¸¶Áö¸·¿¡¼­´Â, ÀÌ·¸°Ô ¾Ö½á(?) ¸¸µç widgetµéÀÇ ¾î¼³Ç ¹®Á¦Á¡µéÀ» ÁöÀûÇÏ°í, ±× ÇØ°á¹æÇâÀ» Á¦½ÃÇÏ°í ÀÖ±º¿ä.

³«¼­Àå, °£´ÜÇÑ ±×¸®±â ¿¹Á¦

»ó´çÈ÷ ¹æ´ëÇÏ°í Àâ´ÙÇÑ(?) ³»¿ëÀ» ´Ù·ç´Â ÀåÀÔ´Ï´Ù. GIMPó·³, ÁøÂ¥ ±×¸²À» ´Ù·ç±â À§Çؼ­ ¾Ë¾Æ¾ß ÇÒ °ÍµéÀ̶ó°í Çϴ±º¿ä. ¸ÕÀú ¸¶¿ì½º¿Í Å°º¸µåÀÇ ¹Ì¹¦ÇÑ Àú¼öÁØ À̺¥Æ®(low-level event)¸¦ ´Ù·ç°í ÀÖ½À´Ï´Ù. Xlib¿¡¼­ Á¢ÇÒ ¼ö ÀÖµíÀÌ ¿©·¯ #define »ó¼öµéÀ» ºñÆ®¿¬»ê (bitwise operation)½ÃÅ°´Â °ÅÁÒ. ÀÌ »ó¼öµéÀº Å°º¸µå¿Í ¸¶¿ì½º¿¡¼­ ÀϾ´Â ¿©·¯°¡Áö À̺¥Æ®µéÀ» ¼¶¼¼ÇÏ°Ô ±¸º°Çϱâ À§ÇÑ °ÍÀÌ°ÚÁÒ? µÚ¸¦ ÀÕ´Â ³ðµéÀº ³«¼­¸¦ ÇÒ µµÈ­Áö¸¦ °ü¸®ÇÏ´Â ¹æ¹ýÀÔ´Ï´Ù. ´ëºÎºÐÀÇ widget°ú ÇÔ¼öµéÀº GTKÀÇ º£À̽º(base)¸¦ ÀÌ·ç´Â GDK(General Drawing Kits) ¶óÀ̺귯¸®¿¡¼­ ¿Â °Íµé ÀÔ´Ï´Ù. À©µµ¿¡ Á÷Á¢ ±×¸®´Â °Íº¸´Ù, ÇȽº¸ÊÀ̶ó´Â °¡»óÀÇ µµÈ­Áö¿¡ ±×·Á³õ°í ±× ³»¿ëÀ» ÇÊ¿äÇÒ ¶§ À©µµ·Î º¹»çÇØ ÁÖ´Â ¹æ½ÄÀ» ¾²ÁÒ, Xlib¿¡¼­Ã³·³. ´ÙÀ½¿£ ÇȽº¸Ê¿¡ ±×¸²À» ±×¸®´Â µµ±¸µé¿¡ ´ëÇØ ÀܼҸ®°¡ À̾îÁý´Ï´Ù. Xlib¿¡¼­ GC(Graphics Context)¶õ ³ðÀ» ±¸°æÇØ ºÃ´Ù¸é ´õ ½±°Ô ÀÌÇØÇÒ ¼ö ÀÖÀ» °Ì´Ï´Ù. ¿¹¸¦µé¾î »ç°¢ÇüÀ» Çϳª ±×¸®´Â µµ±¸´Â gdk_draw_rectangle()À̶õ ³ð Àε¥, »ç°¢ÇüÀ» ÀÌ·ç´Â ¼±ÀÇ ±½±â, »ö±ò, Á¾·ù(½Ç¼±/Á¡¼±/¼â¼±) µî ±âº»ÀûÀÎ ¼Ó¼ºµéÀ» GC¿¡ ÀúÀåÇØ ³õ°í, ½ÇÁ¦·Î ±×¸± ¶§´Â gdk_draw_rectangleÀ̶õ ÇÔ¼öÀÇ ÀÎÀڷμ­ ÇØ´çÇÏ´Â ¼Ó¼ºÀ» °¡Áö°í ÀÖ´Â GC¸¦ ³Ñ°ÜÁÝ´Ï´Ù. ¹°·Ð GTK+´Â ÃæºÐÈ÷ °´Ã¼ÁöÇâÀûÀ̱⠶§¹®¿¡ ±âº»¸¸ ÀÌÇØÇÑ´Ù¸é Xlib¿¡¼­º¸´Ù ´õ Á÷°üÀûÀ¸·Î Áñ±æ ¼ö ÀÖÀ» °Ì´Ï´Ù. ¾ÆÁ÷ ³¡³ªÁö ¾Ê¾Ò±º¿ä! -_-; ÀÌ Àå¿¡¼­´Â ´õ ¼¶¼¼ÇÑ ±×¸²À» ±×¸®±â À§ÇØ ¸¶¿ì½ºº¸´Ù ´õ ÁÁÀº(´õ ºñ½Ñ?) ÀÔ·ÂÀåÄ¡¸¦ ÀÌ¿ëÇÒ °ÍÀ», Àº±ÙÈ÷ ºÎÃß±â°í ÀÖ½À´Ï´Ù. Drawing tablet°°Àº, Ư¼öÇÑ ÀÔ·ÂÀåÄ¡¿¡¼­ ¹ß»ýÇÏ´Â ¶Ç´Ù¸¥ À̺¥Æ® µéÀ» ´Ù·ç±â À§ÇØ È®ÀåÀ̺¥Æ®(extended event)¸¦ Á¦°øÇÑ´Ù°í Çϳ׿ä. ¸¶¿ì½º ¿¡¼­ ¹ß»ýÇÏ´Â ¸î°¡Áö À̺¥Æ®¸¸À¸·Îµµ ¸Ó¸®°¡ ¾Æǵ¥ ¸»ÀÔ´Ï´Ù. :) ¾î·µç ÀÌ ÀåÀÇ ¸¶Áö¸·¿¡¼­´Â, ¸¶¿ì½ºº¸´Ù ´õ ÁÁÀº ÀåÄ¡(device)ÀÇ ±â´ÉÀ» ÀÌ¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ À̾߱âÇÏ°í ÀÖ½À´Ï´Ù.

GTK ¾îÇÃÀ» °³¹ßÇÏ´Â ÆÁ

³Ê¹« Áß¿äÇÑ ³»¿ëÀ̶ó ²À Á÷Á¢ º¸¶ó°í¹Û¿¡´Â ¸»ÇÒ ¼ö ¾ø³×¿ä. ;)

Contributing

¿ª½Ã ¸Å¿ì Áß¿äÇÑ °Ì´Ï´Ù.

Credits

ÀÌ ¹®¼­¸¦ Á¦ÀÛÇÏ´Â µ¥ µµ¿òÀÌ µÈ »ç¶÷µé¿¡°Ô °¨»çÀÇ ¸»À» ÀüÇÏ´Â, ¿ª½Ã ¾ÆÁÖ Áß¿äÇÑ ÀåÀÔ´Ï´Ù. ÀϺΠ¿ø¹®À» ±×´ë·Î µ×½À´Ï´Ù.

Tutorial Copyright and Permissions Notice

GPL¿¡ ÀÇÇÑ ¸ðµç ¹®¼­¿¡¼­ º¼ ¼ö ÀÖ´Â, Á¤¸» Áß¿äÇÑ ±ÛÀÔ´Ï´Ù. ÀϺη¯ ¿ø¹®À» ±×´ë·Î ³öµ×½À´Ï´Ù.

Á¦°¡ 3¿ù 26ÀÏ¿¡ ÀԴ븦 ÇÏ´Â °ü°è·Î liberta@zeus.phys.cau.ac.kr, ±×¸®°í liberta@cau.ac.kr ·Î ¸ÞÀÏÀ» º¸³»¼Åµµ ´äÀÌ ¾øÀ» °Ì´Ï´Ù. :) ÀÌ ¹®¼­¿¡ ´ëÇÑ Ãß°¡¿Í ¼öÁ¤, ±×¸®°í ¾î¶² °÷À¸·ÎÀÇ ¾÷·Îµå µîÀº ÀüÀûÀ¸·Î Àڽſ¡°Ô ´Þ·Á ÀÖ½À´Ï´Ù. ±×·³ GTK+°ú ÇÔ²² Áñ°Å¿î ¿©ÇàÀ» ÇÏ½Ã±æ ¹Ù¶ø´Ï´Ù. :)

(¼­ÁÖÅ´ÔÀÌ ¹ø¿ªÇϽŠÀÌ ¹®¼­¸¦ ÇÑÁöÈ£°¡ ´Ù½Ã ÀÏ¹Ý text¿¡¼­ SGML ÇüÅ·Π¹Ù²Ù°í ÃֽŠ¿ø¹®ÀÎ 5¿ù 24ÀÏÀÚ TutorialÀ» ÂüÁ¶Çؼ­ ´Þ¶óÁø ºÎºÐÀ» º¸ÅÂ¾î ¼öÁ¤Çß½À´Ï´Ù. ÀÌ ¹®¼­¸¦ ÀÐÀ¸½Ã´Ù°¡ °©Àڱ⠹ø¿ªÀÌ ¿­¾ÇÇØÁ³´Ù°í ´À³¢½Ã´Â ºÎºÐÀÌ ÀÖ´Ù¸é ¾Æ¸¶ ±× ºÎºÐÀº ÇÑÁöÈ£°¡ »õ·Î ¹ø¿ªÇؼ­ Ãß°¡ÇÑ °÷ÀÏ°Ì´Ï´Ù. ^^; ÀÌ ±ä ¹®¼­¸¦ ¹ø¿ªÇÏ¿© ÁֽôÀ¶ó ¼ö°íÇϽŠ¼­ÁÖÅ´Բ² °¨»çµå¸³´Ï´Ù. Ȥ½Ã À߸ø ¹ø¿ªµÈ °÷À̳ª ½Ç¼ö, ¿ÀÀÚ¸¦ ¹ß°ßÇϽŠºÐÀº hanjiho@penta.co.kr·Î ¸ÞÀÏÀ» º¸³»ÁÖ½Ã¸é ¹«Ã´ °í¸¿°Ú½À´Ï´Ù. ¼­ÁÖÅÂ´Ô ¸»¾¸´ë·Î GTK+¿Í Áñ°Å¿î ¿©ÇàÀ» ÇÏ½Ã±æ ¹Ù¶ø´Ï´Ù.)

2. ¼Ò°³

GTK(GIMP Toolkit)Àº ¿ø·¡ GIMP(General Image Manipulation Program)À» ¸¸µé±â À§ÇÑ ÅøŶÀ¸·Î °³¹ßµÇ¾ú´Ù. GTK´Â XlibÀÇ ÇÔ¼öµé¿¡ ´ëÇÑ ±âº»ÀûÀÎ wrapperÀÎ GDK(GIMP Drawing Kit)¸¦ ±â¹ÝÀ¸·Î ÇÏ°í ÀÖ´Ù. ¿ø·¡ GIMP¸¦ ¸¸µé ¸ñÀûÀ¸·Î °³¹ßµÇ¾úÁö¸¸, Áö±ÝÀº ¸î °¡Áö ÇÁ¸® ¼ÒÇÁÆ®¿þ¾îÀÇ Á¦ÀÛ¿¡ ¾²ÀÌ°Ô µÇ¾ú´Ù. GTKÀÇ Á¦ÀÛÀÚµéÀº ´ÙÀ½°ú °°´Ù.

GTK´Â º»ÁúÀûÀ¸·Î °´Ã¼ÁöÇâÀûÀÎ ¾îÇà °³¹ßÀÚ È¯°æÀÌ´Ù(API, Application Programmers Interface). ºñ·Ï ¿ÏÀüÈ÷ C·Î ¾²¿©Á³Áö¸¸ Ŭ·¡½ºÀÇ °³³ä°ú callback ÇÔ¼ö(ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅÍ)°¡ °®Ãß¾îÁø °ÍÀÌ´Ù.

¿©±â¿¡´Â ¿¬°á¸®½ºÆ®(linked list)¸¦ ´Ù·ç±â À§ÇÑ ¸î °¡Áö ÇÔ¼öµé°ú ÇÔ²², glib¶ó°í ºÒ¸®¿ì¸ç ¸î °¡Áö Ç¥ÁØÇÔ¼öµéÀ» ´ëÄ¡ÇÒ ¼ö ÀÖ´Â ÇÔ¼öµéµµ ¼¼¹ø° ¿ä¼Ò·Î Æ÷ÇԵǾî ÀÖ´Ù. g_strerror()ó·³, ¿©±â ¾²ÀÎ ¾î¶² ÇÔ¼öµéÀº ´Ù¸¥ À¯´Ð½ºµé¿¡ ´ëÇØ Ç¥ÁØÀÌ ¾Æ´Ï°Å³ª ¾²¿©Áú ¼ö ¾ø´Â °ÍÀ̱⠶§¹®¿¡, GTKÀÇ À̽ļºÀ» ³ôÀ̱â À§ÇØ ¿©±â¿¡ ´ëÇÑ ´ëÄ¡ÇÔ¼öµéµµ ¾²¿´´Ù. ¶ÇÇÑ g_mallocÀÌ µð¹ö±ë ±â´ÉÀ» °­È­ÇßµíÀÌ libcÀÇ ¹öÀü¿¡ º¸°­ÀÌ ÀÌ·ç¾îÁö±âµµ Çß´Ù.

ÀÌ ¹®¼­´Â ´ÜÁö GTK¸¦ À§ÇÑ Âü°í°¡ µÉ »ÓÀ̸ç, ¿ÏÀüÇÑ °ÍÀ» ÀǹÌÇÏÁö ¾Ê´Â´Ù. µ¶ÀÚ´Â C¾ð¾î¸¦ Àß ¾Ë¸ç CÇÁ·Î±×·¥À» ¾î¶»°Ô ¸¸µå´ÂÁö ¾Ë°í ÀÖÀ» °ÍÀ̶ó°í °¡Á¤ ÇÑ´Ù. ²À ÇÊ¿äÇÑ °ÍÀº ¾Æ´Ï°ÚÁö¸¸, µ¶ÀÚ°¡ ÀÌ¹Ì X ÇÁ·Î±×·¥¿¡ ´ëÇÑ °æÇèÀÌ ÀÖ´Ù¸é ¸Å¿ì Å« µµ¿òÀÌ µÉ °ÍÀÌ´Ù. ¸¸¾à ´ç½ÅÀÌ widget ¼¼Æ®¿¡ ´ëÇØ GTK°¡ óÀ½ Á¢ÇÑ °ÍÀ̶ó¸é, ÀÌ ¹®¼­¸¦ ¾î¶»°Ô ¹ß°ßÇÏ°Ô µÇ¾ú°í ¶Ç Ưº°È÷ Èûµç ºÎºÐÀº ¾î¶² °ÍÀ̶ó´Â °ÍÀ» ²À ¾Ë·ÁÁֱ⠹ٶõ´Ù. GTK¸¦ À§ÇØ C++ÀÇ Çü½Ä¿¡ µû¸¥ APIµµ ÀÖ´Ù´Â °ÍÀ» ÂüÁ¶ÇÒ °ÍÀ̸ç, ¸¸¾à C++À» ´õ ¼±È£ÇÑ´Ù¸é ÀÌ°Í ´ë½Å¿¡ ±×°É ¼±ÅÃÇϱ⠹ٶõ´Ù. ¶ÇÇÑ Objective C, Guile°úÀÇ ¹ÙÀεùµµ ÀÖÁö¸¸, ¾î·µç ¿©±â¼­´Â ±×°ÍµéÀ» µû¸£Áö ¾Ê°Ú´Ù.

´ç½ÅÀÌ ÀÌ ¹®¼­¸¦ ÅëÇØ GTK¸¦ °øºÎÇÏ´Â µ¥ À־ ¾î¶² ¹®Á¦¶óµµ ³ª¿¡°Ô ¾Ë·Á Áֱ⠹ٶó¸ç, ±×°ÍÀº ÀÌ ¹®¼­°¡ Çâ»óµÇ´Â °Í¿¡ Å« µµ¿òÀÌ µÉ °ÍÀ̶ó°í »ý°¢ÇÑ´Ù.

3. ½ÃÀÛÇϸ鼭

¸ÕÀú ÇÒ ÀÏÀº ¹°·Ð GTKÀÇ ¼Ò½º¸¦ ¹Þ¾Æ¼­ ±×°ÍÀ» ¼³Ä¡ÇÏ´Â °ÍÀÌ´Ù. ¾ðÁ¦³ª °¡Àå ÃֽŠ¹öÀüÀ» ftp.gtk.orgÀÇ /pub/gtk¿¡¼­ °¡Á®¿Ã ¼ö ÀÖ´Ù. GTK¿¡ ´ëÇÑ ¶Ç´Ù¸¥ ¼Ò½ºµéÀº http://www.gtk.org/¿¡ ÀÖ´Ù. GTK´Â GNU autoconf¸¦ ÀÌ¿ëÇÑ´Ù. ÀÏ´Ü ¾ÐÃàÀ» Ǭ ´ÙÀ½¿¡, ./configure --help¸¦ Ãļ­ ¿É¼ÇµéÀ» »ìÆì º¸±â ¹Ù¶õ´Ù.

GTK¿¡ ´ëÇÑ ¼Ò°³¸¦ À§Çؼ­, °¡´ÉÇÑ ÇÑ °£´ÜÇÑ ÇÁ·Î±×·¥ºÎÅÍ ½ÃÀÛÇØ º¸ÀÚ. ÀÌ ÇÁ·Î±×·¥Àº 200x200 Çȼ¿ÀÇ À©µµ¸¦ ¸¸µå´Â °ÍÀ¸·Î, ½©À» ÀÌ¿ëÇÏÁö ¾Ê°í´Â ³¡³¾ ¼ö ¾ø´Â ÇÁ·Î±×·¥ÀÌ´Ù.

#include <gtk/gtk.h>

int main (int argc, char *argv[])
{
    GtkWidget *window;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
}
À§ ÇÁ·Î±×·¥À» gcc¸¦ »ç¿ëÇÏ¿© ÄÄÆÄÀÏÇÒ ¼ö ÀÖ´Ù.
gcc base.c -o base `pkg-config --cflags --libs gtk+-2.0`

¸ðµç ÇÁ·Î±×·¥Àº ¹°·Ð GTK ¾îÇÿ¡ ¾²ÀÏ º¯¼ö, ÇÔ¼ö, ±¸Á¶Ã¼ µîÀÌ ¼±¾ðµÇ¾î ÀÖ´Â gtk/gtk.h¸¦ Æ÷ÇÔÇÒ °ÍÀÌ´Ù.

gtk_init (&argc, &argv);

GTK·Î ¾²¿©Áö´Â ´Ù¸¥ ¸ðµç ÇÁ·Î±×·¥¿¡¼­ ºÎ¸£°Ô µÇ´Â ÇÔ¼öÀÎ gtk_init(gint *argc, gchar ***argv) ¸¦ ºÎ¸£°í ÀÖ´Ù. ÀÌ°ÍÀº µðÆúÆ®·Î ¾µ ºñÁÖ¾ó°ú Ä®¶ó¸Ê µî ¸î°¡Áö¸¦ ¼¼ÆÃÇÏ¸ç ±× ÀÌÈÄ gdk_init(gint *argc, gchar ***argv)·Î ³Ñ¾î°£´Ù. ÀÌ ÇÔ¼ö´Â ¾²ÀÏ ¶óÀ̺귯¸®¸¦ ÃʱâÈ­ ÇÏ°í, µðÆúÆ®·Î ½Ã±×³Î Çڵ鷯¸¦ ¼Â¾÷Çϸç, ¸í·ÉÇàÀ» ÅëÇØ ÇÁ·Î±×·¥¿¡ ÀüÇØÁø ÀÎÀÚµé Áß ¾Æ·¡ÀÇ °ÍµéÀ» ã¾Æ üũÇÑ´Ù.

  • --gtk-module
  • --g-fatal-warnings
  • --gtk-debug
  • --gtk-no-debug
  • --gdk-debug
  • --gdk-no-debug
  • --display
  • --sync
  • --name
  • --class

´ç½ÅÀÇ ¾îÇÃÀÌ ÀνÄÇÏÁö ¾ÊÀ» °ÍµéÀ» ³²°ÜµÎ°í, À§ÀÇ °ÍµéÀ» ÀÎÀÚÀÇ ¸®½ºÆ®¿¡¼­ Á¦°ÅÇÑ´Ù. ÀÌ°ÍÀº ¸ðµç GTK ¾îÇÿ¡¼­ »ý·«ÇÒ Ç¥ÁØÀûÀÎ ÀÎÀÚµéÀÇ ¼¼Æ®¸¦ ¸¸µç´Ù.

´ÙÀ½ÀÇ µÎ ÁÙ¿¡¼­´Â À©µµ¸¦ ¸¸µé°í º¸¿©ÁØ´Ù.

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);

GTK_WINDOW_TOPLEVELÀ̶õ ÀÎÀÚ´Â À©µµ ¸Å´ÏÀúÀÇ Àå½Ä°ú À§Ä¡¼³Á¤¿¡ µû¸£°Ô ÇÑ´Ù. 0x0 Å©±âÀÇ À©µµ¸¦ ¸¸µéÁö ¾Ê°í, child°¡ ¾ø´Â À©µµ´Â µðÆúÆ®·Î 200x200 Å©±â·Î ¸¸µé¾îÁ®¼­ ¿ì¸®´Â ±×°ÍÀ» ¸¶À½²¯ ´Ù·ê ¼ö ÀÖ´Ù.

gtk_widget_show() ÇÔ¼ö´Â ÀÌ widgetÀÇ ¼Ó¼º¿¡ ´ëÇÑ ¼¼ÆÃÀÌ ³¡³µÀ½À» GTK¿¡ ¾Ë·ÁÁÖ´Â °ÍÀÌ°í, ±×·¡¼­ ±× widgetÀº º¸¿©Áö°Ô µÈ´Ù.

¸¶Áö¸· ÁÙÀº GTKÀÇ ÁÖ Ã³¸® ·çÇÁ¿¡ µé¾î°¡´Â °ÍÀÌ´Ù.

gtk_main ();

gtk_main()Àº GTK ¾îÇà Àü¹ÝÀûÀ¸·Î º¼ ¼ö ÀÖ´Â ¶Ç ÇϳªÀÇ ÇÔ¼öÈ£ÃâÀÌ´Ù. ÇÁ·Î±×·¥ÀÌ ¿©±â¿¡ À̸£¸é, GTK´Â X À̺¥Æ®, ŸÀӾƿô, ¶Ç´Â ÆÄÀÏ ÀÔÃâ·Â °¨Áö µîÀ» ±â´Ù¸®¸ç ´ë±âÇÏ°Ô µÈ´Ù. ±×·¯³ª ÀÌ °£´ÜÇÑ ÇÁ·Î±×·¥¿¡¼­´Â ±×·± °ÍµéÀÌ ¹«½ÃµÇ°í ÀÖ´Ù.

3.1 GTK¿¡¼­ÀÇ Hello World ÇÁ·Î±×·¥

ÀÌÁ¦ ÇϳªÀÇ widget(¹öÆ°)À» À§ÇÑ ÇÁ·Î±×·¥ÀÌ´Ù, ±× À¯¸íÇÑ hello world¸¦ GTK·Î½á ±¸ÇöÇØ º¸ÀÚ.

/* helloworld.c */

#include <gtk/gtk.h>

/* ÀÌ°ÍÀº callbackÇÔ¼ö´Ù.  ¿©±â¼­´Â µ¥ÀÌÅÍÀÎÀÚµéÀÌ ¹«½ÃµÇ¾ú´Ù. */
static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello World\n");
}

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    g_print ("delete event occured\n");
    /* "delete_event"¶ó´Â ½Ã±×³ÎÇڵ鷯¿¡¼­ TRUE¸¦ ¸®ÅÏÇϸé,
     * GTK´Â "destroy" ½Ã±×³ÎÀ» ¹ß»ý½ÃŲ´Ù.  FALSE¸¦ ¸®ÅÏÇϸé
     * À©µµ°¡ ÁøÂ¥·Î Æı«µÇ±æ ¿øÇÏÁö ¾Ê´Â °ÍÀÌ´Ù.  ÀÌ°ÍÀº
     * 'ÁøÂ¥·Î ³¡³»·Æ´Ï±î?' °°Àº ´ëÈ­»óÀÚ°¡ Æ¢¾î³ª¿À°Ô ÇÒ ¶§
     * À¯¿ëÇÏ´Ù. */
       
    /* FALSE¸¦ TRUE·Î °íÄ¡¸é main À©µµ´Â "delete_event"¿Í ÇÔ²²
     * Æı«µÉ °ÍÀÌ´Ù. */
    return (FALSE);
}

/* ¶Ç´Ù¸¥ callback */
static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}

int main( int   argc,
          char *argv[] )
{
    /* GtkWidgetÀº widgetµéÀ» À§ÇÑ ±â¾ïÀå¼Ò ŸÀÔÀÌ´Ù. */
    GtkWidget *window;
    GtkWidget *button;

    /* ÀÌ°ÍÀº ¸ðµç GTK ¾îÇõ鿡¼­ È£ÃâµÈ´Ù.  ÀÎÀÚµéÀº ¸í·ÉÇà »óÀ¸·ÎºÎÅÍ
     * ÁÖ¾îÁ® ¾îÇ÷ΠÀüÇØÁø´Ù. */
    gtk_init (&argc, &argv);

    /* »õ·Î¿î À©µµ¸¦ ¸¸µç´Ù. */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* À©µµ°¡ "delete_event"¸¦ ¹ÞÀ¸¸é(ÀÌ´Â À©µµ¸Å´ÏÀú¸¦ ÅëÇÑ´Ù), ¿ì¸®´Â
     * À§¿¡¼­ Á¤ÀÇÇÑ ÇÔ¼ö delete_event()¸¦ È£ÃâÇÒ °ÍÀÎÁö È®ÀÎÇÑ´Ù.  ÀÌ
     * callbackÇÔ¼ö·Î ÀüÇØÁø µ¥ÀÌÅÍ´Â NULLÀÌ°í µû¶ó¼­ ¿©±â¼­ ¹«½ÃµÈ´Ù. */
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);

    /* ¿©±â¼­´Â ½Ã±×³ÎÇڵ鷯¿¡ "destroy" À̺¥Æ®¸¦ ¿¬°áÇØ ÁØ´Ù.
     * ÀÌ À̺¥Æ®´Â ¿ì¸®°¡ À©µµ¿¡ ´ëÇØ gtk_widget_destroy()¸¦ È£ÃâÇϰųª,
     * ¶Ç´Â "delete_event" callback¿¡¼­ 'TRUE'¸¦ ¸®ÅÏÇßÀ» ¶§ ¹ß»ýÇÑ´Ù. */
    g_signal_connect (window, "destroy",
                      G_CALLBACK (destroy), NULL);

    /* À©µµÀÇ border width¸¦ ¼¼ÆÃÇÑ´Ù. */
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* "Hello World"¶ó´Â ¶óº§ÀÌ ÀÖ´Â »õ·Î¿î ¹öÆ°À» ¸¸µç´Ù. */
    button = gtk_button_new_with_label ("Hello World");

    /* ¹öÆ°ÀÌ "clicked" ½Ã±×³ÎÀ» ¹ÞÀ¸¸é NULLÀ» ÀÎÀÚ·Î Çؼ­ hello()°¡
     * È£ÃâµÈ´Ù.  ÀÌ hello() ÇÔ¼ö´Â À§¿¡¼­ Á¤ÀǵǾú´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (hello), NULL);

    /* ÀÌ°ÍÀÌ "clicked"µÇ¸é gtk_widget_destroy(window)°¡ È£Ãâ, ±× À©µµ¸¦
     * Æı«ÇÏ°Ô µÈ´Ù.  ¾Õ¼­ ¼³¸íÇßµíÀÌ, 'destroy' ½Ã±×³ÎÀº ¿©±â¼­ ÀÌ·¸°Ô
     * ¹ß»ýÇϰųª, ¶Ç´Â À©µµ¸Å´ÏÀú¸¦ ÅëÇØ ¹ß»ýÇÑ´Ù. */
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              window);

    /* ÀÌ°ÍÀº ¹öÆ°À» À©µµ, Áï GTK ÄÁÅ×À̳ÊÀÇ Çϳª·Î ÆÐÅ·ÇÑ´Ù. */
    gtk_container_add (GTK_CONTAINER (window), button);

    /* ³¡À¸·Î »õ·Î ¸¸µç widgetÀÎ ¹öÆ°À» º¸¿©ÁÖ´Â °ÍÀÌ´Ù. */
    gtk_widget_show (button);

    /* À©µµ Àüü¸¦ ¿©±â¼­ º¸¿©ÁØ´Ù. */
    gtk_widget_show (window);

    /* ¸ðµç GTK ¾îÇÃÀº ²À gtk_main()À» Çϳª¾¿ °¡Áö°í ÀÖ´Ù.  ÄÁÆ®·ÑÀº
     * ¿©±â¼­ ³¡³ª°í ÀÌÁ¦ ¾î¶² À̺¥Æ®(Å°¸¦ ´©¸¥´Ù°Å³ª ¸¶¿ì½º¸¦ Á¶ÀÛÇÏ´Â
     * µîÀÇ)°¡ ¹ß»ýÇÒ ¶§±îÁö ´ë±âÇÑ´Ù. */
    gtk_main ();

    return 0;
}

3.2 Hello world¸¦ ÄÄÆÄÀÏÇϱâ

ÄÄÆÄÀÏÇϱâ À§ÇØ ÀÌ·¸°Ô Ç϶ó.

gcc -Wall -g helloworld.c -o helloworld `pkg-config --cflags gtk+-2.0` \
`pkg-config --libs gtk+-2.0`

gtk-config¶õ ÇÁ·Î±×·¥À» ÀÌ¿ëÇÏ¿´´Âµ¥, ÀÌ ÇÁ·Î±×·¥Àº http://www.freedesktop.org/¿¡¼­ ¹ÞÀ» ¼ö ÀÖ´Ù. ÀÌ ÇÁ·Î±×·¥Àº gtk¸¦ ¾²´Â ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇϱâ À§Çؼ­ ¾î¶² ÄÄÆÄÀÏ·¯ ½ºÀ§Ä¡µéÀÌ ÇÊ¿äÇÑÁö '¾Ë°í'ÀÖ´Ù. gtk-config --cflags gtk+-2.0 ´Â ÄÄÆÄÀÏ·¯°¡ header ÆÄÀϵéÀ» ã¾Æº¸¾Æ¾ß ÇÏ´Â include µð·ºÅ丮µéÀ» Ãâ·ÂÇÏ°í, gtk-config --libs gtk+-2.0 ´Â ¸µÅ©µÇ¾î¾ß ÇÏ´Â ¶óÀ̺귯¸®µé°ú ±× ¶óÀ̺귯¸®µéÀÌ Á¸ÀçÇÏ´Â µð·ºÅ丮µéÀ» Ãâ·ÂÇÑ´Ù.

º¸Åë ¸µÅ©½ÃÅ°´Â ¶óÀ̺귯¸®µéÀº ´ÙÀ½°ú °°Àº °ÍµéÀÌ´Ù.

  • The GTK library (-lgtk), GDK¸¦ ±â¹ÝÀ¸·ÎÇÑ widget ¶óÀ̺귯¸®´Ù.
  • The GDK library (-lgdk), Xlib¸¦ °¨Ãß¾î µÑ·¯½Ñ wrapper´Ù.
  • The gdk-pixbuf library (-lgdk_pixbuf), À̹ÌÁö¸¦ ´Ù·ç´Â ¶óÀ̺귯¸®´Ù.
  • The Pango library (-lpango), ±¹Á¦È­ ¶óÀ̺귯¸®´Ù.
  • The gobject library (-lgobject), GTKÀÇ ÇϺÎÀÇ Å¸ÀÔ ½Ã½ºÅÛÀ» Æ÷ÇÔÇÑ´Ù.
  • The gmodule library (-lgmodule), which is used to load run time extensions.
  • The glib library (-lglib), ´Ù¾çÇÑ ÇÔ¼ö¸¦ Æ÷ÇÔÇÏ°í ÀÖÀ¸¸ç, ¿©±â¼­ ¾²ÀÎ °ÍÀº g_print()ÇÔ¼ö´Ù. GTK´Â glib¸¦ ±â¹ÝÀ¸·Î ÇÏ°í ÀÖÀ¸¹Ç·Î ¾ðÁ¦³ª ÀÌ ¶óÀ̺귯¸®°¡ ÇÊ¿äÇÒ °ÍÀÌ´Ù. ÀÚ¼¼ÇÑ °ÍÀº glibÀ» ÂüÁ¶Ç϶ó.
  • The Xlib library (-lX11), GDK¿¡ ÀÇÇØ ¾²¿©Áö°Ô µÈ´Ù.
  • The Xext library (-lXext), ÀÌ°ÍÀº °øÀ¯ ¸Þ¸ð¸® pixmap°ú ´Ù¸¥ X È®Àåµé¿¡ ´ëÇÑ Äڵ带 À§ÇÑ °ÍÀÌ´Ù.
  • The math library (-lm), ÀÌ°ÍÀº ¿©·¯ ¸ñÀûÀ¸·Î GTK¿¡¼­ ¾²ÀÌ°Ô µÈ´Ù.

3.3 ½Ã±×³Î°ú callback¿¡ ´ëÇÑ ÀÌ·Ð

Hello world ÇÁ·Î±×·¥À» ÀÚ¼¼È÷ »ìÆ캸±â¿¡ ¾Õ¼­, À̺¥Æ®¿Í callback¿¡ ´ëÇØ Áý°í ³Ñ¾î°¡ÀÚ. GTK´Â À̺¥Æ®·Î µ¹¾Æ°¡´Â ÅøŶÀ̸ç, ÀÌ°ÍÀº ¾î¶² À̺¥Æ®°¡ ¹ß»ýÇؼ­ ÀûÀýÇÑ ´Ù¸¥ ÇÔ¼ö·Î Á¦¾î°¡ ³Ñ¾î°¡Áö ¾Ê´Â ÇÑ °è¼Ó ´ë±âÇÑ´Ù´Â Àǹ̴Ù.

ÀÌ Á¦¾î¸¦ ³Ñ±ä´Ù´Â °ÍÀº "½Ã±×³Î"ÀÇ ÀÌ¿ë¿¡ ÀÇÇØ ÀÌ·ç¾îÁø´Ù. ¸¶¿ì½º ¹öÆ°À» ´©¸£´Â °Í°°ÀÌ ¾î¶² À̺¥Æ®°¡ ÀÖÀ¸¸é, ´­·¯Á³´Ù¿¡ ÇØ´çÇÏ´Â ÀûÀýÇÑ ½Ã±×³ÎÀÌ widget¿¡ ÀÇÇØ "¹ß»ý"ÇÏ°Ô µÈ´Ù. ÀÌ°ÍÀÌ GTK°¡ ÇÏ´Â À¯¿ëÇÑ ÀÛ¾÷ÀÇ ´ëºÎºÐÀÌ´Ù. ¹öÆ°ÀÇ ÀÛ¿ëÀ¸·Î ¾î¶² µ¿ÀÛÀ» ½ÃÅ°·Á¸é, ¿ì¸®´Â ÀÌ·± ½Ã±×³ÎµéÀ» Àâ¾Æ³»µµ·Ï ½Ã±×³Î Çڵ鷯¸¦ ¼Â¾÷ÇÏ°í ÀÌ¿¡ Àû´çÇÑ ÇÔ¼ö¸¦ ºÎ¸£¸é µÈ´Ù. ÀÌ°ÍÀº ´ÙÀ½°ú °°Àº ÇÔ¼ö¸¦ ÀÌ¿ëÇÔÀ¸·Î½á ÀÌ·ç¾îÁø´Ù.

gulong g_signal_connect( gpointer    *object,
                         const gchar *name,
                         GCallback   func,
                         gpointer    func_data );

ù¹ø° ÀÎÀÚ´Â ½Ã±×³ÎÀ» ¹ß»ý½Ãų widgetÀÌ°í, µÎ¹ø°´Â Àâ¾Æ³»°íÀÚ ÇÏ´Â ½Ã±×³ÎÀÇ À̸§ÀÌ´Ù. ¼¼¹ø° ÀÎÀÚ´Â ±× ½Ã±×³ÎÀÌ Å½ÁöµÇ¾úÀ» ¶§ È£ÃâÇÒ ÇÔ¼ö¸ç, ³×¹ø°´Â ÀÌ ÇÔ¼ö¿¡ ³Ñ°ÜÁÙ Á¤º¸´Ù.

¼¼¹ø° ÀÎÀÚ·Î ³ª¿ÍÀÖ´Â ÇÔ¼ö¸¦ "callback ÇÔ¼ö"¶ó°í ºÎ¸£¸ç ´ÙÀ½Ã³·³ ÀÌ·ç¾îÁ® ÀÖ´Ù.

void callback_func( GtkWidget *widget,
                    ... /* other signal arguments */
                    gpointer   callback_data );

ÀÌ ÇÔ¼öÀÇ Ã¹¹ø° ÀÎÀÚ´Â ½Ã±×³ÎÀ» ¹ß»ý½ÃŲ widgetÀ» ÇâÇÑ Æ÷ÀÎÅÍ°¡ µÇ°í, ¸¶Áö¸· ÀÎÀÚ´Â À§¿¡ º¸ÀÎ g_signal_connect() ÇÔ¼öÀÇ ³×¹ø° ÀÎÀÚ·Î ÁÖ¾îÁ® ÀÖ´Â Á¤º¸¿¡ ´ëÇÑ Æ÷ÀÎÅÍ´Ù.

Hello world ¿¹Á¦¿¡¼­ ¾²ÀÎ ¶Ç´Ù¸¥ È£ÃâÀº ÀÌ°ÍÀÌ´Ù.

gulong g_signal_connect_swapped( gpointer     *object,
                                 const gchar  *name,
                                 GCallback    func,
                                 gpointer     *callback_data );

g_signal_connect_swapped()Àº callbackÇÔ¼ö°¡ GTK object¿¡ ´ëÇÑ Æ÷ÀÎÅͶó´Â, ´Ü ÇϳªÀÇ ÀÎÀÚ¸¦ ÀÌ¿ëÇÑ´Ù´Â Á¡¸¸ »©°í´Â gtk_signal_connect()¿Í °°´Ù. ±×·¯¹Ç·Î ½Ã±×³ÎÀ» ¿¬°á½Ãų ¶§ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù¸é callbackÇÔ¼ö´Â ÀÌ·± ¸ð¾çÀ» ÇØ¾ß ÇÒ °ÍÀÌ´Ù.

void callback_func( gpointer   callback_data,
                    ... /* other signal arguments */
                    GtkWidget *widget);

¿©±â¼­ÀÇ object¶õ ´ë°³ widgetÀ» ¸»ÇÑ´Ù. ¿ì¸®´Â ¾î·µç µÇµµ·Ï g_signal_connect_swapped()À» ÀÌ¿ëÇؼ­ callbackÀ» ¼Â¾÷ÇÏÁö´Â ¾ÊÀ» °ÍÀÌ´Ù. ÀÌ°ÍÀº ´ë°³ ´Ù¸¥ ¿ÀºêÁ§Æ®°¡ ½Ã±×³ÎÀ» ¹Þ¾Æ¼­ ó¸®Çϴµ¥, ´ÜÀÏÀÇ À§Á¬À̳ª ¿ÀºêÁ§Æ®¸¦ Àμö·Î ¹Þ¾ÆµéÀÌ´Â GTK ÇÔ¼ö¸¦ »ç¿ëÇÒ ¶§ »ç¿ëÇÑ´Ù. helloworld ¿¹Á¦¿¡ º¸¸é, ¹öÆ°ÀÇ "clicked" ½Ã±×³Î¿¡ À©µµ¿ìÀÇ gtk_widget_destroy()¸¦ È£ÃâÇÏ¿´´Ù.

Äݹé ÇÔ¼ö¿¡ ºÎ°¡ÀûÀÎ µ¥ÀÌŸ¸¦ »ç¿ëÇÏ·Á¸é g_signal_connect_swapped()ÀÌ ¾Æ´Ñ g_signal_connect()¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù.

3.4 À̺¥Æ® ÀÛ¼º ÇÊ¿ä

3.5 Hello World¸¦ µû¶ó ÇÑ°ÉÀ½¾¿

ÀÌÁ¦ Àû¿ëµÈ À̷п¡ ´ëÇØ ¾Ë¾Ò°í, hello world ¿¹Á¦ ÇÁ·Î±×·¥À» µû¶ó ´õ È®½ÇÈ÷ ÇصÎÀÚ.

ÀÌ°ÍÀº ¹öÆ°ÀÇ "clicked"À̶ó´Â À̺¥Æ®¿¡ ´ëÇØ È£ÃâµÉ callbackÇÔ¼ö´Ù. ÀÌ ¿¹Á¦ ¿¡¼­´Â À§Á¬°ú Á¤º¸°¡ ¸ðµÎ ¹«½ÃµÇÁö¸¸, ±×°ÍµéÀ» ´Ù·ç´Â °ÍÀº ±×´ÙÁö ¾î·ÆÁö ¾Ê´Ù. ÀÌ°Í ´ÙÀ½ÀÇ ¿¹Á¦´Â ¾î¶² ¹öÆ°ÀÌ ´­·¯Á³´Â°¡¸¦ ¾Ë·ÁÁÖ±â À§ÇØ Á¤º¸ ÀÎÀÚ¸¦ ÀÌ¿ëÇÏ´Â °ÍÀÌ´Ù.

static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello World\n");
}

ÀÌ callbackÀº ´Ù¼Ò Ưº°ÇÏ´Ù. À©µµ¸Å´ÏÀú°¡ ¾îÇÿ¡ ÀÌ À̺¥Æ®¸¦ º¸³»¸é "delete_event"°¡ ¹ß»ýÇÏ°Ô µÈ´Ù. ¿ì¸®´Â ¿©±â¼­ ÀÌ·± À̺¥Æ®µé¿¡ ´ëÇØ ¹«¾ùÀ» ÇØÁà¾ß ÇÒÁö ¼±ÅÃÇÑ´Ù. ¿ì¸®´Â ±×°ÍÀ» ¹«½ÃÇÒ ¼öµµ ÀÖ°í, ÀÌ¿¡ ´ëÇÑ ¹ÝÀÀÀ» Á¤¸®ÇÒ ¼öµµ ÀÖÀ¸¸ç, ¶Ç´Â °£´ÜÈ÷ ±× ¾îÇÃÀ» Á¾·áÇÒ ¼öµµ ÀÖ´Ù.

ÀÌ callbackÀÇ ¸®ÅÏ°ªÀ» ÅëÇØ GTK´Â ¾î¶² ÀÏÀ» ÇؾßÇÒ Áö ¾Ë°Ô µÈ´Ù. TRUE¸¦ ¸®ÅÏÇϸé GTK´Â ¿ì¸®°¡ "destroy"½Ã±×³ÎÀ» ¹ß»ýÇÏ´Â °ÍÀ» ¿øÇÏÁö ¾Ê´Â´Ù°í ÆÇ´Ü ÇÏ°Ô µÈ´Ù. ±×¸®°í FALSE¸¦ ¸®ÅÏÇÏ´Â °ÍÀ¸·Î ¿ì¸®´Â "destroy"½Ã±×³ÎÀÌ ¹ß»ýÇÔÀ» È®ÀνÃÅ°°í, "destroy"½Ã±×³Î Çڵ鷯¸¦ È£ÃâÇÏ°Ô µÈ´Ù.

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    g_print ("delete event occurred\n");

    return TRUE; 
}

¿©±â ´ÜÁö gtk_main_quit()À» È£ÃâÇÏ´Â °ÍÀ¸·Î Á¾·áÇØ ¹ö¸®´Â, ¶Ç´Ù¸¥ callback ÇÔ¼ö°¡ ÀÖ´Ù. ÀÌ°Í¿¡ ´ëÇؼ± ±ä¸» ¾Ê°Ú´Ù, º¸¸é ¾Ë ¼ö ÀÖÀ» °ÍÀ̹ǷÎ.

static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}

´ç½ÅÀÌ main() ¶õ °Í¿¡ ´ëÇØ ¾Ë°í ÀÖÀ¸¸®¶ó »ý°¢ÇÑ´Ù, ´Ù¸¥ ¾îÇðú ¸¶Âù°¡Áö·Î, ¸ðµç GTK ¾îÇà ¿ª½Ã main() À» Çϳª¾¿ °¡Áö°í ÀÖ´Ù.

int main( int   argc,
          char *argv[] )
{

ÀÌ ºÎºÐ¿¡¼­, GtkWidgetÇüÀÇ ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ¼±¾ðÇÑ´Ù. À̰͵éÀº À©µµ¿Í ¹öÆ°À» ¸¸µé±â À§ÇØ ¾Æ·¡¿¡¼­ ¾²ÀÌ°Ô µÈ´Ù.

    GtkWidget *window;
    GtkWidget *button;

¿©±â ´Ù½Ã gtk_init°¡ ³ª¿Â´Ù. Àü°ú ¸¶Âù°¡Áö·Î, ÀÌ°ÍÀº ÅøŶÀ» ÃʱâÈ­ÇÏ°í, ¸í·ÉÇà¿¡¼­ ÁÖ¾îÁø ÀÎÀÚµéÀ» ºÐ¼®ÇÑ´Ù. ÀÌ°ÍÀº ¸í·ÉÇà¿¡¼­ °¨ÁöµÈ ¾î¶² ÀÎÀÚ¶óµµ ÀÎÀÚÀÇ ¸®½ºÆ®¿¡¼­ »èÁ¦ÇÏ°í, argc¿Í argv¸¦ º¯Çü½ÃÄÑ ±× ÀÎÀÚµéÀÌ Á¸ÀçÇÏÁö ¾Ê´Â °Íó·³ º¸ÀÌ°Ô Çؼ­, ´ç½ÅÀÇ ¾îÇÃÀÌ ³²¾ÆÀÖ´Â ÀÎÀڵ鸸À» ºÐ¼®Çϵµ·Ï ÇØÁØ´Ù.

    gtk_init (&argc, &argv);

»õ À©µµ¸¦ Çϳª ¸¸µç´Ù. ÀÌ°ÍÀº ²Ï³ª °£´ÜÇÏ´Ù. GtkWidget *window °¡ °¡¸® Å°´Â ±¸Á¶Ã¼¿¡ ¸Þ¸ð¸®°¡ ÇÒ´çµÇ¾î ÀÌÁ¦ ½ÇÁ¦·Î Á¸ÀçÇÏ´Â ±¸Á¶Ã¼¸¦ °¡¸®Å°°Ô µÈ °ÍÀÌ´Ù. »õ·Î¿î À©µµ¸¦ ¼Â¾÷ÇÏÁö¸¸, ¾ÆÁ÷ gtk_widget_show(window)¸¦ È£ÃâÇÏÁö ¾Ê¾Ò±â ¶§¹®¿¡ ½ÇÁ¦·Î º¸¿©ÁöÁø ¾Ê°í ÀÖ´Ù. ÀÌ À©µµ´Â ÇÁ·Î±×·¥ÀÇ ³¡ ±Ùó¿¡¼­¾ß º¸ÀÌ°Ô µÉ °ÍÀÌ´Ù.

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

ÀÌ °æ¿ì¿£ À©µµ°¡ µÇ°ÚÁö¸¸, ¿©±â ÇÑ object¿¡ ½Ã±×³Î Çڵ鷯¸¦ ¿¬°á½ÃÅ°´Â ¿¹°¡ ÀÖ´Ù. ¿©±â¼­´Â "delete-event"¿Í "destory"½Ã±×³ÎÀÌ Å½ÁöµÈ´Ù. ù¹øÀç´Â ¿ì¸®°¡ À©µµ¸¦ ¾ø¾Ö±â À§Çؼ­ À©µµ¸Å´ÏÀúÀÇ ±â´ÉÀ» ÀÌ¿ëÇßÀ» ¶§ ¹ß»ýÇÑ´Ù. µÎ¹ø°´Â Æı«ÇÒ object·Î À©µµwidgetÀ» ¼±ÅÃÇÏ¿© gtk_widget_destroy()¸¦ È£ÃâÇßÀ» ¶§¿Í "delete_event" Çڵ鷯¿¡¼­ TRUE¸¦ ¸®ÅÏÇßÀ» ¶§¿¡ ¹ß»ýÇÑ´Ù.

G_CALLBACK´Â Äڵ带 ½±°Ô ºÐ¼®ÇÒ ¼ö ÀÖ°Ô ÇØÁÖ¸ç ÀÚ·áÇü ij½ºÆðú üũ¸¦ ÇØÁÖ´Â ¸ÅÅ©·ÎµéÀÌ´Ù.

    g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);
    g_signal_connect (window, "destroy",
                      G_CALLBACK (destroy), NULL);

À̹ø ÇÔ¼ö´Â container objectÀÇ ¼Ó¼ºÀ» ¼³Á¤ÇØ ÁÖ±â À§ÇØ ¾²¿´´Ù. ÀÌ°ÍÀº À©µµ¸¦ 10 Çȼ¿ÀÇ ³ÊºñÀÇ ºó ¿µ¿ªÀ¸·Î µÑ·¯½×ÀÌ°Ô ÇÑ´Ù. ¿ì¸®´Â ¾ÕÀ¸·Î Widget ¼Ó¼º¼³Á¤ À̶ó´Â section¿¡¼­ À¯»çÇÑ ±â´ÉÀ» °¡Áø ´Ù¸¥ ÇÔ¼öµéÀ» Á¢ÇÏ°Ô µÉ °ÍÀÌ´Ù.

±×¸®°í, GTK_CONTAINER´Â ¿ª½Ã ÀÚ·áÇü ij½ºÆÃÀ» ÇØÁÖ´Â ¸ÅÅ©·Î´Ù.

    gtk_container_border_width (GTK_CONTAINER (window), 10);

ÀÌ È£ÃâÀº »õ ¹öÆ°À» Çϳª ¸¸µç´Ù. ÀÌ°ÍÀº »õ·Î¿î GtkWidget ±¸Á¶Ã¼¸¦ À§ÇÑ ¸Þ¸ð¸® °ø°£À» ÇÒ´çÇÏ°í, ±×°ÍÀ» ÃʱâÈ­Çϸç, ±×¸®°í buttonÀ̶ó´Â Æ÷ÀÎÅÍ°¡ ±× ¿µ¿ªÀ» °¡¸®Å°µµ·Ï ÇÑ´Ù. ÀÌ ¹öÆ°Àº º¸¿©Áö°Ô µÇ¾úÀ» ¶§ "Hello World"¶ó´Â ¶óº§À» °¡Áö°Ô µÉ °ÍÀÌ´Ù.

    button = gtk_button_new_with_label ("Hello World");

¿ì¸®´Â ¿©±â¼­ ÀÌ ¹öÆ°ÀÌ ¹º°¡ À¯¿ëÇÑ ÀÏÀ» Çϵµ·Ï ÇÑ´Ù. ¿ì¸®´Â ±×°Í¿¡ ½Ã±×³Î Çڵ鷯¸¦ ´Þ¾ÆÁÖ°í, "clicked"½Ã±×³ÎÀÌ ¹ß»ýÇßÀ» ¶§ ¿ì¸®ÀÇ hello() ÇÔ¼ö°¡ È£ÃâµÇµµ·Ï ÇÑ´Ù. ÀüÇØÁú Á¤º¸´Â ¾ø°í, µû¶ó¼­ ¿ì¸®´Â hello()¶ó´Â callbackÇÔ¼ö¿¡ ´Ü¼øÈ÷ NULLÀ» ÀüÇØÁØ´Ù. ºÐ¸íÈ÷, ¿ì¸®°¡ ¸¶¿ì½º Æ÷ÀÎÅÍ·Î ±× ¹öÆ°À» Ŭ¸¯ÇßÀ» ¶§ "clicked"½Ã±×³ÎÀÌ ¹ß»ýÇÏ°Ô µÈ´Ù.

    g_signal_connect (button, "clicked",
                      G_CALLBACK (hello), NULL);

¿ì¸®´Â ¶ÇÇÑ ÇÁ·Î±×·¥À» ³¡³»±â À§Çؼ­µµ ÀÌ ¹öÆ°À» ÀÌ¿ëÇÑ´Ù. ÀÌ°ÍÀº À©µµ ¸Å´ÏÀú¸¦ ÅëÇؼ­, ȤÀº ¿ì¸® ÇÁ·Î±×·¥À» ÅëÇؼ­ "destroy"½Ã±×³ÎÀÌ ¾î¶»°Ô ÀüÇØ ¿À´ÂÁö¸¦ º¸¿©ÁÙ °ÍÀÌ´Ù. ¾Õ¿¡¼­Ã³·³ ¹öÆ°ÀÌ ´­·ÁÁö¸é ¸ÕÀú hello() callback ÇÔ¼ö°¡ ºÒ·ÁÁö°í, µÚÀÌ¾î ±×µéÀÌ ¼Â¾÷µÈ ¼ø¼­´ë·Î ÀÌ°ÍÀÌ È£ÃâµÈ´Ù. ÇÊ¿äÇÏ´Ù¸é ¾ó¸¶µçÁö callbackÇÔ¼ö¸¦ ¾µ ¼ö ÀÖÀ¸¸ç, ±×°Íµé ¸ðµÎ´Â ¿ì¸®°¡ ¿¬°á½ÃÄѳõÀº ¼ø¼­´ë·Î ½ÇÇàµÈ´Ù. gtk_widget_destroy()ÇÔ¼ö°¡ ¿ÀÁ÷ GtkWidget *widget¸¸À» ÀÎÀÚ·Î Çã¿ëÇϱ⠶§¹®¿¡, ¿ì¸®´Â ¿©±â¼­ g_signal_connect()¸¦ ¹Ù·Î ¾²Áö ¾Ê°í g_signal_connect_swapped()¸¦ ¾´´Ù.

    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              window);

ÀÌ°ÍÀº ÆÐÅ·È£ÃâÀÌ¸ç µÚ¿¡¼­ ´õ ±í°Ô ´Ù·ê °ÍÀÌ´Ù. ÇÏÁö¸¸ »ó´çÈ÷ ½±°Ô ÀÌÇØÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ´ÜÁö GTK¿¡°Ô, ¹öÆ°Àº ±× ¹öÆ°ÀÌ º¸¿©Áö°Ô µÉ À©µµ¿¡ À§Ä¡ÇØ¾ß µÈ´Ù´Â °É ¾Ë·ÁÁØ´Ù.

    gtk_container_add (GTK_CONTAINER (window), button);

ÀÌÁ¦ ¿ì¸®´Â ÇÊ¿äÇÑ ¸ðµç ¼Â¾÷À» ¸¶ÃÆ´Ù. ÀÚ¸®¸¦ ÀâÀº ¸ðµç ½Ã±×³Î Çڵ鷯¿Í ÇÔ²², ¸ðµç ¹öÆ°ÀÌ °¢°¢ ÀÖ¾î¾ß ÇÒ À©µµ¿¡ ÀÚ¸®¸¦ Àâ¾Ò°í, ¿ì¸®´Â GTK°¡ ½ºÅ©¸° À§¿¡ widgetµéÀ» "º¸¿©ÁÖ±â"¸¦ ¿ä±¸ÇÑ´Ù. À©µµwidgetÀÌ °¡Àå ³ªÁß¿¡ º¸¿©Áø´Ù. µû¶ó¼­ À©µµ°¡ ¸ÕÀú º¸¿©Áö°í ±× ³»ºÎ¿¡ ¹öÆ° ¸ð¾çÀÌ µÚÀÌ¾î ±×·ÁÁö´Â °Ô ¾Æ´Ï¶ó, ¿ÏÀüÈ÷ ¸ð¾çÀ» °®Ãá À©µµ°¡ ÇѲ¨¹ø¿¡ º¸¿©Áö°Ô µÈ´Ù.

    gtk_widget_show (button);

    gtk_widget_show (window);

±×¸®°í ¹°·Ð, ¿ì¸®´Â gtk_main()À» ºÒ·¯¼­ X ¼­¹ö·ÎºÎÅÍ À̺¥Æ®°¡ ¹ß»ýÇϱ⸦ ±â´Ù¸®°Ô ÇÏ°í, ÀÌ À̺¥Æ®°¡ ŽÁöµÇ¾úÀ» ¶§ ½Ã±×³ÎÀ» ³»µµ·Ï widgetÀ» È£ÃâÇÒ °ÍÀÌ´Ù.

    gtk_main ();
±×¸®°í ¸¶Áö¸· ¸®ÅÏ. gtk_quit()°¡ È£ÃâµÈ ÀÌÈÄ Á¦¾î´Â ¿©±â¼­ ³¡³ª°Ô µÈ´Ù.
    return 0;

ÀÌÁ¦, ¿ì¸®°¡ GTKÀÇ ¹öÆ° À§¿¡¼­ ¸¶¿ì½º ¹öÆ°À» Ŭ¸¯Çϸé widgetÀº "clicked" ½Ã±×³ÎÀ» ¹ß»ý½ÃŲ´Ù. ÀÌ·± Á¤º¸¸¦ ÀÌ¿ëÇϱâ À§ÇØ ¿ì¸® ÇÁ·Î±×·¥Àº ±× ½Ã±×³ÎÀ» Àâ¾Æ³¾ ½Ã±×³Î Çڵ鷯¸¦ ¼Â¾÷ÇÏ°í, ±×°ÍÀº ¿ì¸®ÀÇ ¼±Åÿ¡ ÀÇÇÑ ÇÔ¼öµéÀ» À绡¸® ºÎ¸£°Ô µÈ´Ù. ¿ì¸®ÀÇ ¿¹Á¦¿¡¼­´Â ¿ì¸®°¡ ¸¸µç ¹öÆ°ÀÌ ´­·ÁÁö¸é hello()ÇÔ¼ö°¡ NULL ÀÎÀڷΠȣÃâµÇ°í, µÚÀ̾î ÀÌ ½Ã±×³ÎÀ» À§ÇÑ ´ÙÀ½ Çڵ鷯°¡ È£ÃâµÈ´Ù. ÀÌ°ÍÀº À©µµ widgetÀ» ÀÎÀÚ·Î ÇÏ¿© gtk_widget_destroy()ÇÔ¼ö¸¦ È£ÃâÇؼ­ À©µµ widgetÀ» ¾ø¾Ø´Ù. ÀÌ°ÍÀº À©µµ°¡ "destroy"½Ã±×³ÎÀ» ¹ß»ýÇÏ°Ô Çؼ­ ŽÁöµÇ°í, "destroy"¿¡ ÇØ´çÇÏ´Â callbackÇÔ¼ö¸¦ È£ÃâÇؼ­ GTK°¡ Á¾·áµÇ°Ô ÇÏ´Â °ÍÀÌ´Ù.

À̺¥Æ®µéÀÇ ¶Ç´Ù¸¥ »ç¿ë¹æ¹ýÀº À©µµ¸¦ Á¾·áÇϴµ¥ À©µµ ¸Å´ÏÁ®¸¦ ¾²´Â °ÍÀÌ´Ù. ÀÌ·¸°Ô Çϸé "delete_event" ½Ã±×³ÎÀÌ ¹ß»ýÇÏ°í ÀÌ´Â ¿ì¸®ÀÇ "delete_event" Çڵ鷯¸¦ È£ÃâÇÑ´Ù. ¸¸ÀÏ ¿ì¸®°¡ ¿©±â¼­ TRUE¸¦ ¸®ÅÏÇϸé À©µµ´Â ±×´ë·Î È­¸é¿¡ ³²°í ¾Æ¹«Àϵµ »ý±âÁö ¾Ê´Â´Ù. FALSE¸¦ ¸®ÅÏÇϸé GTK´Â "destroy" ½Ã±×³ÎÀ» ¹ß»ýÇÏ°í "destroy" callbackÀÌ È£ÃâµÇ¾î GTK°¡ Á¾·áµÈ´Ù.

ºñ·Ï ¾²ÀÓ»õ´Â °ÅÀÇ °°Àº °ÍÀÌÁö¸¸, À¯´Ð½º ½Ã½ºÅÛÀÇ ½Ã±×³ÎÀº ¿©±â¼­ ¸»ÇÏ´Â ÀÌ·± ½Ã±×³Î°ú ´Ù¸¥ °ÍÀÌ¸ç »ç¿ëµÇÁöµµ ¾Ê´Â´Ù´Â Á¡À» ±â¾ïÇϱ⠹ٶõ´Ù.

4. ¾ÕÀ¸·Î ³ª¾Æ°¡¸ç

4.1 ÀÚ·áÇü

¾Õ¼­ÀÇ ¿¹Á¦¿¡¼­ ÁÖ¸ñÇß°ÚÁö¸¸ ¼³¸íÀÌ ÇÊ¿äÇÑ °ÍÀÌ Á» ÀÖ´Ù. gint, gchar µîÀº °¢°¢ int¿Í char¿¡ ´ëÇÑ typedefµéÀÌ´Ù. ÀÌ°ÍÀº °è»êÀ» ÇÒ ¶§ °£´ÜÇÑ ÀÚ·áÇüµéÀÇ Å©±â¿¡ ´ëÇÑ ÁöÀúºÐÇÑ ÀÇÁ¸¼ºÀ» ÇÇÇϱâ À§ÇÑ °ÍÀÌ´Ù. 64ºñÆ®ÀÇ ¾ËÆĵç 32ºñÆ®ÀÇ ÀÎÅÚÀ̵ç "gint32"´Â Ç÷§Æû¿¡ °ü°è¾øÀÌ 32ºñÆ® Á¤¼ö·Î typedefµÇ¾î ÀÖ´Â °ÍÀÌ ÁÁÀº ¿¹°¡ µÉ °ÍÀÌ´Ù. ÀÌ typedefÀº »ó´çÈ÷ Á÷°üÀûÀÌ´Ù. ±×µéÀº ¸ðµÎ glib/ glib.h¿¡¼­ Á¤ÀǵǾî ÀÖ´Ù(ÀÌ°ÍÀº gtk.h¿¡¼­ Æ÷ÇÔ½ÃÅ°°Ô µÈ´Ù.). ´ç½ÅÀº ¶ÇÇÑ ÇÔ¼ö°¡ GtkObject¸¦ ºÎ¸¦ ¶§ GtkWidgetÀ» ÀÌ¿ëÇÏ´Â °Í¿¡µµ ÁÖ¸ñÇÒ °ÍÀÌ´Ù. GTK´Â °´Ã¼ÁöÇâÀûÀ¸·Î ¼³°èµÈ °ÍÀÌ°í, widgetÀº ÇϳªÀÇ objectÀÌ´Ù.

4.2 ½Ã±×³Î Çڵ鷯¿¡ ´ëÇØ Á» ´õ ¾Ë¾Æº¸±â

g_signal_connect()ÀÇ ¼±¾ðÀ» ¶Ç ´Ù¸£°Ô »ìÆ캸ÀÚ.

gulong g_signal_connect( gpointer object,
                         const gchar *name,
                         GCallback func,
                         gpointer func_data );

gulongÇüÀÇ ¸®ÅÏ°ª? ÀÌ°ÍÀº callbackÇÔ¼ö¸¦ È®ÀÎÇϱâ À§ÇÑ ²¿¸®Ç¥´Ù. ¾Õ¼­ ¾ê±âÇßµíÀÌ ¿ì¸®´Â ½Ã±×³Î°ú object¿¡ ´ëÇØ ÇÊ¿äÇÑ ¸¸Å­ÀÇ ¸¹Àº callbackÀ» °¡Áú ¼ö ÀÖ°í, ±×°ÍµéÀº ºÙ¿©Á® ÀÖ´Â ¼ø¼­´ë·Î °¢°¢ ½ÇÇàµÉ °ÍÀÌ´Ù. ÀÌ ²¿¸®Ç¥´Â ¿ì¸®°¡ ¸®½ºÆ®¿¡¼­ ÀÌ·± callbackÀ» Á¦°ÅÇϵµ·Ï ÇØÁØ´Ù.

void g_signal_handler_disconnect( gpointer object,
                                  gulong   id );

±×·¡¼­, Çڵ鷯·ÎºÎÅÍ Á¦°ÅÇÏ°íÀÚ ÇÏ´Â widget°ú signal_connectÇÔ¼ö·ÎºÎÅÍ ¸®ÅÏµÈ±× widgetÀÇ ²¿¸®Ç¥ ȤÀº id¸¦ ³Ñ°ÜÁÜÀ¸·Î½á ½Ã±×³Î Çڵ鷯¸¦ ²÷¾îÁÙ ¼ö ÀÖ´Ù.

g_signal_handler_block()°ú g_signal_handler_unblock() °è¿­ÀÇ ÇÔ¼ö·Î ÇѽÃÀûÀ¸·Î ½Ã±×³ÎÀ» ºñÈ°¼ºÈ­ ÇÒ ¼ö ÀÖ´Ù.

void g_signal_handler_block( gpointer object,
                             gulong   id );

void g_signal_handlers_block_by_func( gpointer  object,
                                      GCallback func,
                                      gpointer  data );

void g_signal_handler_unblock( gpointer object,
                               gulong   id );

void g_signal_handlers_unblock_by_func( gpointer  object,
                                        GCallback func,
                                        gpointer  data );

4.3 Çâ»óµÈ Hello World ÇÁ·Î±×·¥

CallbackÇÔ¼ö¿¡ ´ëÇÑ ´õ ³ªÀº ¿¹Á¦°¡ µÉ ¾à°£ °³¼±µÈ hello world¸¦ º¸ÀÚ. ÀÌ°ÍÀº ¶ÇÇÑ ¿ì¸®ÀÇ ´ÙÀ½ Àý¿¡¼­ÀÇ ÁÖÁ¦ÀÎ ÆÐÅ· widgetÀ» ¼Ò°³ÇÒ °ÍÀÌ´Ù.

/* helloworld2.c */

#include <gtk/gtk.h>

/* ¿ì¸®ÀÇ ¾à°£ °³¼±µÈ callback.  ÀÌ ÇÔ¼ö·Î ÀüÇØÁø µ¥ÀÌÅʹ ǥÁØÃâ·ÂÀ¸·Î
 * º¸¿©Áø´Ù. */
static void callback( GtkWidget *widget,
                      gpointer   data )
{
    g_print ("Hello again - %s was pressed\n", (gchar *) data);
}

/* ´Ù¸¥ callback */
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    gtk_main_quit ();
    return FALSE;
}

int main (int argc, char *argv[])
{
    /* GtkWidgetÀº widgetµéÀ» À§ÇÑ ÀúÀåÀå¼Ò ŸÀÔÀÌ´Ù. */ 
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box1;

    /* ÀÌ°ÍÀº ¸ðµç GTK ¾îÇÿ¡¼­ ¾´´Ù.  ¸í·ÉÇà¿¡¼­ ÁÖ¾îÁø ÀÎÀÚµéÀº ÀÌ°ÍÀ»
     * Åë°úÇؼ­ ¾îÇÿ¡ Àü´ÞµÈ´Ù. */
    gtk_init (&argc, &argv);

    /* »õ·Î¿î À©µµ¸¦ ¸¸µç´Ù. */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* »õ·Î Á¢ÇÏ´Â ÇÔ¼ö·Î, À©µµ¿¡ "Hello Buttons!"¶ó´Â ŸÀÌƲÀ» ÁØ´Ù. */
    gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");

    /* ¿©±â¼­ ¿ì¸®´Â GTK¸¦ Áï½Ã ³¡³ª°Ô ÇÏ´Â delete_event¸¦ À§ÇÑ Çڵ鷯¸¦
     * ¼¼ÆÃÇÑ´Ù. */
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);

    /* À©µµÀÇ border width¸¦ ¼¼ÆÃÇÑ´Ù. */
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* widgetµéÀÌ ÆÐÅ·µÉ ¹Ú½º¸¦ ¸¸µç´Ù.  ÀÌ°ÍÀº ÆÐÅ·¿¡ ´ëÇÑ ºÎºÐ¿¡¼­
     * ÀÚ¼¼È÷ ¼³¸íµÉ °ÍÀÌ´Ù.  ¹Ú½º´Â ½ÇÁ¦·Î º¸ÀÌ´Â °Ç ¾Æ´Ï¸ç ´ÜÁö
     * widgetµéÀ» Á¤·ÄÇØ ³õÀ» µµ±¸·Î¼­ ¾²ÀδÙ. */
    box1 = gtk_hbox_new(FALSE, 0);

    /* ¹Ú½º¸¦ À©µµ ¾È¿¡ ³õ´Â´Ù. */
    gtk_container_add (GTK_CONTAINER (window), box1);

    /* "Button 1"À̶õ ¶óº§À» °¡Áø »õ·Î¿î ¹öÆ°À» ¸¸µç´Ù. */
    button = gtk_button_new_with_label ("Button 1");

    /* ÀÌÁ¦ ¹öÆ°ÀÌ Å¬¸¯µÇ¸é ¿ì¸®´Â ÀÌ ¹öÆ°¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ÀÎÀÚ·Î °¡Áö´Â
     * "callback" ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (callback), (gpointer) "button 1");

    /* gtk_container_add ´ë½Å¿¡, ¿ì¸®´Â ÀÌ¹Ì À©µµ¿¡ ÆÐÅ·µÇ¾î ÀÖ´Â º¸ÀÌÁö
     * ¾Ê´Â ¹Ú½º¿¡ ¹öÆ°À» ÆÐÅ·ÇÑ´Ù. */
    gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);

    /* ÀÌ ¼ø¼­¸¦ ²À ±â¾ïÇ϶ó.  ¿©±â¼­ ¹öÆ°¿¡ ´ëÇÑ ¼¼ÆÃÀÌ ¿ÏÀüÈ÷ ³¡³µÀ½À»
     * GTK¿¡°Ô ¾Ë¸®°í, µû¶ó¼­ ±×°ÍÀº ÀÌÁ¦ º¸¿©Áú ¼ö ÀÖ´Ù. */
    gtk_widget_show(button);

    /* µÎ¹ø° ¹öÆ°À» ¸¸µé±â À§ÇØ °°Àº ÀýÂ÷¸¦ °ÅÄ£´Ù. */
    button = gtk_button_new_with_label ("Button 2");

    /* °°Àº callbackÀ» È£ÃâÇÑ´Ù.  ¹°·Ð ÀÎÀÚ´Â "button 2"¿¡ ´ëÇÑ
     * Æ÷ÀÎÅÍ´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (callback), (gpointer) "button 2");

    gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);

    /* ¿ì¸®°¡ ¹öÆ°À» ¸ÕÀú º¸¿©Áà¾ß ÇÏ´Â ±× ¼ø¼­´Â ½ÇÁ¦·Î Áß¿äÇÑ °ÍÀº
     * ¾Æ´Ï´Ù.  ÇÏÁö¸¸ ³ª´Â ¸ðµç °ÍµéÀÌ ÇѲ¨¹ø¿¡ Æ¢¾î ³ª¿À¸ç º¸¿©Áú ¼ö
     * ÀÖµµ·Ï À©µµ¸¦ °¡Àå ³ªÁß¿¡ º¸¿©ÁÙ °ÍÀ» ±ÇÀåÇÑ´Ù. */
    gtk_widget_show(button);
    gtk_widget_show(box1);
    gtk_widget_show (window);

    /* ¿©±â¼­ ¾ÕÀ¸·ÎÀÇ Àç¹ÌÀÖ´Â °ÍµéÀ» ±â´Ù¸®°Ô µÈ´Ù! */
    gtk_main ();

    return 0;
}

ÀÌ ÇÁ·Î±×·¥À» ¿ì¸®ÀÇ Ã¹¹ø° ¿¹Á¦¿Í °°Àº ¸µÅ© ÀÎÀÚ¸¦ ÁÖ°í ÄÄÆÄÀÏÇÏÀÚ. ¿ª½Ã ¿ì¸®´Â ÀÌ ÇÁ·Î±×·¥À» Á¾·áÇϱâ À§Çؼ­ À©µµ¸Å´ÏÀú¸¦ ÀÌ¿ëÇϰųª ¸í·ÉÇà¿¡¼­ Á×ÀÌ´Â °Í ¸»°í´Â ´Ù¸¥ ¹æ¹ýÀÌ ¾ø´Ù´Â °É ¾Ë °ÍÀÌ´Ù. ¿¬½À»ï¾Æ ¼¼¹ø°·Î "Quit" ¹öÆ°À» ¸¸µé¾î Ãß°¡ÇØ º¸´Â °Íµµ ÁÁÀ» °ÍÀÌ´Ù. ¶ÇÇÑ ´ÙÀ½ ÀýÀ» Àо¸ç gtk_box_pack_start()¿¡ ¿É¼ÇÀ» Á־ ¼öµµ ÀÖ´Ù. À©µµÀÇ Å©±â¸¦ ¹Ù²Ù·Á°í ½Ãµµµµ Çغ¸°í, µ¿ÀÛÀ» °üÂûÇØ º¸¶ó.

5. ÆÐÅ· Widget

¿ì¸®°¡ ¾î¶² ¾îÇÃÀ» °³¹ßÇϸ鼭, ÇϳªÀÇ À©µµ¿¡ Çϳª ÀÌ»óÀÇ ¹öÆ°À» ³õÀ¸·Á ÇÒ °ÍÀÌ´Ù. ¿ì¸®ÀÇ Ã¹¹ø° hello world ¿¹Á¦´Â ÇϳªÀÇ widget¸¸ ½è°í µû¶ó¼­ ¿ì¸®´Â ±×°ÍÀ» À©µµ ³»ºÎ¿¡ "pack"Çϱâ À§ÇØ gtk_container_add ÇÔ¼ö¸¦ ½è´Ù. ±×·¯³ª ¿ì¸®°¡ ÇϳªÀÇ À©µµ¿¡ ´õ¸¹Àº widgetÀ» ³õÀ¸·Á ÇÒ ¶§, ¾î¶»°Ô ±×µéÀÌ ³õÀÏ À§Ä¡¸¦ Á¦¾îÇØ¾ß ÇÒ±î? ¿©±â¼­ ¹Ù·Î "packing"À̶õ °ÍÀÌ µîÀåÇÑ´Ù.

5.1 ¹Ú½º packingÀÇ ¿ø¸®

´ëºÎºÐÀÇ ÆÐÅ·Àº ¾Õ¼­ÀÇ ¿¹Á¦¿¡¼­Ã³·³ ¹Ú½º¸¦ ¸¸µå´Â °ÍÀ¸·Î ÀÌ·ç¾îÁø´Ù. À̵éÀº ¿ì¸®ÀÇ widgetÀ» ¼öÆò ȤÀº ¼öÁ÷ ¹æÇâÀ¸·Î ÆÐÅ·ÇØ ³ÖÀ» ¼ö ÀÖ´Â, º¸ÀÌÁö ¾Ê´Â widget ÄÁÅ×À̳ʵéÀÌ´Ù. ¼öÆò ¹Ú½º·ÎÀÇ ÆÐÅ·widgetÀÎ °æ¿ì, object´Â È£Ãâ ÇÏ´Â ¹æ½Ä¿¡ µû¶ó ¼öÆòÀ¸·Î ¿ÞÂÊ¿¡¼­ ¿À¸¥ÂÊÀ¸·Î ȤÀº ¿À¸¥ÂÊ¿¡¼­ ¿ÞÂÊÀ¸·Î »ðÀÔ µÈ´Ù. ¼öÁ÷ ¹Ú½º¿¡¼­´Â ¹Ý´ë·Î ¼öÁ÷À¸·Î »ðÀԵȴÙ. ¿ì¸®´Â ¿øÇÏ´Â È¿°ú¸¦ ³»±â À§ÇØ ´Ù¸¥ ¹Ú½ºµéÀÇ ¾ÈÆÆ¿¡¼­ ¾î¶»°Ô¶óµµ Á¶ÇÕÇؼ­ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

»õ·Î¿î ¼öÆò¹Ú½º¸¦ ¸¸µé±â À§ÇØ ¿ì¸®´Â gtk_hbox_new()¸¦, ±×¸®°í ¼öÁ÷¹Ú½º¸¦ À§Çؼ­´Â gtk_vbox_new()¸¦ ÀÌ¿ëÇÑ´Ù. gtk_box_pack_start()¿Í gtk_box_pack_end()´Â ÀÌ·± ÄÁÅ×À̳ÊÀÇ ³»ºÎ¿¡ objectµéÀ» À§Ä¡½ÃÅ°±â À§ÇØ »ç¿ëÇÑ´Ù. gtk_box_pack_start()ÇÔ¼ö´Â ¼öÁ÷¹Ú½º¿¡¼­´Â À§¿¡¼­ ¾Æ·¡ÂÊÀ¸·Î, ±×¸®°í ¼öÆò¹Ú½º¿¡¼­´Â ¿ÞÂÊ¿¡¼­ ¿À¸¥ÂÊÀ¸·Î ÆÐÅ·ÇÒ °ÍÀÌ´Ù. ±×¸®°í gtk_box_pack_end()´Â ÀÌ¿Í ¹Ý´ë ¹æÇâÀ¸·Î ÆÐÅ·ÇÑ´Ù. ÀÌ ÇÔ¼öµéÀ» ÀÌ¿ëÇÔÀ¸·Î½á ¿ì¸®´Â ¿À¸¥ÂÊ ¶Ç´Â ¿ÞÂÊÀ¸·Î widgetÀ» Á¤·ÄÇÒ ¼ö ÀÖ°í, ¿øÇÏ´Â È¿°ú¸¦ ³¾ ¼ö ÀÖ´Ù. ¿ì¸®´Â ´ëºÎºÐÀÇ ¿¹Á¦¿¡¼­ gtk_box_pack_start()¸¦ ÀÌ¿ëÇÒ °ÍÀÌ´Ù. Object´Â ¶Ç´Ù¸¥ ÄÁÅ×À̳ʰųª widgetÀÌ µÉ ¼ö ÀÖ´Ù. ±×¸®°í »ç½Ç, ¸¹Àº widgetµéÀº ½ÇÁ¦·Î ¹öÆ°À» Æ÷ÇÔÇÏ°í ÀÖ´Â widget ÀÌÁö¸¸, ¿ì¸®´Â º¸Åë ¹öÆ° ¾ÈÀÇ ¶óº§¸¸À» ÀÌ¿ëÇÒ °ÍÀÌ´Ù.

ÀÌ·± ÇÔ¼öÈ£Ãâ·Î½á, GTK´Â ¿ì¸®°¡ widgetÀ» ³õÀ» À§Ä¡¸¦ ¾Ë°ÔµÇ°í µû¶ó¼­ ÀÚµ¿ÀûÀ¸·Î Å©±â¸¦ Á¶ÀýÇÑ´ÙµçÁö ¶Ç´Ù¸¥ ¸Å·ÂÀûÀÎ ÀϵéÀ» ÇÒ ¼ö ÀÖ°Ô µÈ´Ù. ¶ÇÇÑ ¿ì¸®ÀÇ widgetÀÌ ¾î¶»°Ô ÆÐÅ·µÇ¾î¾ß ÇÏ´À³Ä¿¡ µû¸¥ ¼ö¸¹Àº ¿É¼Çµéµµ ÀÖ´Ù. ¿ì¸®°¡ »ó»óÇϵíÀÌ, ÀÌ·± ¹æ½ÄÀº widgetÀ» ³õ°í ¸¸µå´Â µ¥ À־ »ó´çÇÑ À¯¿¬¼º À» Á¦°øÇØ ÁØ´Ù.

5.2 ¹Ú½º¿¡ ´ëÇØ ÀÚ¼¼È÷ ¾Ë¾Æº¸ÀÚ

ÀÌ·± À¯¿¬¼º ¶§¹®¿¡, GTK¿¡¼­ ¹Ú½º¸¦ ÆÐÅ·ÇÏ´Â °ÍÀº óÀ½¿£ È¥¶õ½º·¯¿ïÁö ¸ð¸¥´Ù. ¸¹Àº ¿É¼ÇµéÀÌ ÀÖÀ¸¸ç, ±×µéÀÌ ¾î¶»°Ô ¼­·Î ²ç¾î ¸ÂÃçÁö´ÂÁö Áï½Ã °£ÆÄ ÇÒ ¼ö´Â ¾øÀ» °ÍÀÌ´Ù. ±×·¯³ª °á±¹, ¿ì¸®´Â ´Ù¼¸ °¡ÁöÀÇ ±âº»ÀûÀÎ ½ºÅ¸ÀÏÀ» °¡Áö°Ô µÈ´Ù.

Box Packing Example Image

°¢°¢ÀÇ ÁÙÀº ¸î °³ÀÇ ¹öÆ°À» °¡Áö°í ÀÖ´Â ÇϳªÀÇ ¼öÆò¹Ú½º(hbox)¸¦ Æ÷ÇÔÇÑ´Ù. ÇÔ¼öÈ£Ãâ gtk_box_packÀº ÀÌ ¼öÆò¹Ú½º¿¡ °¢°¢ÀÇ ¹öÆ°À» ÆÐÅ·ÇÏ´Â °ÍÀ» ´ÜÃàÇÑ °ÍÀÌ´Ù. °¢°¢ÀÇ ¹öÆ°Àº ÀÌ ¼öÆò¹Ú½º¿¡ °°Àº ¹æ¹ýÀ¸·Î ÆÐÅ·µÈ´Ù(Áï, gtk_box_pack_startÇÔ¼ö¿¡ °°Àº ÀÎÀÚ¸¦ Áشٴ ¸»).

ÀÌ°ÍÀº gtk_box_pack_startÇÔ¼öÀÇ ¼±¾ðÀÌ´Ù.

void gtk_box_pack_start( GtkBox    *box,
                         GtkWidget *child,
                         gboolean   expand,
                         gboolean   fill,
                         guint      padding );

ù¹ø° ÀÎÀÚ´Â object¸¦ ÆÐÅ·ÇÒ ¹Ú½º°í µÎ¹ø°´Â ±× object´Ù. Object´Â ¿©±â¼­ ¸ðµÎ ¹öÆ°ÀÌ µÉ °ÍÀÌ°í, µû¶ó¼­ ¿ì¸®´Â ¹Ú½º¾È¿¡ ¹öÆ°µéÀ» ÆÐÅ·ÇÏ°Ô µÈ´Ù.

gtk_box_pack_start() ¶Ç´Â gtk_box_pack_end()¿¡¼­ÀÇ expand¶ó´Â ÀÎÀÚ°¡ TRUE ÀÏ ¶§, widgetÀº ¿©¹é°ø°£À» °¡µæ ä¿ì¸ç ¹Ú½º¿¡ µé¾î°¡°Ô µÉ °ÍÀÌ´Ù. ±×¸®°í ±×°ÍÀÌ FALSE¶ó¸é widgetÀº ÀûÀýÈ÷ ¿©¹éÀ» µÎ°Ô µÈ´Ù. ÀÌ expand¸¦ FALSE·Î µÎ¸é ¿ì¸®´Â widgetÀÇ Á¿ì Á¤·ÄÀ» °áÁ¤ÇÒ ¼ö ÀÖ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ±×µéÀº ¹Ú½º¿¡ °¡µæÂ÷¼­ gtk_box_pack_start ¶Ç´Â gtk_box_pack_end ¾î´À ÂÊÀ» ÀÌ¿ëÇϵçÁö °°Àº È¿°ú¸¦ °¡Áö°Ô µÈ´Ù.

ÀÎÀÚ fillÀº TRUEÀÏ ¶§ object ÀÚ½ÅÀÇ ¿©¹é°ø°£À» Á¦¾îÇÑ´Ù. ±×¸®°í FALSE¶ó¸é object ÀÚ½ÅÀÇ ¿©¹é°ø°£À» µÎÁö ¾Ê´Â´Ù. ÀÌ°ÍÀº expand ÀÎÀÚ°¡ TRUEÀÏ ¶§¸¸ È¿°ú °¡ ÀÖ´Ù.

»õ·Î¿î ¹Ú½º¸¦ ¸¸µé ¶§´Â ÀÌ·± ÇÔ¼ö°¡ ÀÖ´Ù(¼öÆò¹Ú½º).

GtkWidget *gtk_hbox_new ( gboolean homogeneous,
                          gint     spacing );

¿©±â¼­ÀÇ ÀÎÀÚ homogeneous´Â ¹Ú½º ¾ÈÀÇ °¢ objectµéÀÌ °°Àº Å©±â¸¦ °¡Áöµµ·Ï Á¦¾îÇÑ´Ù(Áï ¼öÆò¹Ú½ºÀÏ °æ¿ì¿£ °°Àº ³Êºñ, ¼öÁ÷¹Ú½ºÀÏ °æ¿ì¿£ °°Àº ³ôÀÌ). ÀÌ°ÍÀÌ ¼¼ÆõǸé, gtk_box_packÇÔ¼öÀÇ expand ÀÎÀÚ´Â ¾ðÁ¦³ª TRUE°¡ µÈ´Ù.

¿©±â¼­ spacing(¹Ú½º°¡ ¸¸µé¾îÁö¸ç ¼¼ÆõÊ)¿Í padding(¿ä¼ÒµéÀÌ ÆÐÅ·µÇ¸ç ¼¼ÆõÊ)ÀÇ Â÷ÀÌÁ¡Àº ¹«¾ùÀϱî? SpacingÀº objectµé »çÀÌ¿¡ »ý°Ü³ª´Â °ÍÀ̸ç paddingÀº ÇÑ objectÀÇ °¢ ¹æÇâ¿¡¼­ »ý°Ü³ª´Â °ÍÀÌ´Ù. ÀÌ°ÍÀÌ ±× Á¡À» ¸íÈ®È÷ ÇØÁÙ °ÍÀÌ´Ù.

Box Packing Example Image

¿©±â ÀÌ À̹ÌÁö¸¦ ¸¸µé¾î ÁÖ´Â Äڵ尡 ÀÖ´Ù. ³ª´Â ¿©·¯ ¹ø °­Á¶ÇßÀ¸¹Ç·Î ÀÌ°Í¿¡¼­ º° ¹®Á¦´Â ¾øÀ¸¸®¶ó ¹Ï´Â´Ù. ½º½º·Î ÄÄÆÄÀÏÇؼ­ °¡Áö°í ³î¾Æ º¸µµ·Ï ÇÑ´Ù.

5.3 ÆÐÅ·¿¡ ´ëÇÑ ¿¹Á¦ ÇÁ·Î±×·¥

/* packbox.c */

#include <stdio.h>
#include <stdlib.h>
#include "gtk/gtk.h"

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    gtk_main_quit ();
    return FALSE;
}

/* Button_labelµé·Î ÀÌ·ç¾îÁø hbox¸¦ ¸¸µç´Ù.  ¿ì¸®°¡ °ü½ÉÀ» °¡Áø º¯¼öµéÀ»
 * À§ÇÑ ÀÎÀÚµéÀÌ ÀÌ ÇÔ¼ö·Î ³Ñ°ÜÁø´Ù.
 * ¿ì¸®´Â ¹Ú½º¸¦ º¸ÀÌÁö ¾Ê°í, ±× ¾È¿¡ ÀÖ´Â ¸ðµç °ÍÀ» º¸ÀÏ °ÍÀÌ´Ù. */
static GtkWidget *make_box( gboolean homogeneous,
                            gint     spacing,
                            gboolean expand,
                            gboolean fill,
                            guint    padding )
{
  GtkWidget *box;
  GtkWidget *button;
  char padstr[80];

  /* Àû´çÇÑ homogenous¿Í spacingÀ» °¡Áø hbox¸¦ ¸¸µç´Ù. */
  box = gtk_hbox_new (homogeneous, spacing);

  /* ÀûÀýÈ÷ ¼¼ÆÃµÈ ¹öÆ°µéÀ» ¸¸µç´Ù. */
  button = gtk_button_new_with_label ("gtk_box_pack");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  button = gtk_button_new_with_label ("(box,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  button = gtk_button_new_with_label ("button,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  /* expandÀÇ °ª¿¡ µû¸£´Â ¶óº§À» °¡Áø ÇÑ ¹öÆ°À» ¸¸µç´Ù. */
  if (expand == TRUE)
    button = gtk_button_new_with_label ("TRUE,");
  else
    button = gtk_button_new_with_label ("FALSE,");

  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  /* À§ÀÇ °æ¿ì¿Í °°Àº ¹öÆ°À» ¸¸µéÁö¸¸, ´õ ´ÜÃàµÈ Ç¥ÇöÀÌ´Ù. */
  button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  sprintf (padstr, "%d);", padding);

  button = gtk_button_new_with_label (padstr);
  gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
  gtk_widget_show (button);

  return box;
}

int main( int   argc,
          char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *separator;
  GtkWidget *label;
  GtkWidget *quitbox;
  int which;

  /* ¾ðÁ¦³ª ÀÌ·¸°Ô ½ÃÀÛÇÏ´Â °ÍÀ» ÀØÁö ¸» °Í! */
  gtk_init (&argc, &argv);

  if (argc != 2) {
    fprintf (stderr, "usage: packbox num, where num is 1, 2, 3.\n");
    /* GTK¸¦ ³¡³»´Â ºÎºÐÀ̸ç, exit status´Â 1ÀÌ´Ù. */
    gtk_exit (1);
  }

  which = atoi (argv[1]);

  /* ¿ì¸®ÀÇ À©µµ¸¦ ¸¸µç´Ù. */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  /* Main À©µµ¿¡ destroy ½Ã±×³ÎÀ» ¿¬°á½ÃÄÑ Áà¾ß ÇÑ´Ù.  ÀÌ°ÍÀº Á¦´ë·Î µÈ
   * µ¿ÀÛÀ» À§ÇØ ¸Å¿ì Áß¿äÇÑ °ÍÀÌ´Ù. */
  g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  /* ¿ì¸®´Â ¼öÆò¹Ú½ºµéÀ» ÆÐÅ·ÇØ ³ÖÀ» ¼öÁ÷¹Ú½º(vbox)¸¦ ¸¸µç´Ù.
   * ¹öÆ°ÀÌ µé¾îÀÖ´Â ¼öÆò¹Ú½º´Â ÀÌ ¼öÁ÷¹Ú½º ¾ÈÀ¸·Î ¼ø¼­´ë·Î ½×ÀδÙ.
   * (½ºÅà ±¸Á¶¸¦ »ý°¢ÇÏ¸é µÉ °ÍÀÌ´Ù.) */
  box1 = gtk_vbox_new (FALSE, 0);

  switch (which) {
  case 1:
        /* »õ·Î¿î ¶óº§À» ¸¸µç´Ù. */
        label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");

        /* ¶óº§µéÀ» ¿ÞÂÊÀ¸·Î Á¤·Ä½ÃŲ´Ù.  ÀÌ°Í¿¡ ´ëÇؼ­ widgetÀÇ ¼Ó¼º
         * ¼¼ÆÃÇϱ⿡¼­ ´Ù½Ã ´Ù·ê °ÍÀÌ´Ù. */
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);

        /* ¶óº§À» ¼öÁ÷¹Ú½º(vbox box1)¿¡ ÆÐÅ·ÇÑ´Ù.  ÇÑ vbox¿¡ ÆÐÅ·µÇ´Â
         * widgetµéÀº ¼ø¼­´ë·Î ´Ù¸¥ °ÍµéÀÇ À§ÂÊÀ¸·Î ÆÐÅ·µÈ´Ù. */
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);

        /* ¶óº§À» º¸¿©ÁØ´Ù. */
        gtk_widget_show (label);

        /* make_box ÇÔ¼ö¸¦ ÀûÀýÇÑ ÀÎÀڷνá È£ÃâÇÑ´Ù. */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);
        /* ÇϳªÀÇ separator¸¦ ¸¸µç´Ù.  À̵鿡 ´ëÇؼ­ µÚ¿¡¼­ ÀÚ¼¼È÷
         * ´Ù·ê °ÍÀ̸ç, ²Ï³ª °£´ÜÇÑ °ÍÀÌ´Ù. */
        separator = gtk_hseparator_new ();

        /* separator¸¦ vbox ¾ÈÀ¸·Î ÆÐÅ·ÇÑ´Ù.  ÀÌµé °¢°¢ÀÇ widgetÀº
         * vbox ¾ÈÀ¸·Î ÆÐÅ·µÇ¹Ç·Î, ¼öÁ÷ ¹æÇâÀ¸·Î ½×ÀÏ °ÍÀÌ´Ù. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        /* ¶Ç´Ù¸¥ ¶óº§À» ¸¸µé¾î ±×°ÍÀ» º¸¿©ÁØ´Ù. */
        label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        /* °¢ ÀÎÀÚ´Â homogeneous, spacing, expand, fill, paddingÀÌ´Ù. */
        box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* ¶Ç´Ù¸¥ separator */
        separator = gtk_hseparator_new ();
        /* gtk_box_pack_start ÀÇ ¸¶Áö¸· 3°¡Áö ÀÎÀÚµéÀº
         * expand, fill, padding ÀÌ´Ù. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        break;

    case 2:

        /* ¶óº§À» »õ·Î ¸¸µç´Ù. box1Àº main()ÀÇ ½ÃÀۺκп¡¼­ ¸¸µé¾îÁø
         * ´ë·Î vboxÀÌ´Ù. */
        label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        separator = gtk_hseparator_new ();
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);

        label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
        gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
        gtk_widget_show (label);

        box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        separator = gtk_hseparator_new ();
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
        break;

    case 3:
        /* ÀÌ°ÍÀº gtk_box_pack_end()¸¦ ÀÌ¿ëÇÏ¿© widgetÀ» ¿À¸¥ÂÊ Á¤·ÄÇÏ´Â
         * °É º¸¿©ÁØ´Ù.  ¸ÕÀú, ¾Õ¿¡¼­Ã³·³ »õ·Î¿î ¹Ú½º¸¦ Çϳª ¸¸µç´Ù. */
        box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
        /* ¶óº§À» Çϳª ¸¸µç´Ù. */
        label = gtk_label_new ("end");
        /* ±×°ÍÀ» gtk_box_pack_end()·Î½á ÆÐÅ·ÇϹǷÎ, make_box()·Î ¸¸µé¾îÁø
         * hboxÀÇ ¿À¸¥ÂÊÀ¸·Î ³õ¿©Áö°Ô µÈ´Ù.
        gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
        /* ¶óº§À» º¸ÀδÙ. */
        gtk_widget_show (label);

        /* box2¸¦ box1 ¾ÈÀ¸·Î ÆÐÅ·ÇÑ´Ù. */
        gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
        gtk_widget_show (box2);

        /* bottom ÂÊÀ» À§ÇÑ separator. */
        separator = gtk_hseparator_new ();
        /* ÀÌ°ÍÀº 400Çȼ¿ÀÇ ³Êºñ¿¡ 5Çȼ¿ÀÇ ³ôÀÌ(µÎ²²)·Î separator¸¦
         * ¼¼ÆÃÇÑ´Ù. ÀÌ°ÍÀº ¿ì¸®°¡ ¸¸µç hbox°¡ ¶ÇÇÑ 400Çȼ¿ÀÇ ³ÊºñÀ̱â
         * ¶§¹®ÀÌ°í, "end" ¶óº§Àº hboxÀÇ ´Ù¸¥ ¶óº§µé°ú ±¸ºÐµÉ(separated)
         * °ÍÀÌ´Ù.  ±×·¸Áö ¾ÊÀ¸¸é, hbox ³»ºÎÀÇ ¸ðµç widgetµéÀº °¡´ÉÇѸ¸Å­
         * ¼­·Î »ª»ªÈ÷ ºÙ¾î¼­ ÆÐÅ·µÉ °ÍÀÌ´Ù. */
        gtk_widget_set_usize (separator, 400, 5);
        /* main()ÇÔ¼öÀÇ ½ÃÀۺκп¡¼­ ¸¸µé¾îÁø vbox(box1)À¸·Î separator¸¦ 
         * ÆÐÅ·ÇÑ´Ù. */
        gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
        gtk_widget_show (separator);
    }

    /* ¶Ç´Ù¸¥ hbox¸¦ ¸¸µç´Ù.. ¿ì¸®°¡ ¿øÇÏ´Â ¸¸Å­ ¾ó¸¶µçÁö ¸¸µé¼ö ÀÖ´Ù! */
    quitbox = gtk_hbox_new (FALSE, 0);

    /* ¿ì¸®ÀÇ quit ¹öÆ°ÀÌ´Ù. */
    button = gtk_button_new_with_label ("Quit");

    /* À©µµ¸¦ Æı«Çϱ⠽ñ׳ÎÀ» ¼¼ÆÃÇÑ´Ù.  ÀÌ°ÍÀº À§¿¡¼­ Á¤ÀÇµÈ ¿ì¸®ÀÇ 
     * ½Ã±×³Î Çڵ鷯¿¡ ÀÇÇØ Æ÷ÂøµÉ, "destroy"½Ã±×³ÎÀ» À©µµ·Î º¸³»ÁØ´Ù. */
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_main_quit),
                              window);
    /* quitbox·Î ¹öÆ°À» ÆÐÅ·ÇÑ´Ù.  gtk_box_pack_startÀÇ ¸¶Áö¸· ¼¼ ÀÎÀÚ´Â
     * expand, fill, paddingÀÌ´Ù. */
    gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
    /* vbox(box1) ¾ÈÀ¸·Î quitbox¸¦ ÆÐÅ·ÇÑ´Ù. */
    gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);

    /* ¿ì¸®ÀÇ ¸ðµç widgetÀ» Æ÷ÇÔÇÏ°Ô µÈ ÀÌ vbox¸¦, mainÀ©µµ·Î ÆÐÅ·. */
    gtk_container_add (GTK_CONTAINER (window), box1);

    /* ±×¸®°í ³²¾ÆÀÖ´Â ¸ðµç °ÍÀ» º¸¿©ÁØ´Ù. */
    gtk_widget_show (button);
    gtk_widget_show (quitbox);

    gtk_widget_show (box1);
    /* ¸¶Áö¸·¿¡ À©µµ¸¦ º¸¿©Á༭ ¸ðµç °ÍÀÌ Çѹø¿¡ Æ¢¾î³ª¿À¸ç º¸ÀδÙ. */
    gtk_widget_show (window);

    /* ´ç¿¬È÷ ¿ì¸®ÀÇ gtk_mainÀÌ´Ù. */
    gtk_main ();

    /* gtk_main_quit()À» È£ÃâÇß´Ù¸é Á¦¾î´Â ÀÌ°÷À¸·Î ¿Â´Ù.  gtk_exit()¸¦
     * È£ÃâÇÏ¸é ±×·¸Áö ¾Ê´Ù. */

    return 0;
}

5.4 Å×À̺íÀ» ÀÌ¿ëÇÑ ÆÐÅ·

¶Ç´Ù¸¥ ÆÐÅ· - Å×À̺íÀ» ÀÌ¿ëÇÑ °ÍÀ» º¸ÀÚ. ÀÌ°ÍÀº ¾î¶² »óȲ¿¡¼­ ¾ÆÁÖ À¯¿ëÇÒ °ÍÀÌ´Ù.

Å×À̺íÀ» ÀÌ¿ëÇؼ­, ¿ì¸®´Â widgetÀ» ³Ö¾îµÑ °ÝÀÚÆÇÀ» ¸¸µé°Ô µÈ´Ù. ±× widget µéÀº ¿ì¸®°¡ ¼³Á¤Çϴ´ë·Î ¾ó¸¶µçÁö °ø°£À» °¡Áö°Ô µÉ °ÍÀÌ´Ù.

¹°·Ð ¸ÕÀú ºÁ¾ß ÇÒ °ÍÀº gtk_table_new ÇÔ¼ö´Ù.

GtkWidget *gtk_table_new( guint    rows,
                          guint    columns,
                          gboolean homogeneous );

ù¹ø° ÀÎÀÚ´Â Å×ÀÌºí¿¡ ¸¸µé ÇàÀÇ °¹¼ö°í, µÎ¹ø°´Â ´ç¿¬È÷ ¿­ÀÇ °¹¼ö´Ù.

ÀÎÀÚ homogeneous´Â Å×À̺íÀÇ ¹Ú½ºµéÀÇ Å©±â°¡ ¾î¶»°Ô µÇ¾î¾ß ÇÏ´ÂÁö¸¦ °áÁ¤ ÇÑ´Ù. ÀÌ°ÍÀÌ TRUE¶ó¸é Å×À̺íÀÇ ¹Ú½ºµéÀº ±× Å×ÀÌºí¿¡¼­ °¡Àå Å« widgetÀÇ Å©±â¿¡ µû¸£°Ô µÈ´Ù. ¶Ç FALSE¶ó¸é °¢ ¹Ú½ºµéÀº °°Àº Çà¿¡¼­ °¡Àå ³ôÀº widgetÀÇ ³ôÀ̸¦, ±×¸®°í °°Àº ¿­¿¡¼­´Â °¡Àå ³ÐÀº widgetÀÇ ³Êºñ¸¦ µû¸£°Ô µÈ´Ù.

°¢ Çà°ú ¿­Àº 0¿¡¼­ n±îÁö Â÷ÁöÇÏ°Ô µÈ´Ù. ¿©±â¼­ nÀº gtk_table_new¸¦ È£ÃâÇÒ ¶§ °áÁ¤µÈ ¼ýÀÚ´Ù. ±×·¡¼­, ¸¸¾à ¿ì¸®°¡ Çà=2 ±×¸®°í ¿­=2, ÀÌ·¸°Ô ¼³Á¤ÇÏ°Ô µÇ¸é ±¸Á¶´Â ÀÌ·¸°Ô µÈ´Ù.

 0          1          2
0+----------+----------+
 |          |          |
1+----------+----------+
 |          |          |
2+----------+----------+

ÁÂÇ¥°è´Â ¿ÞÂÊ À§¿¡¼­ Ãâ¹ßÇÏ´Â °ÍÀ» ÁÖÀÇÇÏÀÚ. ¹Ú½º¾È¿¡ widgetÀ» ³õÀ¸·Á¸é ´ÙÀ½ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void gtk_table_attach( GtkTable         *table,
                       GtkWidget        *child,
                       guint            left_attach,
                       guint            right_attach,
                       guint            top_attach,
                       guint            bottom_attach,
                       GtkAttachOptions xoptions,
                       GtkAttachOptions yoptions,
                       guint            xpadding,
                       guint            ypadding );

ù¹ø° ÀÎÀÚ tableÀº ¿ì¸®°¡ ¸¸µç Å×À̺íÀÌ°í µÎ¹ø° child´Â ÀÌ Å×ÀÌºí¿¡ ³õÀ¸·Á°í ÇÏ´Â widgetÀÌ´Ù.

¿ÞÂÊ°ú ¿À¸¥ÂÊÀÇ attach¶ó´Â ÀÎÀÚµéÀº widgetÀ» ³õÀ» À§Ä¡¿Í ÀÌ¿ëÇÒ ¹Ú½ºÀÇ °¹¼ö¸¦ °áÁ¤ÇÑ´Ù. ¸¸¾à ¿ì¸®ÀÇ 2x2 Å×À̺íÀÇ ¿À¸¥ÂÊ ¾Æ·¡ Ä­¿¡ À§Ä¡ÇÑ ¹öÆ°À» ¿øÇÑ´Ù¸é, ±×¸®°í ±× ¿ä¼Ò¸¸ °¡µæä¿ì±â¸¦ ¿øÇÑ´Ù¸é, left_attach=1, right_ attach=2, top_attach=1, bottom_attach=2, ÀÌ·¸°Ô µÇ¾î¾ß ÇÑ´Ù.

ÀÌÁ¦, ¿ì¸®ÀÇ 2x2 Å×À̺íÀÇ Ã¹¹ø° Çà Àüü¸¦ ¼±ÅÃÇß´Ù¸é, left_attach=0, right_attach=2, top_attach=0, bottom_attach=1 À̶ó°í ÇÏ¸é µÈ´Ù.

ÀÎÀÚ xoption°ú yoptionÀº ÆÐÅ· ¿É¼ÇÀ» Á¤Çϱâ À§ÇÑ °ÍÀ¸·Î, ¿©·¯°¡ÁöÀÇ ¿É¼ÇÀ» ÁÖ±â À§Çؼ­ OR ¿¬»êÀÚ¸¦ ¾µ ¼ö ÀÖ´Ù.

ÀÌ ¿É¼ÇµéÀº ´ÙÀ½°ú °°´Ù.

  • GTK_FILL - GTK_FILLÀÌ ¼³Á¤µÇ¸é Å×ÀÌºí ¹Ú½º°¡ widgetº¸´Ù Ŭ ¶§ widgetÀº »ç¿ë°¡´ÉÇÑ ¸ðµç °ø°£À¸·Î È®´ëµÈ´Ù.
  • GTK_SHRINK - Å×À̺í widgetÀÌ ´õ ÀûÀº °ø°£À» Â÷ÁöÇϵµ·Ï µÇ¾úÀ» ¶§ widget Àº Á¤»óÀûÀ¸·Î À©µµÀÇ ¾Æ·¡ÂÊÀ¸·Î ¹Ð·Á³ª¼­ ÀϺΰ¡ º¸ÀÌÁö ¾Ê°Ô µÈ´Ù. ¸¸¾à GTK_SHRINK°¡ ¼³Á¤µÇ¸é widgetÀº ÀÚµ¿À¸·Î ÁÙ¾îµé¾î ³»ºÎ¿¡ ²À ¸Â°Ô µÈ´Ù.
  • GTK_EXPAND - ÀÌ°ÍÀÌ ¼³Á¤µÇ¸é Å×À̺íÀº À©µµÀÇ ³²´Â °ø°£À¸·Î ²Ë Â÷°Ô È®´ëµÈ´Ù.

ÆеùÀº ¹Ú½º ¾È¿¡¼­Ã³·³, Çȼ¿ ´ÜÀ§·Î ¶Ñ·ÇÇÑ ¿µ¿ªÀ» widget ÁÖÀ§¿¡ ¸¸µé¾î ÁØ´Ù.

gtk_table_attach()´Â ¼ö¸¹Àº ¿É¼ÇÀ» °¡Áö°í ÀÖ´Ù. ±×·¡¼­ ÀÌ·± shortcutÀÌ ÀÖ´Ù.

void gtk_table_attach_defaults( GtkTable  *table,
                                GtkWidget *widget,
                                guint      left_attach,
                                guint      right_attach,
                                guint      top_attach,
                                guint      bottom_attach );

X¿Í Y ¿É¼ÇÀº µðÆúÆ®·Î GTK_FILL|GTK_EXPAND, ±×¸®°í X¿Í YÀÇ ÆеùÀº 0ÀÌ´Ù. ³ª¸ÓÁö ÀÎÀÚµéÀº ÀÌÀüÀÇ ÇÔ¼ö¿Í °°´Ù.

¶ÇÇÑ gtk_table_set_row_spacing()°ú gtk_table_set_col_spacing()À̶õ ÇÔ¼öµµ ÀÖ´Ù. ÀÌ°ÍÀº ÁÖ¾îÁø Çà ¶Ç´Â ¿­¿¡ ´ëÇØ spacingÀ» ¼³Á¤ÇÑ´Ù.

void gtk_table_set_row_spacing( GtkTable *table,
                                guint     row,
                                guint     spacing );
±×¸®°í
void gtk_table_set_col_spacing ( GtkTable *table,
                                 guint     column,
                                 guint     spacing );
¾î¶² ¿­¿¡ ´ëÇؼ­ space´Â ¿­ÀÇ ¿À¸¥ÂÊÀ¸·Î, ±×·¡°í Çà¿¡ ´ëÇؼ­´Â ÇàÀÇ ¾Æ·¡ÂÊ À¸·Î ÁÖ¾îÁø´Ù´Â °ÍÀ» ¿°µÎ¿¡ µÎÀÚ.

¸ðµç Çà°ú ¿­¿¡ ´ëÇÑ ÀÏ°üµÈ spacingÀº ´ÙÀ½ µÎ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.

void gtk_table_set_row_spacings( GtkTable *table,
                                 guint    spacing )

void gtk_table_set_col_spacings( GtkTable *table,
                                 guint     spacing );

ÀÌ µÎ ÇÔ¼ö´Â ¸¶Áö¸· Çà°ú ¸¶Áö¸· ¿­¿¡ ´ëÇؼ­´Â spacingÀ» ÇÏÁö ¾Ê´Â´Ù´Â °ÍÀ» ±â¾ïÇ϶ó.

5.5 Å×À̺í ÆÐÅ· ¿¹Á¦

¿©±â¼­ ¿ì¸®´Â 2x2 Å×ÀÌºí ¾È¿¡ ¼¼°³ÀÇ ¹öÆ°ÀÌ ÀÖ´Â À©µµ¸¦ Çϳª ¸¸µç´Ù. óÀ½ µÎ ¹öÆ°Àº À­Çà¿¡ ³õÀÌ°í ¼¼¹ø° quit ¹öÆ°Àº µÎ¿­À» Â÷ÁöÇϸ鼭 ¾Æ·§Çà¿¡ ³õÀδÙ. ±×·¯¹Ç·Î ´ÙÀ½ ±×¸²Ã³·³ º¸ÀÌ°Ô µÈ´Ù.

Table Packing Example Image

¼Ò½º ÄÚµå´Â ÀÌ·¸´Ù.

/* table.c */
#include <gtk/gtk.h>

/* ¿ì¸®ÀÇ callback.
 * ÀÌ ÇÔ¼ö·Î ³Ñ°ÜÁö´Â µ¥ÀÌŸ´Â stdoutÀ¸·Î Ãâ·ÂµÈ´Ù. */
static void callback( GtkWidget *widget,
                      gpointer   data )
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

/* ÀÌ callback ÇÁ·Î±×·¥À» Á¾·áÇÑ´Ù */
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    gtk_main_quit ();
    return FALSE;
}

int main( int   argc,
          char *argv[] )
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;

    gtk_init (&argc, &argv);

    /* »õ·Î¿î À©µµ¸¦ ¸¸µç´Ù. */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* À©µµÀÇ Á¦¸ñÀ» Á¤ÇÑ´Ù. */
    gtk_window_set_title (GTK_WINDOW (window), "Table");

    /* GTK¸¦ °ðÀå Á¾·á½ÃÅ°´Â delete_event Çڵ鷯¸¦ Á¤ÇÑ´Ù. */
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);

    /* À©µµÀÇ border width¸¦ Á¤ÇÑ´Ù. */
    gtk_container_border_width (GTK_CONTAINER (window), 20);

    /* 2x2ÀÇ Å×À̺íÀ» ¸¸µç´Ù. */
    table = gtk_table_new (2, 2, TRUE);

    /* Å×À̺íÀ» À©µµ¿¡ ³õ´Â´Ù. */
    gtk_container_add (GTK_CONTAINER (window), table);

    /* ù ¹öÆ°À» ¸¸µç´Ù. */
    button = gtk_button_new_with_label ("button 1");

    /* ¹öÆ°ÀÌ ´­¸®¸é "button 1"À» Àμö·Î Çؼ­ "callback" ÇÔ¼ö¸¦
     * ºÎ¸¥´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (callback), (gpointer) "button 1");

    /* ù ¹öÆ°À» Å×ÀÌºí ¿ÞÂÊ Á¦ÀÏ À§¿¡ ³õ´Â´Ù. */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);

    gtk_widget_show (button);

    /* µÎ¹ø° ¹öÆ°À» ¸¸µç´Ù. */

    button = gtk_button_new_with_label ("button 2");

    /* ¹öÆ°ÀÌ ´­¸®¸é "button 2"À» Àμö·Î Çؼ­ "callback" ÇÔ¼ö¸¦ 
     * ºÎ¸¥´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (callback), (gpointer) "button 2");

    /* µÎ¹ø° ¹öÆ°À» Å×ÀÌºí ¿À¸¥ÂÊ Á¦ÀÏ À§¿¡ ³õ´Â´Ù. */
    gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);

    gtk_widget_show (button);

    /* "Quit" ¹öÆ°À» ¸¸µç´Ù. */
    button = gtk_button_new_with_label ("Quit");

    /* ¹öÆ°ÀÌ ´­¸®¸é "delete_event" ÇÔ¼ö¸¦ È£ÃâÇؼ­
     * ÇÁ·Î±×·¥À» ³¡³½´Ù. */
    g_signal_connect (button, "clicked",
                      G_CALLBACK (delete_event), NULL);

    /* "Quit" ¹öÆ°À» Å×À̺íÀÇ ¾Æ·§ÇàÀÇ  µÎ¿­¿¡ ³õ´Â´Ù. */ 
    gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);

    gtk_widget_show (button);

    gtk_widget_show (table);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
}

6. WidgetÀÇ °³¿ä

GTK¿¡¼­ widgetÀ» ¸¸µå´Â ÀϹÝÀûÀÎ ÀýÂ÷´Â ´ÙÀ½°ú °°´Ù.

  1. gtk_*_new() - »õ·Î¿î widgetÀ» ¸¸µé±â À§ÇÑ ´Ù¾çÇÑ ÇÔ¼ö. ÀÌ°Íµé ¸ðµÎ´Â ¿©±â¼­ ÀÚ¼¼È÷ º¸¿©Áú °ÍÀÌ´Ù.
  2. Àû´çÇÑ Çڵ鷯¿¡ »ç¿ëÇÒ ¸ðµç ½Ã±×³ÎÀ» °áÇÕ½ÃŲ´Ù.
  3. WidgetÀÇ ¼Ó¼ºÀ» ¼¼ÆÃÇÑ´Ù.
  4. gtk_container_add()³ª gtk_box_pack_start()°°Àº Àû´çÇÑ ÇÔ¼ö¸¦ ½á¼­ widgetÀ» ÄÁÅ×ÀÌ³Ê ¾ÈÀ¸·Î ÆÐÅ·ÇÑ´Ù.
  5. gtk_widget_show()·Î widgetÀ» º¸ÀδÙ.

gtk_widget_show()´Â ¿ì¸®°¡ widgetÀÇ ¼Ó¼ºÀ» ¸ðµÎ ¼¼ÆÃÇßÀ½À» GTK¿¡°Ô ¾Ë¸®°í, ±×°ÍÀº ÀÌÁ¦ º¸¿©Áú Áغñ°¡ ´Ù µÈ °ÍÀÌ´Ù. ¿ì¸®´Â ±×°ÍÀ» ´Ù½Ã º¸ÀÌÁö ¾Ê°Ô Çϱâ À§ÇØ gtk_widget_hide¸¦ ÀÌ¿ëÇÒ ¼öµµ ÀÖ´Ù. WidgetµéÀÌ º¸¿©Áö´Â ¼ø¼­´Â Áß¿ä ÇÏÁö ¾Ê´Ù. ³»°¡ ¸»ÇÏ·Á´Â °ÍÀº, °¢°¢ÀÇ widgetÀÌ »ý°Ü³ª´Â ´ë·Î ½ºÅ©¸°¿¡ º¸¿©Áö°Ô ÇÏ´Â °Íº¸´Ù´Â, À©µµ¸¦ °¡Àå ³ªÁß¿¡ º¸¿©Áö°Ô Çؼ­ ¸ðµç ±¸¼º¿ä¼Ò°¡ Çѹø¿¡ Æ¢¾î¿À¸£°Ô ÇÏ´Â °ÍÀÌ ³´´Ù´Â °ÍÀÌ´Ù. gtk_widget_show()ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ°Ô µÇ¸é ¾î¶² widget(À©µµ ¿ª½Ã ÇϳªÀÇ widgetÀÌ´Ù)ÀÇ ±¸¼º¿ä¼ÒµéÀº ±× À©µµ ÀÚü°¡ º¸¿©Áö±â Àü¿¡ ¸ÕÀú º¸¿©ÁöÁö ¾Ê´Â´Ù.

6.1 ij½ºÆÃ(ÀÚ·áÇüÀÇ °­Á¦º¯È¯)

°è¼ÓÇϸ鼭 ¾Ë°ÚÁö¸¸, GTK´Â ÀÚ·áÇüÀÇ °­Á¦º¯È¯ ½Ã½ºÅÛÀ» ¾´´Ù. ÀÌ°ÍÀº ÁÖ¾îÁø ´ë»óÀ» ij½ºÆÃÇÏ´Â ´É·ÂÀ» Å×½ºÆ®ÇÒ ¶§³ª, ±×¸®°í ij½ºÆÃÀ» ½ÇÇàÇÒ ¶§³ª, ¾ðÁ¦³ª ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÔÀ¸·Î½á ÀÌ·ç¾îÁø´Ù. ¿ì¸®°¡ º¸°Ô µÉ ¸î¸îÀº ´ÙÀ½°ú °°´Ù.

  • GTK_WIDGET(widget)
  • GTK_OBJECT(object)
  • G_CALLBACK(function)
  • GTK_CONTAINER(container)
  • GTK_WINDOW(window)
  • GTK_BOX(box)

À̰͵éÀº ¸ðµÎ ÇÔ¼öÀÇ ÀÎÀÚµéÀ» ij½ºÆ®Çϱâ À§ÇØ ¾²¿´´Ù. ¿ì¸®´Â À̵éÀ» ¿¹Á¦µé¿¡¼­ º¼ °ÍÀ̸ç, ÇÔ¼öÀÇ ¼±¾ðºÎ¸¦ º¸´Â °Í¸¸À¸·Î ±×µéÀ» ÀÌ¿ëÇÒ ¶§¸¦ ¸»ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

¾Æ·¡ÀÇ Å¬·¡½º °èÃþ±¸Á¶¿¡¼­ º¼ ¼ö ÀÖµíÀÌ, ¸ðµç GtkWidgetµéÀº ±â¹ÝŬ·¡½ºÀÎ GtkObject¿¡¼­ ÆÄ»ýµÈ °ÍÀÌ´Ù. ÀÌ°ÍÀº ¾î¶² ÇÔ¼ö°¡ object¸¦ ¿ä±¸ÇÒ ¶§ ¾îµð¼­ µçÁö widgetÀ» ÀÌ¿ëÇÒ ¼ö ÀÖÀ½À» ÀǹÌÇÑ´Ù. ¸¹Àº ÇÔ¼ö¿¡¼­ ¼ö¿ëÇÏ´Â gpointer¿¡´Â ŸÀÔ Ä³½ºÆÃÀÌ ÇÊ¿ä¾ø´Ù.

¿¹¸¦ µé¾î º¸ÀÚ.

g_signal_connect( button, "clicked",
                  G_CALLBACK (callback_function), callback_data);

ÀÌ°ÍÀº ¹öÆ°À» ÇϳªÀÇ object·Î ij½ºÆ®ÇÏ°í, ÇÔ¼ö Æ÷ÀÎÅ͸¦ callbackÀ¸·Î ij½ºÆ®ÇÑ´Ù.

¸¹Àº À§Á¬Àº ¶ÇÇÑ ÄÁÅ×À̳ʴÙ. ¾Æ·¡ÀÇ Å¬·¡½º °èÃþ±¸Á¶¸¦ º¸¸é »ó´ç¼öÀÇ À§Á¬ÀÌ ÄÁÅ×ÀÌ³Ê Å¬·¡½º¿¡¼­ ÆÄ»ýµÇ¾úÀ½À» ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. ±×µé Áß ¾î¶² widgetÀÌ¶óµµ ÄÁÅ×À̳ʸ¦ ¿ä±¸ÇÏ´Â ÇÔ¼ö¿¡ ³Ñ°ÜÁÖ±â À§ÇØ GTK_CONTAINER ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.

ºÒÇàÇÏ°Ôµµ ÀÌ·± ¸ÅÅ©·ÎµéÀº ÀÌ ¹®¼­¿¡¼­ ±¤¹üÀ§ÇÏ°Ô ´Ù·ç¾îÁöÁö ¾Ê¾Ò´Ù. ³ª´Â ¿©·¯ºÐÀÌ GTKÀÇ Çì´õÆÄÀϵéÀ» »ìÆ캸±â¸¦ ±ÇÇÑ´Ù. »ç½Ç, ÇÔ¼öÀÇ ¼±¾ðºÎ¸¦ º¸¸é¼­ À§Á¬ÀÌ ¾î¶»°Ô ÀÛ¿ëÇÏ´ÂÁö °øºÎÇÏ´Â °ÍÀº ±×¸® ¾î·ÆÁö ¾Ê´Ù.

6.2 WidgetÀÇ °èÃþ±¸Á¶

¿©·¯ºÐÀÌ Âü°íÇÒ ¼ö ÀÖµµ·Ï, ¿©±â widgetµéÀ» º¸ÃæÇϱâ À§ÇÑ Å¬·¡½º °èÃþ±¸Á¶ Æ®¸®°¡ ÀÖ´Ù.

GObject
 |  
 GtkObject
  +GtkWidget
  | +GtkMisc
  | | +GtkLabel
  | | | `GtkAccelLabel
  | | +GtkArrow
  | | `GtkImage
  | +GtkContainer
  | | +GtkBin
  | | | +GtkAlignment
  | | | +GtkFrame
  | | | | `GtkAspectFrame
  | | | +GtkButton
  | | | | +GtkToggleButton
  | | | | | `GtkCheckButton
  | | | | |   `GtkRadioButton
  | | | | `GtkOptionMenu
  | | | +GtkItem
  | | | | +GtkMenuItem
  | | | |   +GtkCheckMenuItem
  | | | |   | `GtkRadioMenuItem
  | | | |   +GtkImageMenuItem
  | | | |   +GtkSeparatorMenuItem
  | | | |   `GtkTearoffMenuItem
  | | | +GtkWindow
  | | | | +GtkDialog
  | | | | | +GtkColorSelectionDialog
  | | | | | +GtkFileSelection
  | | | | | +GtkFontSelectionDialog
  | | | | | +GtkInputDialog
  | | | | | `GtkMessageDialog
  | | | | `GtkPlug
  | | | +GtkEventBox
  | | | +GtkHandleBox
  | | | +GtkScrolledWindow
  | | | `GtkViewport
  | | +GtkBox
  | | | +GtkButtonBox
  | | | | +GtkHButtonBox
  | | | | `GtkVButtonBox
  | | | +GtkVBox
  | | | | +GtkColorSelection
  | | | | +GtkFontSelection
  | | | | `GtkGammaCurve
  | | | `GtkHBox
  | | |   +GtkCombo
  | | |   `GtkStatusbar
  | | +GtkFixed
  | | +GtkPaned
  | | | +GtkHPaned
  | | | `GtkVPaned
  | | +GtkLayout
  | | +GtkMenuShell
  | | | +GtkMenuBar
  | | | `GtkMenu
  | | +GtkNotebook
  | | +GtkSocket
  | | +GtkTable
  | | +GtkTextView
  | | +GtkToolbar
  | | `GtkTreeView
  | +GtkCalendar
  | +GtkDrawingArea
  | | `GtkCurve
  | +GtkEditable
  | | +GtkEntry
  | |   `GtkSpinButton
  | +GtkRuler
  | | +GtkHRuler
  | | `GtkVRuler
  | +GtkRange
  | | +GtkScale
  | | | +GtkHScale
  | | | `GtkVScale
  | | `GtkScrollbar
  | |   +GtkHScrollbar
  | |   `GtkVScrollbar
  | +GtkSeparator
  | | +GtkHSeparator
  | | `GtkVSeparator
  | +GtkInvisible
  | +GtkPreview
  | `GtkProgressBar
  +GtkAdjustment
  +GtkCellRenderer
  | +GtkCellRendererPixbuf
  | +GtkCellRendererText
  | +GtkCellRendererToggle
  +GtkItemFactory
  +GtkTooltips
  `GtkTreeViewColumn

6.3 À©µµ¿Í ¹«°üÇÑ widget

¿©±âÀÇ widgetµéÀº °ü·ÃµÈ À©µµ°¡ ¾ø´Â °ÍµéÀÌ´Ù. ¸¸¾à ¾î¶² À̺¥Æ®¸¦ Æ÷Âø ÇÏ·Á¸é GtkEventBox¸¦ ÀÌ¿ëÇØ¾ß ÇÒ °ÍÀÌ´Ù. The EventBox Widget¿¡ ´ëÇÑ sectionÀ» ÂüÁ¶Ç϶ó.

GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkButton
GtkCheckButton
GtkFixed
GtkImage
GtkLabel
GtkMenuItem
GtkNotebook
GtkPaned
GtkRadioButton
GtkRange
GtkScrolledWindow
GtkSeparator
GtkTable
GtkToolbar
GtkAspectFrame
GtkFrame
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator

¿ì¸®´Â °¢°¢ÀÇ widgetÀ» Â÷·Ê·Î ½ÃÇèÇÏ°í ±×µéÀ» º¸ÀÏ ¼ö ÀÖ´Â °£´ÜÇÑ ÇÔ¼öµéÀ» ¸¸µé¾î °¡¸ç GTK¿¡ ´ëÇÑ Å½±¸¸¦ °è¼ÓÇÒ °ÍÀÌ´Ù. ¶Ç´Ù¸¥ ÈǸ¢ÇÑ ¼Ò½º´Â GTK¿Í ÇÔ²² ¹èÆ÷µÈ testgtk.c ÀÌ´Ù. ±×°ÍÀº gtk/testgtk.c ¿¡¼­ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.

7. ¹öÆ° widget

7.1 º¸ÅëÀÇ ¹öÆ°

¿ì¸®´Â ¹öÆ° À§Á¬¿¡ ´ëÇؼ­´Â °ÅÀÇ º¸¾Æ¿Ô´Ù. ±×°ÍÀº »ó´çÈ÷ °£´ÜÇÏ´Ù. ±×·±µ¥ ¹öÆ°À» ¸¸µå´Âµ¥´Â µÎ°¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. ¿ì¸®´Â ¶óº§ÀÌ ÀÖ´Â ¹öÆ°À» ¸¸µé±â À§ÇØ gtk_button_new_with_labe()À̳ª gtk_button_new_with_mnemonic()À» ÀÌ¿ëÇÒ ¼ö ÀÖ°í, ºó ¹öÆ°À» ¸¸µé±âÀ§ÇØ gtk_button_new()¸¦ ÀÌ¿ëÇÒ ¼öµµ ÀÖ´Ù. ±×·± ´ÙÀ½ ±×°Í¿¡ ¶óº§À» ºÙÀ̵çÁö ÇȽº¸ÊÀ» ºÙÀ̵çÁö ÇÏ´Â °ÍÀº ¿©·¯ºÐ¿¡°Ô ´Þ·ÁÀÖ´Ù. ±×·¸°Ô ÇÏ·Á¸é »õ·Î¿î ¹Ú½º¸¦ ¸¸µé°í gtk_box_pack_start()·Î½á ÀÌ ¹Ú½º ¾È¿¡ ¿ì¸®ÀÇ object¸¦ ÆÐÅ·Çϸç, ±× ´ÙÀ½¿£ gtk_container_add()·Î½á ±× ¹Ú½º¸¦ ¹öÆ° ¾ÈÀ¸·Î ÆÐÅ·ÇÏ¸é µÈ´Ù.

ÀÌ ¿¹Á¦´Â gtk_button_new()¸¦ ÀÌ¿ëÇÏ¿© ±×¸²°ú ¶óº§ÀÌ ÀÖ´Â ¹öÆ°À» ¸¸µç´Ù. ¹Ú½º¸¦ ¸¸µå´Â Äڵ尡 ´Ù¸¥ °Íµé·ÎºÎÅÍ ¶³¾îÁ® ³ª¿Í ÀÖÀ¸¸ç ¿©·¯ºÐÀÇ ÇÁ·Î±×·¥ ¿¡¼­ ±×°ÍÀ» ÀÌ¿ëÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

/* buttons.c */

#include <stdlib.h>
#include <gtk/gtk.h>

/* À̹ÌÁö¿Í ±×°Í¿¡ ÆÐÅ·µÈ ¶óº§À» °¡Áö°í ÀÖ´Â hbox¸¦ Çϳª ¸¸µç´Ù.
 * ±×¸®°í ±× ¹Ú½º¸¦ ¸®ÅÏÇÑ´Ù. */

static GtkWidget *xpm_label_box( gchar     *xpm_filename,
                                 gchar     *label_text )
{
    GtkWidget *box;
    GtkWidget *label;
    GtkWidget *image;

    /* À̹ÌÁö¿Í ¶óº§À» À§ÇÑ ¹Ú½º¸¦ ¸¸µç´Ù. */
    box = gtk_hbox_new (FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (box), 2);

    /* ¹öÆ°ÀÇ ½ºÅ¸ÀÏÀ» ÃëÇÑ´Ù.. background »ö±òÀ» ÃëÇÏ´Â °Í °°Àºµ¥,
     * ¾Æ´Ï¶ó¸é ´©±º°¡ ³ª¿¡°Ô Á¤Á¤ÇØ ÁÖ±æ ¹Ù¶õ´Ù. */
    image = gtk_image_new_from_file (xpm_filename);

    /* ¹öÆ°À» À§ÇÑ ¶óº§À» ¸¸µç´Ù. */
    label = gtk_label_new (label_text);

    /* ¹Ú½º ¾ÈÀ¸·Î ÇȽº¸Ê°ú ¶óº§À» ÆÐÅ·ÇØ ³Ö´Â´Ù. */
    gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
    gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);

    gtk_widget_show (image);
    gtk_widget_show (label);

    return box;
}

/* ¿ì¸®ÀÇ ÀüÇüÀûÀÎ callback ÇÔ¼ö´Ù. */
static void callback( GtkWidget *widget,
                      gpointer   data )
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

int main( int   argc,
          char *argv[] )
{
    /* GtkWidgetÀº À§Á¬µéÀ» À§ÇÑ ±â¾ïÀå¼Ò Á¾·ù´Ù. */
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box;

    gtk_init (&argc, &argv);

    /* À©µµ¸¦ Çϳª ¸¸µç´Ù. */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");

    /* ¸ðµç À©µµµé¿¡ ´ëÇØ ÀÌ·¸°Ô ÇØÁÖ´Â °ÍÀÌ ÁÁÀ» °ÍÀÌ´Ù. */
    g_signal_connect (window, "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);

    g_signal_connect (window, "delete-event",
                      G_CALLBACK (gtk_main_quit), NULL)

    /* À©µµÀÇ border width¸¦ ¼¼ÆÃÇÑ´Ù. */
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* »õ·Î¿î ¹öÆ°À» Çϳª ¸¸µç´Ù. */
    button = gtk_button_new ();

    /* "clicked" ½Ã±×³ÎÀ» ¿ì¸®ÀÇ ÄݹéÇÔ¼ö¿Í ¿¬°áÇÑ´Ù.*/
    g_signal_connect (button, "clicked",
                      G_CALLBACK (callback), (gpointer) "cool button");

    /* ¹Ú½º¸¦ ¸¸µå´Â ÇÔ¼ö´Ù. */
    box = xpm_label_box ("info.xpm", "cool button");

    /* ¿ì¸® widgetµéÀ» ÆÐÅ·ÇÏ°í, º¸¿©ÁØ´Ù. */
    gtk_widget_show (box);

    gtk_container_add (GTK_CONTAINER (button), box);

    gtk_widget_show (button);

    gtk_container_add (GTK_CONTAINER (window), button);

    gtk_widget_show (window);

    /* ¿©±â¼­ºÎÅÍ´Â ¹º°¡ Àç¹ÌÀÖ´Â ÀÏÀÌ ½ÃÀÛµÉ ¶§±îÁö ¹«ÀÛÁ¤ ±â´Ù¸°´Ù. */
    gtk_main ();

    return 0;
}

xpm_label_box ÇÔ¼ö´Â ÄÁÅ×À̳ʰ¡ µÉ ¼ö ÀÖ´Â ¾î¶² widget¿¡¶óµµ ÇȽº¸Ê°ú ¶óº§À» ÆÐÅ·Çϱâ À§ÇÏ¿© ¾²¿©Áú ¼ö ÀÖÀ» °ÍÀÌ´Ù.

¹öÆ° À§Á¬Àº ¿©·¯ ½Ã±×³ÎÀ» °¡Áø´Ù.

  • pressed - ¹öÆ° À§Á¬À» ´­¸£¸é ¹ß»ýÇÑ´Ù.
  • released - ¹öÆ° À§Á¬À» ¶¼¸é ¹ß»ýÇÑ´Ù.
  • clicked - ¹öÆ° À§Á¬À» ´­·¶´Ù°¡ ¶¼¸é ¹ß»ýÇÑ´Ù.
  • enter - ¹öÆ° À§Á¬¿¡ ÁøÀÔÇÏ¸é ¹ß»ýÇÑ´Ù.
  • leave - ¹öÆ° À§Á¬¿¡¼­ ¹þ¾î³ª¸é ¹ß»ýÇÑ´Ù.

7.2 Åä±Û ¹öÆ°

Åä±Û¹öÆ°Àº Ŭ¸¯¿¡ ÀÇÇØ ÅÃÀϵǴ µÎ°¡Áö Áß ¾î´À ÇÑ »óÅ¿¡ ÀÖ¾î¾ß ÇÑ´Ù´Â Á¡¸¸ »«´Ù¸é º¸Åë ¹öÆ°°ú ¸Å¿ì À¯»çÇÏ´Ù. ±×°ÍÀº ´­·ÁÁø »óÅ·ΠÀÖ´Ù°¡µµ, ¿ì¸®°¡ ´Ù½Ã Ŭ¸¯ÇØ ÁÖ¸é ´Ù½Ã Æ¢¾î³ª¿À°Ô µÉ ¼ö ÀÖ´Ù. ¶Ç Ŭ¸¯ÇÏ¸é ±×°ÍÀº ´Ù½Ã ´­·¯Á® µé¾î°¥ °ÍÀÌ´Ù.

Åä±Û¹öÆ°¿¡ ¾²ÀÌ´Â ¸¹Àº ÇÔ¼öµéÀÌ ¶óµð¿À¿Í üũ ¹öÆ°¿¡ ÀÇÇØ »ó¼ÓµÇ¾î ¾²À̵íÀÌ, Åä±Û¹öÆ°Àº üũ¹öÆ°°ú ¶óµð¿À¹öÆ°ÀÇ ±â¹ÝÀÌ µÈ´Ù. À̰͵éÀ» Á¢ÇÏ°Ô µÇ¸é ÀÌ Á¡À» ´Ù½Ã ÁöÀûÇÒ °ÍÀÌ´Ù.

»õ·Î¿î Åä±Û¹öÆ°À» ¸¸µé·Á¸é ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

GtkWidget *gtk_toggle_button_new( void );

GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );

GtkWidget *gtk_toggle_button_new_with_mnemonic( const gchar *label );

ÃßÃøÇÒ ¼ö ÀÖ°ÚÁö¸¸, ÀÌ°ÍÀº º¸Åë¹öÆ° widgetÀÇ È£Ãâ°ú ¶È°°ÀÌ ÀÛ¿ëÇÑ´Ù. ù¹ø° °ÍÀº ºó Åä±Û¹öÆ°À», ±×¸®°í µÎ¹ø° °ÍÀº ÀÌ¹Ì ¶óº§widgetÀÌ ÆÐÅ·µÇ¾î ÀÖ´Â ¹öÆ°À» ¸¸µç´Ù.

Åä±Û¹öÆ°°ú ¶óµð¿À¹öÆ°, üũ¹öÆ°ÀÇ »óŸ¦ µÇµ¹¸®±â À§ÇØ, ¿ì¸®´Â ¾Æ·¡ÀÇ ¿¹Á¦¿¡¼­ º¸¿©Áú ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÑ´Ù. ÀÌ°ÍÀº ¾î¶² callback¿¡¼­ Åä±ÛÀÇ »óŸ¦ Å×½ºÆ®ÇÑ´Ù. Åä±Û¹öÆ°¿¡ ÀÇÇØ ¹ß»ýÇÏ´Â ½Ã±×³ÎÀº (Åä±Û/üũ/¶óµð¿À ¹öÆ° widgetµé) "toggled" ½Ã±×³ÎÀÌ´Ù. ÀÌ ¹öÆ°µéÀÇ »óŸ¦ üũÇÏ·Á¸é ÀÌ toggled ½Ã±×³ÎÀ» Àâ¾Æ³»µµ·Ï ½Ã±×³Î Çڵ鷯¸¦ ¼Â¾÷ÇÏ°í, ±×°ÍÀÇ »óŸ¦ °áÁ¤Çϱâ À§ÇÑ ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÑ´Ù. ±× callbackÀº ÀÌ·± ¸ð¾çÀÇ °ÍÀÌ´Ù.

void toggle_button_callback (GtkWidget *widget, gpointer data)
{
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
    {
        /* If control reaches here, the toggle button is down */
    
    } else {
    
        /* If control reaches here, the toggle button is up */
    }
}

void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
                                   gboolean        is_active );

À§ÀÇ È£ÃâÀº Åä±Û¹öÆ°°ú, ±×°Í¿¡¼­ ÆÄ»ýµÇ´Â ¶óµð¿À¿Í üũ¹öÆ°ÀÇ »óŸ¦ ¼¼ÆÃÇϱâ À§ÇØ ¾²ÀÏ ¼ö ÀÖ´Ù. ù¹ø° ÀÎÀÚ·Î ¿ì¸®°¡ ¸¸µç ¹öÆ°À» ³Ñ°ÜÁÖ°í, ±×¸®°í ±×°ÍÀÌ ´­¸° »óÅÂÀÎÁö ¾Æ´ÑÁö¸¦ ±¸º°Çϱâ À§ÇØ µÎ¹ø° ÀÎÀÚ¸¦ TRUE ¶Ç´Â FALSE·Î ³Ñ°ÜÁØ´Ù. µðÆúÆ®´Â ¾È ´­·¯Áø »óÅÂ, Áï FALSEÀÌ´Ù.

¿ì¸®°¡ gtk_toggle_button_set_state()ÇÔ¼ö¸¦ ¾²¸é ¹öÆ°¿¡¼­ "clicked"°ú "toggled" ½Ã±×³ÎÀÌ ¹ß»ýÇؼ­ ¹öÆ°ÀÇ »óÅ°¡ ½ÇÁ¦·Î º¯ÇÏ°Ô µÊÀ» ±â¾ïÇÏÀÚ.

gboolean gtk_toggle_button_get_active   (GtkToggleButton *toggle_button);

ÀÌ°ÍÀº °£´ÜÈ÷ ¹öÆ°À» Åä±ÛÇÏ°í, "toggled"½Ã±×³ÎÀ» ¹ß»ý½ÃŲ´Ù.

7.3 üũ¹öÆ°

üũ¹öÆ°Àº À§¿¡ ÀÖ´Â Åä±Û¹öÆ°¿¡¼­ ¸¹Àº Ư¼º°ú ÇÔ¼öµéÀ» »ó¼Ó¹Þ¾ÒÁö¸¸ ´Ù¼Ò ´Ù¸£°Ô º¸ÀδÙ. ÀÌ°ÍÀº ¹öÆ°°ú ±× ¾ÈÀÇ ÅؽºÆ®·Î Àִٱ⺸´Ù´Â, ÅؽºÆ® ¿·¿¡ ÀÖ´Â ÀÛÀº »ç°¢ÇüÀ̶ó°í ÇÒ ¼ö ÀÖ´Ù. À̵éÀº ¾î¶² ¾îÇÿ¡¼­ Åä±ÛµÇ´Â ¿É¼ÇÀ¸·Î¼­ ¸¹ÀÌ ºÃÀ» °ÍÀÌ´Ù.

ÀÌ°ÍÀ» ¸¸µå´Â µÎ°¡Áö ÇÔ¼ö´Â º¸Åë¹öÆ°¿¡¼­¿Í ¸¶Âù°¡Áö´Ù.

GtkWidget* gtk_check_button_new (void);

GtkWidget* gtk_check_button_new_with_label (gchar *label);

GtkWidget *gtk_check_button_new_with_mnemonic ( const gchar *label );

new_with_labelÇÔ¼ö´Â ¿·¿¡ ÅؽºÆ® ¶óº§À» °¡Áö°í Àִ üũ¹öÆ°À» ¸¸µç´Ù.

üũ¹öÆ°ÀÇ »óŸ¦ üũÇÏ´Â °ÍÀº Åä±Û¹öÆ°¿¡¼­¿Í °°´Ù.

7.4 ¶óµð¿À¹öÆ°

¶óµð¿À¹öÆ°Àº ±×µéÀÌ ±×·ìÈ­µÇ¾î À־ ÇÑ ¹ø¿¡ ¿ÀÁ÷ Çϳª¾¿¸¸ ¼±ÅÃ/º¹±ÍµÉ ¼ö ÀÖ´Ù´Â Á¡¸¸ »©°í´Â üũ¹öÆ°°ú À¯»çÇÏ´Ù. ÀÌ°ÍÀº ¾îÇÃÀÌ ¿É¼ÇÀÇ ¸®½ºÆ®¿¡¼­ Çϳª¸¦ ¼±ÅÃÇϵµ·Ï ÇÏ´Â °æ¿ì¿¡ ¾²À̸é ÁÁÀ» °ÍÀÌ´Ù.

»õ·Î¿î ¶óµð¿À¹öÆ°À» ¸¸µå´Â µ¥ ¾²´Â ÇÔ¼öµéÀÌ´Ù.

GtkWidget *gtk_radio_button_new( GSList *group );

GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );

GtkWidget *gtk_radio_button_new_with_label( GSList *group,
                                            const gchar  *label );

GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
                                                        const gchar    *label );

GtkWidget *gtk_radio_button_new_with_mnemonic( GSList *group,
                                               const gchar  *label );

GtkWidget *gtk_radio_button_new_with_mnemonic_from_widget( GtkRadioButton *group,
                                                           const gchar  *label );

ÀÌ È£Ãâµé¿¡´Â ´Ù¼Ò ´Ù¸¥ ÀÎÀÚ°¡ ÀÖ´Ù´Â °ÍÀ» ´«¿©°Ü º¸ÀÚ. À̵éÀº ÀûÀýÈ÷ ÀÓ¹«¸¦ ¼öÇàÇÒ ±×·ìÀ» ÇÊ¿ä·Î ÇÑ´Ù. gtk_radio_button_new()°ú gtk_radio_button_new_with_label()ÀÇ Ã¹¹ø° È£Ãâ¿¡¼­ ù¹ø° ÀÎÀÚ·Î NULLÀ» ³Ñ°Ü Áà¾ß ÇÑ´Ù. ±×¸®°í ¿ì¸®´Â ÀÌ°ÍÀ» ÀÌ¿ëÇÏ¿© ±×·ìÀ» ¸¸µç´Ù.

GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );

±×¸®°í´Â ÀÌ ±×·ìÀ» gtk_radio_button_new ¶Ç´Â gtk_radio_button_new_with_ label¿¡ ù¹ø° ÀÎÀÚ·Î ³Ñ°ÜÁØ´Ù.

´ÙÀ½ ¹®Àå°ú °°Àº ½ÄÀ¸·Î ¾î¶² º¯¼ö Çϳª°¡ ¹öÆ°µéÀÇ ¸®½ºÆ®¸¦ °¡Áö°í ÀÖ¾î¾ßÇÒ ÇÊ¿ä°¡ ¾øµµ·Ï ÁÙ¿© ¾µ ¼öµµ ÀÖ´Ù.

     button2 = gtk_radio_button_new_with_label(
                 gtk_radio_button_get_group (GTK_RADIO_BUTTON (button1)),
                 "button2");

_from_widget() °è¿­ÀÇ »ý¼º ÇÔ¼ö´Â gtk_radio_button_get_group() È£ÃâÀ» Á¦°ÅÇÏ¿© ´õ ÁÙ¿© ¾µ ¼ö ÀÖ°Ô ÇÑ´Ù.

     button2 = gtk_radio_button_new_with_label_from_widget(
                 GTK_RADIO_BUTTON (button1), 
                 "button2");

´ÙÀ½À» ÀÌ¿ëÇؼ­ ¾î¶² ¹öÆ°ÀÌ µðÆúÆ®·Î ´­·¯Áö°Ô µÇ´ÂÁö¸¦ ºÐ¸íÈ÷ Çصδ °Íµµ ÁÁÀº »ý°¢ÀÌ´Ù.

void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
                                  gint state);

ÀÌ°ÍÀº Åä±Û¹öÆ°¿¡ ´ëÇÑ ºÎºÐ¿¡¼­ ¼³¸íµÇ¾úÀ¸¸ç, Á¤È®È÷ °°Àº ¹æ¹ýÀ» µû¸¥´Ù.

´ÙÀ½ ¿¹´Â ¼¼°³ÀÇ ¹öÆ°À¸·Î ÀÌ·ç¾îÁø ±×·ìÀ» ¸¸µç´Ù.

/* radiobuttons.c */

#include <glib.h>
#include <gtk/gtk.h>

static gboolean close_application( GtkWidget *widget,
                                   GdkEvent  *event,
                                   gpointer   data )
{
  gtk_main_quit ();
  return FALSE;
}

int main( int   argc,
          char *argv[] )
{
    GtkWidget *window = NULL;
    GtkWidget *box1;
    GtkWidget *box2;
    GtkWidget *button;
    GtkWidget *separator;
    GSList *group;
  
    gtk_init (, );    
      
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (close_application),
                      NULL);

    gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
    gtk_container_set_border_width (GTK_CONTAINER (window), 0);

    box1 = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), box1);
    gtk_widget_show (box1);

    box2 = gtk_vbox_new (FALSE, 10);
    gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
    gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
    gtk_widget_show (box2);

    button = gtk_radio_button_new_with_label (NULL, "button1");
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

    group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
    button = gtk_radio_button_new_with_label (group, "button2");
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

    button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
                                                          "button3");
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

    separator = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
    gtk_widget_show (separator);

    box2 = gtk_vbox_new (FALSE, 10);
    gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
    gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
    gtk_widget_show (box2);

    button = gtk_button_new_with_label ("close");
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (close_application),
                              window);
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_set_can_default (button, TRUE);
    gtk_widget_grab_default (button);
    gtk_widget_show (button);
    gtk_widget_show (window);
     
    gtk_main ();

    return 0;
}

8. ´Ù¾çÇÑ widgetµé

8.1 ¶óº§(label)

¶óº§Àº GTK¿¡¼­ ÀÚÁÖ ¾²ÀÌ°í ºñ±³Àû °£´ÜÇÑ °ÍÀÌ´Ù. À̵éÀº °ü·ÃµÈ XÀ©µµ°¡ ¾øÀ¸¹Ç·Î ½Ã±×³ÎÀ» ¹ß»ýÇÏÁö ¾Ê´Â´Ù. ¸¸¾à ½Ã±×³ÎÀ» Àâ¾Æ³»°Å³ª Ŭ¸®ÇÎÀ» ÇÒ ¸ñÀûÀ̶ó¸é EventBox widgetÀ» ÀÌ¿ëÇ϶ó.

»õ·Î¿î ¶óº§À» ¸¸µé±â À§ÇØ ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

GtkWidget *gtk_label_new( const char *str );

GtkWidget *gtk_label_new_with_mnemonic( const char *str );

ÇϳªÀÇ ÀÎÀÚ´Â ¿ì¸®°¡ ³ªÅ¸³»°íÀÚ ÇÏ´Â ¶óº§ÀÇ ¹®ÀÚ¿­ÀÌ´Ù.

¶óº§À» ¸¸µç ÀÌÈÄ¿¡ ÀÌ ¶óº§ÀÇ ÅؽºÆ®¸¦ ¹Ù²Ù·Á¸é ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

void gtk_label_set_text( GtkLabel   *label,
                         const char *str );

ù¹ø° ÀÎÀÚ´Â ÀÌÀü¿¡ ¸¸µé¾îÁ® ÀÖ´Â ¶óº§(GTK_LABEL()¸ÅÅ©·Î·Î½á ij½ºÆ®µÊ) ÀÌ°í, µÎ¹ø°´Â »õ·Î¿î ¹®ÀÚ¿­ÀÌ´Ù.

»õ·Î¿î ¶óº§À» À§ÇÑ °ø°£Àº ÇÊ¿äÇÒ °æ¿ì¿¡ ÀÚµ¿ÀûÀ¸·Î Á¶ÀýµÈ´Ù.

ÇöÀçÀÇ ¹®ÀÚ¿­À» µÇã°í ½Í´Ù¸é ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

const gchar* gtk_label_get_text( GtkLabel  *label );

¹ÝȯÇÑ ¹®ÀÚ¿­À» Àý´ë·Î free ÇÏÁö ¸»¶ó.

¶óº§Àº ÀÌ°ÍÀ» »ç¿ëÇÏ¿© Á¤·ÄÇÒ ¼ö ÀÖ´Ù.

void gtk_label_set_justify( GtkLabel         *label,
                            GtkJustification  jtype );

jtypeÀÇ °ª:

  GTK_JUSTIFY_LEFT
  GTK_JUSTIFY_RIGHT
  GTK_JUSTIFY_CENTER (the default)
  GTK_JUSTIFY_FILL

¶óº§Àº ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ ÀÚµ¿ ÁٹٲÞÀ» ÇÒ ¼ö ÀÖ´Ù.

void gtk_label_set_line_wrap (GtkLabel *label,
                              gboolean  wrap);

wrapÀº TRUE ³ª FALSE ÀÌ´Ù.

#include <gtk/gtk.h>

int main( int   argc,
          char *argv[] )
{
  static GtkWidget *window = NULL;
  GtkWidget *hbox;
  GtkWidget *vbox;
  GtkWidget *frame;
  GtkWidget *label;

  /* Initialise GTK */
  gtk_init (, );

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window, "destroy",
                    G_CALLBACK (gtk_main_quit),
                    NULL);

  gtk_window_set_title (GTK_WINDOW (window), "Label");
  vbox = gtk_vbox_new (FALSE, 5);
  hbox = gtk_hbox_new (FALSE, 5);
  gtk_container_add (GTK_CONTAINER (window), hbox);
  gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (window), 5);
  
  frame = gtk_frame_new ("Normal Label");
  label = gtk_label_new ("This is a Normal label");
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  frame = gtk_frame_new ("Multi-line Label");
  label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
                         "Third line");
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  frame = gtk_frame_new ("Left Justified Label");
  label = gtk_label_new ("This is a Left-Justified\n" \
                         "Multi-line label.\nThird      line");
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  frame = gtk_frame_new ("Right Justified Label");
  label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
                         "Fourth line, (j/k)");
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);

  vbox = gtk_vbox_new (FALSE, 5);
  gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  frame = gtk_frame_new ("Line wrapped label");
  label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
                         "should not be taking up the entire             " /* big space to test spacing */\
                         "width allocated to it, but automatically " \
                         "wraps the words to fit.  " \
                         "The time has come, for all good men, to come to " \
                         "the aid of their party.  " \
                         "The sixth sheik's six sheep's sick.\n" \
                         "     It supports multiple paragraphs correctly, " \
                         "and  correctly   adds "\
                         "many          extra  spaces. ");
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  frame = gtk_frame_new ("Filled, wrapped label");
  label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
                         "It should be taking "\
                         "up the entire              width allocated to it.  " \
                         "Here is a sentence to prove "\
                         "my point.  Here is another sentence. "\
                         "Here comes the sun, do de do de do.\n"\
                         "    This is a new paragraph.\n"\
                         "    This is another newer, longer, better " \
                         "paragraph.  It is coming to an end, "\
                         "unfortunately.");
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  frame = gtk_frame_new ("Underlined label");
  label = gtk_label_new ("This label is underlined!\n"
                         "This one is underlined in quite a funky fashion");
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
  gtk_label_set_pattern (GTK_LABEL (label),
                         "_________________________ _ _________ _ ______     __ _______ ___");
  gtk_container_add (GTK_CONTAINER (frame), label);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  
  gtk_widget_show_all (window);

  gtk_main ();
  
  return 0;
}

8.2 dz¼± µµ¿ò¸»(tooltip widget)

¸¶¿ì½ºÆ÷ÀÎÅ͸¦ ¾î¶² ¹öÆ°À̳ª ´Ù¸¥ widget À§¿¡ ¸î ÃÊ ¸Ó¹«¸£°Ô Çϸé ÀÛÀº ÅؽºÆ® ¹®ÀÚ¿­ÀÌ Æ¢¾î³ª¿À´Â °æ¿ì°¡ ÀÖ´Ù. ÀÌ°ÍÀº °£´ÜÇÑ °ÍÀ̸ç, ±×·¡¼­ ¿©±â¼­ ¿¹Á¦¾øÀÌ ¼³¸íÇÏ°Ú´Ù. ½ÇÁ¦·Î Äڵ带 º¸°í½Í´Ù¸é GDK¿Í ÇÔ²² ¹èÆ÷µÇ´Â testgtk.c ÇÁ·Î±×·¥À» ÂüÁ¶Ç϶ó.

¶óº§ µî ¾î¶² widget¿¡´Â ÀÌ tooltipÀÌ ¾²ÀÌÁö ¾Ê´Â´Ù.

¿ì¸®°¡ óÀ½ ÀÌ¿ëÇÒ ÇÔ¼ö´Â »õ·Î¿î tooltipÀ» ¸¸µå´Â °ÍÀÌ´Ù. ÀÌ°ÍÀº ÁÖ¾îÁø ÇÔ¼ö¿¡¼­ Çѹø¸¸ ÇØÁÖ¸é µÈ´Ù. ÀÌ ÇÔ¼ö°¡ ¸®ÅÏÇÏ´Â GtkTooltipÀº ´ÙÁßÀÇ tooltipµéÀ» ¸¸µå´Âµ¥µµ ÀÌ¿ëµÉ ¼ö ÀÖ´Ù.

GtkTooltips *gtk_tooltips_new( void );

ÀÏ´Ü »õ·Î¿î tooltip°ú ±×°ÍÀ» »ç¿ëÇÒ widgetÀ» ¸¸µé¾úÀ¸¸é, ±×°ÍÀ» ¼¼ÆÃÇϱâ À§ÇØ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇ϶ó.

void gtk_tooltips_set_tip( GtkTooltips *tooltips,
                           GtkWidget   *widget,
                           const gchar *tip_text,
                           const gchar *tip_private );

ù¹ø° ÀÎÀÚ´Â ¿ì¸®°¡ ¸¸µç tooltipÀÌ°í, ´ÙÀ½Àº ÀÌ tooltipÀ» Æ÷ÇÔÇÏ°Ô µÉ widgetÀÌ´Ù. ¼¼¹ø° ÀÎÀÚÀÎ ÅؽºÆ®´Â ¿ì¸®°¡ tooltip¿¡¼­ ¸»ÇÏ°íÀÚ ÇÏ´Â °ÍÀÌ´Ù. ¸¶Áö¸· ÀÎÀÚ´Â NULL·Î ÁÙ ¼ö ÀÖ´Ù.

ÀÌ°ÍÀº ªÀº ¿¹´Ù.

GtkTooltips *tooltips;
GtkWidget *button;
.
.
.
tooltips = gtk_tooltips_new ();
button = gtk_button_new_with_label ("button 1");
.
.
.
gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);

Tooltip¿¡ ¾²ÀÌ´Â ´Ù¸¥ ÇÔ¼öµéµµ ÀÖ´Ù. ¿©±â¼­ ±×µéÀ» °£´ÜÈ÷ ¼Ò°³ÇÏ°Ú´Ù.

void gtk_tooltips_enable( GtkTooltips *tooltips );

Disable·Î ¼³Á¤µÈ tooltipÀ» enableÇÑ´Ù.

void gtk_tooltips_disable( GtkTooltips *tooltips );

Enable·Î ¼³Á¤µÈ tooltipÀ» disableÇÑ´Ù.

Tooltip¿¡ °ü·ÃµÈ ÇÔ¼ö´Â ÀÌ°ÍÀÌ ÀüºÎ´Ù. ´õÀÌ»ó ¾Ë °Íµµ ¾ø´Ù. :)

8.3 ÁøÇื´ë(progress bar)

ÁøÇื´ë´Â ÀÛ¾÷ÀÇ »óȲÀ» ³ªÅ¸³»±â À§ÇØ ¾²ÀδÙ. ÀÌÁ¦ Äڵ带 º¸¸é ¾Ë°ÚÁö¸¸, ÀÌ°ÍÀº ²Ï °£´ÜÇÏ´Ù. ±×·¯³ª ¸ÕÀú »õ·Î¿î ÁøÇื´ë¸¦ ¸¸µé¾îÁÖ´Â ÇÔ¼ö¸¦ »ìÆì º¸´Â °ÍÀ¸·Î ½ÃÀÛÇÏÀÚ.

GtkWidget *gtk_progress_bar_new( void );

ÀÌÁ¦ ÁøÇื´ë°¡ ¸¸µé¾îÁ³°í ¿ì¸®´Â ±×°ÍÀ» ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.

void gtk_progress_bar_set_fraction ( GtkProgressBar *pbar,
                                     gdouble        fraction );

ù¹ø° ÀÎÀÚ´Â µ¿ÀÛ½Ãų ÁøÇื´ë°¡ µÇ°í, µÎ¹ø° ÀÎÀÚ´Â '¿Ï·áµÈ' ºÐ·®À» ³ªÅ¸³½´Ù. ÀÌ°ÍÀº ½ÇÁ¦ ¼ýÀÚ·Î 0ºÎÅÍ 1±îÁö°í, 0ºÎÅÍ 100ÆÛ¼¾Æ®¸¦ ÀǹÌÇÏ´Â °ÍÀÌ´Ù.

ÁøÇื´ë´Â º¸Åë ŸÀӾƿôÀ̳ª ¶Ç´Â ¸ÖƼŽºÅ·ÇÏ´Â Âø°¢À» ÀÏÀ¸Å°°Ô ÇÏ´Â ÇÔ¼öµé°ú ÇÔ²² ¾²ÀδÙ. (section ŸÀӾƿô, ±×¸®°í I/O¿Í Idle ÇÔ¼öµéÀ» ÂüÁ¶Ç϶ó.) ¸ðµç °æ¿ì¿¡ gtk_progress_bar_set_fraction() ¶Ç´Â gtk_progress_bar_pulse() ÇÔ¼ö°¡ µ¿ÀÏÇÑ ¹æ½ÄÀ¸·Î ¾²ÀÌ°Ô µÈ´Ù.

ÀÌ°ÍÀº ŸÀӾƿôÀ» ÀÌ¿ëÇØ ¾÷µ¥ÀÌÆ®µÇ´Â ÁøÇื´ë¸¦ º¸ÀÎ ¿¹Á¦´Ù. ÀÌ°ÍÀº ¶ÇÇÑ ÁøÇื´ë¸¦ ¸®¼Â, Áï ÃʱâÈ­ÇÏ´Â ¹æ¹ýµµ º¸¿©ÁÙ °ÍÀÌ´Ù.

/* progressbar.c */

#include <gtk/gtk.h>

typedef struct _ProgressData {
  GtkWidget *window;
  GtkWidget *pbar;
  int timer;
  gboolean activity_mode;
} ProgressData;

/* ÀÌ ÇÔ¼ö´Â ÁøÇื´ë¸¦ Áõ°¡½ÃÅ°°í ¾÷µ¥ÀÌÆ®ÇÑ´Ù. */
static gboolean progress_timeout( gpointer data )
{
  ProgressData *pdata = (ProgressData *)data;
  gdouble new_val;

  if (pdata->activity_mode) 
    gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
  else 
    {
      /* Calculate the value of the progress bar using the
       * value range set in the adjustment object */

      
      new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
      
      if (new_val > 1.0)
        new_val = 0.0;
      
      /* Set the new value */
      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
    }
  
  /* As this is a timeout function, return TRUE so that it
   * continues to get called */
  return TRUE;
} 

/* Callback that toggles the text display within the progress bar trough */
static void toggle_show_text( GtkWidget    *widget,
                              ProgressData *pdata )
{
  const gchar *text;
  
  text = gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata->pbar));
  if (text && *text)
    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar), "");
  else 
    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar), "some text");
}

/* Callback that toggles the activity mode of the progress bar */
static void toggle_activity_mode( GtkWidget    *widget,
                                  ProgressData *pdata )
{
  pdata->activity_mode = !pdata->activity_mode;
  if (pdata->activity_mode) 
      gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
  else
      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), 0.0);
}

/* Callback that toggles the orientation of the progress bar */
static void toggle_orientation( GtkWidget    *widget,
                                ProgressData *pdata )
{
  switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata->pbar))) {
  case GTK_PROGRESS_LEFT_TO_RIGHT:
    gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar), 
                                      GTK_PROGRESS_RIGHT_TO_LEFT);
    break;
  case GTK_PROGRESS_RIGHT_TO_LEFT:
    gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar), 
                                      GTK_PROGRESS_LEFT_TO_RIGHT);
    break;
  default:;
    /* do nothing */
  }
}

/* Clean up allocated memory and remove the timer */
static void destroy_progress( GtkWidget    *widget,
                              ProgressData *pdata)
{
    g_source_remove (pdata->timer);
    pdata->timer = 0;
    pdata->window = NULL;
    g_free (pdata);
    gtk_main_quit ();
}

int main( int   argc,
          char *argv[])
{
    ProgressData *pdata;
    GtkWidget *align;
    GtkWidget *separator;
    GtkWidget *table;
    GtkWidget *button;
    GtkWidget *check;
    GtkWidget *vbox;

    gtk_init (, );

    /* Allocate memory for the data that is passed to the callbacks */
    pdata = g_malloc (sizeof (ProgressData));

    pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);

    g_signal_connect (pdata->window, "destroy",
                      G_CALLBACK (destroy_progress),
                      (gpointer) pdata);
    gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
    gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
    gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
    gtk_widget_show (vbox);

    /* Create a centering alignment object */
    align = gtk_alignment_new (0.5, 0.5, 0, 0);
    gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
    gtk_widget_show (align);

    /* »õ·Î¿î ÁøÇื´ë¸¦ ¸¸µç´Ù */
    pdata->pbar = gtk_progress_bar_new ();
    pdata->activity_mode = FALSE;

    gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
    gtk_widget_show (pdata->pbar);

    /* ÁøÇื´ëÀÇ ÀÚµ¿ ¾÷µ¥ÀÌÆ®¸¦ À§ÇÑ timeoutÀ» ¼³Á¤ÇÑ´Ù. */
    pdata->timer = g_timeout_add (100, progress_timeout, pdata);

    separator = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
    gtk_widget_show (separator);

    /* rows, columns, homogeneous */
    table = gtk_table_new (2, 3, FALSE);
    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
    gtk_widget_show (table);

    /* Add a check button to select displaying of the trough text */
    check = gtk_check_button_new_with_label ("Show text");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_show_text),
                      pdata);
    gtk_widget_show (check);

    /* Add a check button to toggle activity mode */
    check = gtk_check_button_new_with_label ("Activity mode");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_activity_mode),
                      pdata);
    gtk_widget_show (check);

    /* Add a check button to toggle orientation */
    check = gtk_check_button_new_with_label ("Right to Left");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_orientation),
                      pdata);
    gtk_widget_show (check);

    /* Add a button to exit the program */
    button = gtk_button_new_with_label ("close");
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              pdata->window);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

    /* This makes it so the button is the default. */
    gtk_widget_set_can_default (button, TRUE);

    /* This grabs this button to be the default button. Simply hitting
     * the "Enter" key will cause this button to activate. */
    gtk_widget_grab_default (button);
    gtk_widget_show (button);

    gtk_widget_show (pdata->window);

    gtk_main ();
    
    return 0;
}

8.4 ´ëÈ­»óÀÚ

´ëÈ­»óÀÚ widgetÀº ¸Å¿ì °£´ÜÇÑ °ÍÀε¥, ½ÇÁ¦·Î ÀÌ°ÍÀº ¸î°¡Áö°¡ ¹Ì¸® ÆÐÅ·µÇ¾î ÀÖ´Â ÇϳªÀÇ À©µµÀÏ »ÓÀÌ´Ù. Dialog¸¦ À§ÇÑ ±¸Á¶Ã¼´Â ÀÌ°ÍÀÌ´Ù.

struct GtkDialog
{
      GtkWindow window;
    
      GtkWidget *vbox;
      GtkWidget *action_area;
};

º¸´Ù½ÃÇÇ ÀÌ°ÍÀº ´Ü¼øÈ÷ À©µµ¸¦ ¸¸µé°í, ±×¸®°í´Â vbox¸¦ ¸Ç À§·Î ÆÐÅ·ÇÏ°í, ´ÙÀ½À¸·Î separator¸¦, ±×¸®°í ³ª¼­ "action_area"¸¦ À§ÇÑ hbox¸¦ ÆÐÅ·ÇÑ´Ù.

´ëÈ­»óÀÚwidgetÀº »ç¿ëÀÚ¿¡°Ô Æ˾÷ ¸Þ½ÃÁö¸¦ º¸À̰ųª ÇÏ´Â µîÀÇ ¸ñÀûÀ¸·Î ¾²ÀÏ ¼ö ÀÖ´Ù. ´ëÈ­ »óÀÚ¸¦ »ý¼ºÇÏ´Â ÇÔ¼ö´Â µÎ°¡Áö°¡ ÀÖ´Ù.

GtkWidget *gtk_dialog_new( void );

GtkWidget *gtk_dialog_new_with_buttons( const gchar    *title,
                                        GtkWindow      *parent,
                                        GtkDialogFlags  flags, 
                                        const gchar    *first_button_text,
                                        ... );

ÀÌ°ÍÀº ´ëÈ­»óÀÚ¸¦ ¸¸µé °ÍÀÌ°í, ¾î¶»°Ô ÀÌ¿ëÇÒÁö´Â °¢ÀÚ¿¡°Ô ´Þ·ÁÀÖ´Ù. ¿ì¸®´Â ÀÌ·± ½ÄÀ¸·Î Çؼ­ action_area ¾È¿¡ ¹öÆ°À» ÆÐÅ·ÇÒ ¼ö ÀÖ´Ù.

    button = ...
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
                        button, TRUE, TRUE, 0);
    gtk_widget_show (button);

±×¸®°í ¿ì¸®´Â ÆÐÅ·¿¡ ÀÇÇÏ¿© vbox ¿µ¿ª¿¡ ¶óº§ µîÀ» Ãß°¡ÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡¿Í °°ÀÌ Çغ¸ÀÚ.

    label = gtk_label_new ("Dialogs are groovy");
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
                        label, TRUE, TRUE, 0);
    gtk_widget_show (label);

´ëÈ­»óÀÚ¸¦ ÀÌ¿ëÇÑ ¿¹Á¦¿¡¼­Ã³·³, ¿ì¸®´Â action_area¿¡ Cancel°ú OkÀÇ µÎ ¹öÆ°À», ±×¸®°í vbox¿µ¿ª¿£ »ç¿ëÀÚ¿¡°Ô ¹°¾îº¸°Å³ª ¿¡·¯¸Þ½ÃÁö¸¦ ³»°Å³ª ÇÏ´Â ¸ñÀûÀÇ ¶óº§À» ¸¸µé ¼ö ÀÖÀ» °ÍÀÌ´Ù. ±×¸®°í ³ª¼­ »ç¿ëÀÚÀÇ ¼±Åÿ¡ µû¶ó ÀÛµ¿Çϵµ·Ï ¹öÆ° °¢°¢¿¡ ¼­·Î ´Ù¸¥ ½Ã±×³ÎÀ» ¼³Á¤ÇØ µÑ ¼ö ÀÖ´Ù.

8.5 ·ê·¯(ruler)

·ê·¯ widgetÀº ÁÖ¾îÁø ÇÑ À©µµ¿¡¼­ ¸¶¿ì½º Æ÷ÀÎÅÍÀÇ À§Ä¡¸¦ °¡¸®Å°´Âµ¥ ¾²ÀδÙ. À©µµ´Â ÆøÀ» °¡·ÎÁö¸£´Â ¼öÆò ·ê·¯¿Í ³ôÀ̸¦ °¡·ÎÁö¸£´Â ¼öÁ÷·ê·¯¸¦ °¡Áú ¼ö ÀÖ´Ù. ·ê·¯ À§ÀÇ Á¶±×¸¸ »ï°¢Çü Ç¥½Ã±â(indicator)°¡ ·ê·¯¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÇ Á¤È®ÇÑ À§Ä¡¸¦ º¸¿©ÁØ´Ù.

·ê·¯´Â ¹Ýµå½Ã ¹Ì¸® ¸ÕÀú ¸¸µé¾îÁ®¾ß¸¸ ÇÑ´Ù. ¼öÆò ¹× ¼öÁ÷ ·ê·¯´Â ´ÙÀ½ ÇÔ¼öµéÀ» ÀÌ¿ëÇؼ­ ¸¸µé¾îÁø´Ù.

GtkWidget *gtk_hruler_new( void );    /* ¼öÆò ·ê·¯ */
GtkWidget *gtk_vruler_new( void );    /* ¼öÁ÷ ·ê·¯ */

·ê·¯°¡ Çѹø ¸¸µé¾îÁö¸é ÃøÁ¤´ÜÀ§¸¦ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù. ·ê·¯ÀÇ ÃøÁ¤´ÜÀ§´Â GTK_PIXELS³ª GTK_INCHES, GTK_CENTIMETERS ÁßÀÇ Çϳª°¡ µÈ´Ù.

void gtk_ruler_set_metric( GtkRuler      *ruler,
                           GtkMetricType  metric );

±âº» ¼³Á¤ ´ÜÀ§´Â GTK_PIXELSÀÌ´Ù.

   gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );

¶Ç´Ù¸¥ Áß¿äÇÑ ·ê·¯ÀÇ Æ¯¼ºÀº ¾î¶»°Ô Å©±â ´ÜÀ§¸¦ ³ªÅ¸³»´À³Ä ÇÏ´Â Á¡°ú Ç¥½Ã±â°¡ óÀ½ ¾îµð¿¡ ³õÀ̳ÄÇÏ´Â Á¡ÀÌ´Ù. À̵éÀº ´ÙÀ½ ÇÔ¼ö·Î °áÁ¤ÇÑ´Ù.

void gtk_ruler_set_range( GtkRuler *ruler,
                          gdouble   lower,
                          gdouble   upper,
                          gdouble   position,
                          gdouble   max_size );

ÀÎÀÚ lower¿Í upper´Â ·ê·¯ÀÇ ¹üÀ§¸¦ Á¤ÀÇÇÏ°í max_size´Â Ãâ·Â °¡´ÉÇÑ °¡Àå Å« ¼ö¸¦ ¼³Á¤ÇÑ´Ù. PositionÀº ·ê·¯ ³»ÀÇ Ç¥½Ã±â Ãʱâ À§Ä¡ÀÌ´Ù.

800 Çȼ¿ÀÇ ¼öÁ÷ ·ê·¯´Â ÀÌ·¸°Ô µÈ´Ù.

gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);

0ºÎÅÍ 800±îÁö ¸Å 100 Çȼ¿¸¶´Ù Ç¥Áö(marking)°¡ Ãâ·ÂµÉ °ÍÀÌ´Ù. ¸¸ÀÏ ·ê·¯ÀÇ ¹üÀ§¸¦ 7ºÎÅÍ 16À¸·Î ¹Ù²Ù·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù.

gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);

·ê·¯ÀÇ Ç¥½Ã±â´Â Æ÷ÀÎÅÍÀÇ »ó´ëÀûÀÎ À§Ä¡¸¦ °¡¸®Å°´Â Á¶±×¸¸ »ï°¢Çü Ç¥ÁöÀÌ´Ù. ¸¸ÀÏ ·ê·¯°¡ ¸¶¿ì½º Æ÷ÀÎÅ͸¦ µû¸£°Ô ÇÏ°í ½Í´Ù¸é motion_notify_event ½Ã±×³ÎÀÌ ·ê·¯ÀÇ motion_notify_event method¿Í ¿¬°áµÇ¾î¾ß¸¸ ÇÑ´Ù. ƯÁ¤ À©µµ ¿µ¿ª ³»ÀÇ ¸ðµç ¸¶¿ì½º ¿òÁ÷ÀÓÀ» µû¸£°Ô Çϱâ À§ÇØ ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù.

#define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)->x

    g_signal_connect_swapped (area, "motion_notify_event",
           G_CALLBACK (EVENT_METHOD (ruler, motion_notify_event)),
           ruler);

´ÙÀ½ ¿¹Á¦´Â ¼öÆò ·ê·¯¸¦ À§¿¡ ¼öÁ÷ ·ê·¯¸¦ ¿ÞÂÊ¿¡ °¡Áø drawing area¸¦ ¸¸µç´Ù. ÀÌ drawing area´Â 600 Çȼ¿ÀÇ Æø°ú 400 Çȼ¿ÀÇ ³ôÀ̸¦ °¡Áø´Ù. ¼öÆò ·ê·¯´Â 7ºÎÅÍ 13ÀÇ ¹üÀ§¿¡ ¸Å 100 Çȼ¿¸¶´Ù Ç¥Áö¸¦ ÇÏ°í ¼öÁ÷ ·ç·¯´Â 0ºÎÅÍ 400ÀÇ ¹üÀ§¿¡ ¸¶Âù°¡Áö·Î ¸Å 100 Çȼ¿¸¶´Ù Ç¥Áö¸¦ ÇÑ´Ù. ·ê·¯µé°ú drawing areaÀÇ À§Ä¡ ¼³Á¤Àº Å×À̺íÀ» »ç¿ëÇÑ´Ù.

/* rulers.c */

#include <gtk/gtk.h>

#define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x

#define XSIZE  600
#define YSIZE  400

/* ´Ý±â ¹öÆ°(close button)ÀÌ ´­·¯Áö¸é ÀÌ ÇÔ¼ö°¡ ºÒ¸°´Ù.
 */
static gboolean close_application( GtkWidget *widget,
                                   GdkEvent  *event,
                                   gpointer   data )
{
    gtk_main_quit ();
    return FALSE;
}


/* ¸ÞÀÎ ÇÔ¼ö
 */
int main( int   argc,
          char *argv[] ) {
    GtkWidget *window, *table, *area, *hrule, *vrule;

    /* gtk¸¦ ÃʱâÈ­ÇÏ°í ¸ÞÀÎ À©µµ¸¦ ¸¸µç´Ù.*/
    gtk_init( &argc, &argv );

    window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (close_application), NULL);
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* ·ê·¯¿Í drawing area¸¦ ³õÀº Å×À̺íÀ» ¸¸µç´Ù */
    table = gtk_table_new( 3, 2, FALSE );
    gtk_container_add( GTK_CONTAINER(window), table );

    area = gtk_drawing_area_new();
    gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
    gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
                      GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
    gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );

    /* ¼öÆò ·ê·¯´Â °¡Àå À§¿¡ ³õÀδÙ.  ¸¶¿ì½º°¡ drawing area À§¸¦ ¿òÁ÷À̸é,
       motion_notify_event °¡ ·ê·¯ÀÇ ÀûÀýÇÑ À̺¥Æ® Çڵ鷯¿¡°Ô Àü´ÞµÈ´Ù.
     */
    hrule = gtk_hruler_new();
    gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
    gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
    g_signal_connect_swapped (area, "motion_notify_event",
                              G_CALLBACK (EVENT_METHOD (hrule, motion_notify_event)),
                              hrule);
    /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
    gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
                      GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
    
    /* ¼öÁ÷ ·ê·¯´Â Á¦ÀÏ ¿ÞÂÊ¿¡ ³õÀδÙ.  ¸¶¿ì½º°¡ drawing area À§¸¦ ¿òÁ÷À̸é,,
       motion_notify_event °¡ ·ê·¯ÀÇ ÀûÀýÇÑ À̺¥Æ® Çڵ鷯¿¡°Ô Àü´ÞµÈ´Ù.
     */
    vrule = gtk_vruler_new();
    gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
    gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
    g_signal_connect_swapped (area, "motion_notify_event",
                              G_CALLBACK (EVENT_METHOD (vrule, motion_notify_event)),
                              vrule);
    gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
                      GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );

    /* ÀÌÁ¦ ¸ðµç °ÍÀ» º¸¿©ÁØ´Ù */
    gtk_widget_show( area );
    gtk_widget_show( hrule );
    gtk_widget_show( vrule );
    gtk_widget_show( table );
    gtk_widget_show( window );
    gtk_main();

    return 0;
}

8.6 »óÅÂÇ¥½ÃÁÙ(statusbar)

»óÅÂÇ¥½ÃÁÙÀº ÅؽºÆ® ¸Þ½ÃÁö¸¦ º¸¿©Áִµ¥ ¾²ÀÌ´Â °£´ÜÇÑ widgetÀÌ´Ù. ÀÌ widgetÀº ÅؽºÆ® ¸Þ½ÃÁöµéÀ» ½ºÅÿ¡ º¸°üÇÑ´Ù. µû¶ó¼­ ÇöÀçÀÇ ¸Þ½ÃÁö¸¦ ²¨³»¸é ¹Ù·Î ÀÌÀüÀÇ ¸Þ½ÃÁö¸¦ ´Ù½Ã º¸¿©ÁÖ°Ô µÈ´Ù.

ÇÑ ¾îÇø®ÄÉÀ̼ÇÀÇ ¿©·¯ ºÎºÐµéÀÌ ¸Þ½ÃÁö¸¦ Ç¥½ÃÇϴµ¥ °°Àº »óÅÂÇ¥½ÃÁÙÀ» »ç¿ëÇؾßÇÏ´Â °æ¿ì, »óÅÂÇ¥½ÃÁÙ widgetÀº ¿©·¯ '»ç¿ëÀÚ'µéÀ» ±¸ºÐÇϴµ¥ ¾²ÀÌ´Â Context Identifier¸¦ ¹ßÇàÇÑ´Ù. ¾î¶² context¸¦ °¡Á³´À³Ä¿¡ »ó°ü¾øÀÌ ½ºÅà Á¦ÀÏ À§ÀÇ ¸Þ½ÃÁö°¡ º¸¿©Áø´Ù. ¸Þ½ÃÁöµéÀº Context IdentifierÀÇ ¼ø¼­°¡ ¾Æ´Ï¶ó ³ªÁß¿¡ µé¾î°£ °ÍÀÌ ¸ÕÀú ³ª¿À´Â ¼ø¼­·Î ½ºÅÿ¡ ½×ÀδÙ.

»óÅÂÇ¥½ÃÁÙÀº ´ÙÀ½ ÇÔ¼ö¸¦ ÅëÇØ ¸¸µé¾îÁø´Ù.

GtkWidget *gtk_statusbar_new( void );

»õ·Î¿î Context Identifier´Â °£´ÜÇÑ context¿¡ °üÇÑ ¼³¸í°ú ÇÔ²² ´ÙÀ½ ÇÔ¼ö¸¦ È£ÃâÇÏ¿© ¾òÀ» ¼ö ÀÖ´Ù.

guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
                                    const gchar  *context_description );

»óÅÂÇ¥½ÃÁÙÀ» ´Ù·ç´Â ´ÙÀ½°ú °°Àº ÇÔ¼öµéÀÌ ÀÖ´Ù.

guint gtk_statusbar_push( GtkStatusbar *statusbar,
                          guint         context_id,
                          const gchar  *text );

void gtk_statusbar_pop( GtkStatusbar *statusbar)
                        guint         context_id );

void gtk_statusbar_remove( GtkStatusbar *statusbar,
                           guint         context_id,
                           guint         message_id ); 

¸ÕÀú gtk_statusbar_push´Â »óÅÂÇ¥½ÃÁÙ¿¡ »õ·Î¿î ¸Þ½ÃÁö¸¦ Ãß°¡Çϴµ¥ ¾²ÀδÙ. ÀÌ ÇÔ¼ö´Â ³ªÁß¿¡ gtk_statusbar_remove¸¦ È£ÃâÇϴµ¥ ¾²ÀÏ ¼ö ÀÖ´Â Message Identifier¸¦ ¸®ÅÏÇÑ´Ù. gtk_statusbar_remove´Â ÁÖ¾îÁø Message¿Í Context IdentifierÀÇ ¸Þ½ÃÁö¸¦ »óÅÂÇ¥½ÃÁÙ¿¡¼­ Á¦°ÅÇÑ´Ù.

gtk_statusbar_popÀº ÁÖ¾îÁø Context IdentifierÀÇ ½ºÅà Á¦ÀÏ À§ ¸Þ½ÃÁö¸¦ ²¨³» »èÁ¦ÇÑ´Ù.

´ÙÀ½ ¿¹Á¦´Â ¹öÆ° 2°³¿Í »óÅÂÇ¥½ÃÁÙ Çϳª¸¦ ¸¸µç´Ù. º­Æ° Çϳª´Â »óÅÂÇ¥½ÃÁÙ¿¡ »õ ¸Þ½ÃÁö¸¦ ³Ö°í ³ª¸ÓÁö ´Ù¸¥ ¹öÆ°Àº ¸¶Áö¸·À¸·Î ³Ö¾îÁø ¸Þ½ÃÁö¸¦ Á¦°ÅÇÑ´Ù.

/* statusbar.c */

#include <stdlib.h>
#include <gtk/gtk.h>
#include <glib.h>

GtkWidget *status_bar;

static void push_item( GtkWidget *widget,
                       gpointer   data )
{
  static int count = 1;
  gchar *buff;

  buff = g_strdup_printf ("Item %d", count++);
  gtk_statusbar_push (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data), buff);
  g_free (buff);
}

static void pop_item( GtkWidget *widget,
                      gpointer   data )
{
  gtk_statusbar_pop (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data));
}

int main( int   argc,
          char *argv[] )
{
    GtkWidget *window;
    GtkWidget *vbox;
    GtkWidget *button;

    int context_id;

    gtk_init (&argc, &argv);

    /* »õ À©µµ¸¦ Çϳª ¸¸µç´Ù */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
    gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
    g_signal_connect (window, "delete-event",
                      G_CALLBACK (exit), NULL);
 
    vbox = gtk_vbox_new(FALSE, 1);
    gtk_container_add(GTK_CONTAINER(window), vbox);
    gtk_widget_show(vbox);
          
    status_bar = gtk_statusbar_new();      
    gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
    gtk_widget_show (status_bar);

    context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");

    button = gtk_button_new_with_label("push item");
    g_signal_connect (button, "clicked",
                      G_CALLBACK (push_item), GINT_TO_POINTER (context_id));
    gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
    gtk_widget_show(button);              

    button = gtk_button_new_with_label("pop last item");
    g_signal_connect (button, "clicked",
                      G_CALLBACK (pop_item), GINT_TO_POINTER (context_id));
    gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
    gtk_widget_show(button);              

    /* ´Ù¸¥ ¸ðµç °ÍµéÀÌ Çѹø¿¡ ¸ðµÎ ´Ù º¸À̵µ·Ï Çϱâ À§Çؼ­
     * Ç×»ó À©µµ¸¦ Á¦ÀÏ ¸¶Áö¸·¿¡ º¸¿©ÁØ´Ù. */
    gtk_widget_show(window);

    gtk_main ();

    return 0;
}

8.7 ÅؽºÆ® ÀÔ·Â(text entry)

ÅؽºÆ® ÀÔ·Â widgetÀº ÇÑÁÙÂ¥¸® ÅؽºÆ® »óÀÚ ¾È¿¡ ¹®ÀÚ¸¦ ŸÀÌÇÁÇØ ³Ö°Å³ª ¶Ç´Â ±×³É º¸¿©ÁÙ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÅؽºÆ®´Â Çö ÀÔ·Â widgetÀÇ ³»¿ëÀ» Ãß°¡Çϰųª ¶Ç´Â ¿ÏÀüÈ÷ ´ëüÇÏ´Â ÇÔ¼ö È£Ãâµé¿¡ ÀÇÇØ °áÁ¤µÈ´Ù.

ÅؽºÆ® ÀÔ·Â widgetÀ» ¸¸µå´Âµ¥´Â ´ÙÀ½ µÎ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.

GtkWidget *gtk_entry_new( void );

óÀ½ °ÍÀº ´Ü¼øÈ÷ »õ·Î¿î ÀÔ·Â widgetÀ» Çϳª ¸¸µç´Ù. ±×¿¡ ¹ÝÇØ µÎ¹ø° °ÍÀº ÆíÁý°¡´ÉÇÑ ÅؽºÆ®ÀÇ ±æÀÌ Á¦ÇÑÀ» °¡Áø ÀÔ·Â widgetÀ» ¸¸µç´Ù.

´ÙÀ½ ÇÔ¼ö´Â Çö ÀÔ·ÂÀÇ ÅؽºÆ®¸¦ º¯°æÇÑ´Ù.

void gtk_entry_set_text( GtkEntry    *entry,
                         const gchar *text );

ÀÔ·Â widgetÀÇ ³»¿ëÀº ´ÙÀ½ ÇÔ¼ö È£Ãâ¿¡ ÀÇÇؼ­ ¾Ë ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ³ªÁß¿¡ ¼³¸íÇÒ callback ÇÔ¼ö ¾È¿¡¼­ »ç¿ëÇÏ´Â °ÍÀÌ À¯¿ëÇÏ´Ù.

const gchar *gtk_entry_get_text( GtkEntry *entry );

¸¸ÀÏ ÀÔ·ÂµÈ ³»¿ëÀÌ Å¸ÀÌÇο¡ ÀÇÇؼ­ º¯°æµÇ´Â °ÍÀ» ¿øÇÏÁö ¾Ê´Â´Ù¸é ÆíÁýÀÌ ºÒ°¡´ÉÇϵµ·Ï »óŸ¦ ¹Ù²Ü ¼ö ÀÖ´Ù.

void gtk_editable_set_editable( GtkEditable *entry,
                                gboolean     editable );

ÀÌ ÇÔ¼öÀÇ editable ÀÎÀÚ¿¡ TRUE³ª FALSE¸¦ ÁÖ¾î ÀÔ·Â widgetÀÌ ÆíÁý °¡´ÉÇÏ°Ô µÇ°Å³ª ¶Ç´Â °¡´ÉÇÏÁö ¾Êµµ·Ï º¯°æÇÒ ¼ö ÀÖ´Ù.

¸¸¾à Æнº¿öµå¸¦ ÀÔ·ÂÇÒ ¶§Ã³·³ ÀÔ·ÂÇÏ´Â ÅؽºÆ®°¡ º¸ÀÌÁö ¾Ê¾Æ¾ß ÇÑ´Ù¸é boolean flag¸¦ °®´Â ´ÙÀ½ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.

void gtk_entry_set_visibility( GtkEntry *entry,
                               gboolean  visible );

´ÙÀ½ ÇÔ¼ö¸¦ ½á¼­ ÅؽºÆ®ÀÇ ÀÏÁ¤ ºÎºÐÀ» ¼±ÅÃ(selected)µÇµµ·Ï ¸¸µé ¼ö ÀÖ´Ù. ÀÌ ±â´ÉÀº ¹Ì¸® ±âº» ÅؽºÆ®¸¦ Á¤ÇØ Ãâ·ÂÇÏ°í À̸¦ »ç¿ëÀÚ°¡ »õ·Î¿î ÀÔ·ÂÀ» À§Çؼ­ °£´ÜÈ÷ Áö¿ï ¼ö ÀÖ°Ô Çϴµ¥ ÀÚÁÖ ¾²ÀδÙ.

void gtk_editable_select_region( GtkEditable *entry,
                                 gint         start,
                                 gint         end );

¸¸¾à¿¡ »ç¿ëÀÚ°¡ ÅؽºÆ®¸¦ ÀÔ·ÂÇÏ´Â °ÍÀ» ¾Ë¾Æä°í ½Í´Ù¸é, activate³ª changed ½Ã±×³ÎÀ» ¿¬°áÇÒ ¼ö ÀÖ´Ù. Activate´Â »ç¿ëÀÚ°¡ ¿£ÅÍÅ°¸¦ ŸÀÌÇÁÇϸé, Changed´Â ÅؽºÆ®°¡ ÀüºÎ ´Ù¸¥ °ÍÀ¸·Î ¹Ù²î¸é ¹ß»ýÇÑ´Ù.(¸ðµç ¹®ÀÚ°¡ ÀԷµǾú°Å³ª Áö¿öÁ³À» ¶§ µî)

´ÙÀ½Àº ÅؽºÆ® ÀÔ·Â widgetÀÇ ÇÑ ¿¹ÀÌ´Ù.

/* entry.c */

#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>

static void enter_callback( GtkWidget *widget,
                            GtkWidget *entry )
{
  const gchar *entry_text;
  entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
  printf ("Entry contents: %s\n", entry_text);
}

static void entry_toggle_editable( GtkWidget *checkbutton,
                                   GtkWidget *entry )
{
  gtk_editable_set_editable (GTK_EDITABLE (entry),
                             GTK_TOGGLE_BUTTON (checkbutton)->active);
}

static void entry_toggle_visibility( GtkWidget *checkbutton,
                                     GtkWidget *entry )
{
  gtk_entry_set_visibility (GTK_ENTRY (entry),
                            GTK_TOGGLE_BUTTON (checkbutton)->active);
}

int main( int   argc,
          char *argv[] )
{
    GtkWidget *window;
    GtkWidget *vbox, *hbox;
    GtkWidget *entry;
    GtkWidget *button;
    GtkWidget *check;
    gint tmp_pos;

    gtk_init (, );

    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
    gtk_window_set_title (GTK_WINDOW (window), "GTK Entry");
    g_signal_connect (window, "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);
    g_signal_connect_swapped (window, "delete-event",
                              G_CALLBACK (gtk_widget_destroy), 
                              window);

    vbox = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), vbox);
    gtk_widget_show (vbox);

    entry = gtk_entry_new ();
    gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
    g_signal_connect (entry, "activate",
                      G_CALLBACK (enter_callback),
                      entry);
    gtk_entry_set_text (GTK_ENTRY (entry), "hello");
    tmp_pos = GTK_ENTRY (entry)->text_length;
    gtk_editable_insert_text (GTK_EDITABLE (entry), " world", -1, _pos);
    gtk_editable_select_region (GTK_EDITABLE (entry),
                                0, GTK_ENTRY (entry)->text_length);
    gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
    gtk_widget_show (entry);

    hbox = gtk_hbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (vbox), hbox);
    gtk_widget_show (hbox);
                                  
    check = gtk_check_button_new_with_label ("Editable");
    gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
    g_signal_connect (check, "toggled",
                      G_CALLBACK (entry_toggle_editable), entry);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
    gtk_widget_show (check);
    
    check = gtk_check_button_new_with_label ("Visible");
    gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
    g_signal_connect (check, "toggled",
                      G_CALLBACK (entry_toggle_visibility), entry);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
    gtk_widget_show (check);
                                   
    button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              window);
    gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
    gtk_widget_set_can_default (button, TRUE);
    gtk_widget_grab_default (button);
    gtk_widget_show (button);
    
    gtk_widget_show (window);

    gtk_main();

    return 0;
}

8.8 »ö ¼±ÅÃ(color selection)

»ö¼±Åà widgetÀº, »ç½Ç ÀüÇô ³î¶øÁö ¾Ê°ÚÁö¸¸, Á÷Á¢ »öÀ» ¼±ÅÃÇϴµ¥ ¾²ÀδÙ. ÀÌ º¹ÇÕÀûÀÎ widgetÀº »ç¿ëÀÚ·Î ÇÏ¿©±Ý RGB(Red, Green, Blue)¿Í HSV (Hue, Saturation, Value) ¼¼ ¿ä¼Ò¸¦ ÅëÇØ »öÀ» °í¸£°Ô ÇÑ´Ù. ÀÌ´Â ½½¶óÀÌ´õ³ª ÀÔ·ÂâÀ» ÀÌ¿ëÇؼ­ °¢ ¿ä¼Ò¿¡ ƯÁ¤ °ªÀ» ÁÖ°ÔÇϰųª ¶Ç´Â, hue-saturation wheel¿¡¼­ Á÷Á¢ »öÀ» ¼±ÅÃÇÏ°Ô ÇÔÀ¸·Î½á ÀÌ·ç¾îÁø´Ù. ÇÊ¿ä¿¡ µû¶ó¼­´Â »öÀÇ Åõ¸íµµµµ Á¤ÇØÁÙ ¼ö ÀÖ´Ù.

ÀÌ »ö¼±Åà widgetÀº ¿ÜºÎ¿¡¼­ gtk_color_selection_set_color()À» ÅëÇØ ÁöÁ¤Ç߰ųª ¶Ç´Â »ç¿ëÀÚ°¡ Á÷Á¢ ÇöÀç »öÀ» º¯°æÇÒ ¶§¸¶´Ù "color_changed"À̶ó´Â ´Ü ÇÑ°¡ÁöÀÇ ½Ã±×³Î¸¸À» ¹ß»ý½ÃŲ´Ù.

ÀÌ »ö¼±Åà widgetÀÌ ¿ì¸®¿¡°Ô ¹«¾ùÀ» ³Ñ°ÜÁÖ¾î¾ß ÇÏ´ÂÁö º¸ÀÚ. ÀÌ widgetÀº gtk_color_selection¿Í gtk_color_selection_dialogÀÇ µÎ ÇüÅ°¡ ÀÖ´Ù.

GtkWidget *gtk_color_selection_new(void);

´ë°³ ÀÌ ÇÔ¼ö¸¸À» Á÷Á¢ ¾µ ¼ö´Â ¾ø´Ù. ÀÌ°ÍÀº ³ªÁß¿¡ ¾îµò°¡·Î ¿¬°áÀ» ½ÃÄÑÁÖ¾î¾ß¸¸ ÇÏ´Â GtkColorSelection widgetÀ» ¸¸µé µû¸§ÀÌ´Ù. ÀÌ GtkColorSelection widgetÀº GtkVBox widget¿¡¼­ »ó¼ÓµÈ °ÍÀÌ´Ù.

 
GtkWidget *gtk_color_selection_dialog_new(const gchar *title);

´ë°³ ÀÌ ÇÔ¼ö¸¦ »ö¼±Åà widgetÀ» ¸¸µå´Â µ¥ »ç¿ëÇÑ´Ù. ÀÌ´Â GtkColorSelectionDialog¶ó´Â GtkDialog¿¡¼­ »ó¼ÓµÈ widgetÀ» ¸¸µç´Ù. ÀÌ widgetÀº GtkColorSelection, GtkHSeparator¿Í "Ok", "Cancel", "Help"ÀÇ ¹öÆ° ¼¼°³¸¦ °¡Áø GtkHBoxµéÀ» Æ÷ÇÔÇÑ GtkFrame widgetÀ¸·Î ÀÌ·ç¾îÁ®ÀÖ´Ù. GtkColorSelectionDialog structure¿¡¼­ "ok_button", "cancel_button", "help_button" widget¿¡ Á¢±ÙÇؼ­ ±× ¼¼ ¹öÆ°µéÀ» Á÷Á¢ ´Ù·ê ¼ö ÀÖ´Ù. (¿¹ : GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button)

void gtk_color_selection_set_update_policy(GtkColorSelection *colorsel, 
                                           GtkUpdateType policy);

ÀÌ ÇÔ¼ö´Â °»½Å Á¤Ã¥À» Á¤ÇÑ´Ù. ±âº» Á¤Ã¥Àº »ç¿ëÀÚ°¡ ¹«¾ùÀÌµç º¯°æÇÏ´Â ±×¶§¸¶´Ù ¹Ù·Î Áï½Ã ÇöÀçÀÇ »öÀ» °Å±â¿¡ µû¶ó ¹Ù²Ù´Â GTK_UPDATE_CONTINOUSÀÌ´Ù. ¼º´É¹®Á¦°¡ ¹ß»ýÇϸé GTK_UPDATE_DISCONTINOUS³ª GTK_UPDATE_DELAYED·Î ¹Ù²Ù¾î ÁÙ ¼ö ÀÖ´Ù.

void gtk_color_selection_set_opacity(GtkColorSelection *colorsel,
                                     gint use_opacity);
»ö¼±Åà widgetÀº »öÀÇ Åõ¸íµµ(¾ËÆÄä³ÎÀ̶ó°íµµ ¾Ë·ÁÁø)¸¦ Á¶Á¤ÇÏ´Â ±â´Éµµ Áö¿øÇÑ´Ù. ÀÌ ±â´ÉÀº ±âº» ¼³Á¤¿¡¼­´Â ²¨Á®ÀÖ´Ù. ÀÌ°ÍÀ» »ç¿ëÇÏ·Á¸é À§ÀÇ ÇÔ¼ö¸¦ use_opacity¸¦ TRUE·Î Çؼ­ È£ÃâÇÑ´Ù. ¸¶Âù°¡Áö·Î use_opacity¸¦ FALSE·Î Çؼ­ È£ÃâÇϸé Åõ¸íµµ Á¶Á¤ ±â´ÉÀÌ ²¨Áø´Ù.

void gtk_color_selection_set_color(GtkColorSelection *colorsel,
                                   gdouble *color);

»ö»ó array(gdouble)¿Í ÇÔ²² À§ ÇÔ¼ö¸¦ È£ÃâÇÏ¿© ¿ÜºÎ¿¡¼­ ÇöÀç »öÀ» ÁöÁ¤ÇØ ÁÙ ¼ö ÀÖ´Ù. ÀÌ arrayÀÇ ±æÀÌ´Â »ö Åõ¸íµµ Á¶Á¤ ±â´ÉÀ» Äѳõ¾Ò´ÂÁö ²¨³õ¾Ò´ÂÁö¿¡ µû¶ó ´Þ¶óÁø´Ù. À§Ä¡ 0Àº »¡°£»ö, 1Àº ³ì»ö, 2´Â ÆĶõ»öÀ̸ç 3Àº Åõ¸íµµÀÌ´Ù.(Åõ¸íµµ´Â ÀÌ ±â´ÉÀ» Äѳõ¾ÒÀ» ¶§¸¸ Àǹ̰¡ ÀÖ´Ù. ¾Õ¿¡¼­ ³ª¿Â gtk_color_selection_set_opacity()¿¡ ´ëÇÑ ºÎºÐÀ» º¸¶ó.) ¸ðµç °ªÀº 0.0°ú 1.0 »çÀÌ¿¡ ÀÖ´Ù.

void gtk_color_selection_get_color(GtkColorSelection *colorsel,
                                   gdouble *color);

¸¸ÀÏ 'color_changed" ½Ã±×³ÎÀ» ¹Þ¾ÒÀ» ¶§, ÇöÀç »öÀÌ ¾î¶² °ÍÀÌÁö ¾Ë°í ½Í´Ù¸é À§ÀÇ ÇÔ¼ö¸¦ »ç¿ëÇÏ¸é µÈ´Ù. Color´Â »ö arrayÀÌ´Ù. ÀÌ »ö array¿¡ ´ëÇÑ °ÍÀº gtk_color_selection_set_color() ÇÔ¼ö¿¡ ´ëÇÑ ºÎºÐÀ» º¸¶ó.

´ÙÀ½Àº GtkColorSelectionDialogÀ» »ç¿ëÇÏ´Â °£´ÜÇÑ ¿¹ÀÌ´Ù. ÀÌ ÇÁ·Î±×·¥Àº drawing area¸¦ °¡Áø À©µµ Çϳª¸¦ ¸¸µç´Ù. ÀÌ°ÍÀ» Ŭ¸¯Çϸé color selection dialog°¡ ¶á´Ù. À̸¦ Á¶Á¤Çؼ­ ¹è°æ»öÀ» ¹Ù²Ü ¼ö ÀÖ´Ù.

#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>

GtkWidget *colorseldlg = NULL;
GtkWidget *drawingarea = NULL;

/* »öÀÌ ¹Ù²î¸é ÀÌ ÇÔ¼ö¸¦ ºÎ¸¥´Ù. */

void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
{
  gdouble color[3];
  GdkColor gdk_color;
  GdkColormap *colormap;

  /* drawing areaÀÇ colormapÀ» ¾ò´Â´Ù */

  colormap = gdk_window_get_colormap (drawingarea->window);

  /* ÇöÀç »öÀ» ¾ò´Â´Ù */

  gtk_color_selection_get_color (colorsel,color);

  /* unsigned 16 bit Á¤¼ö(0..65535)·Î ¹Ù²ã¼­ GdkColor¿¡ ³Ö´Â´Ù  */

  gdk_color.red = (guint16)(color[0]*65535.0);
  gdk_color.green = (guint16)(color[1]*65535.0);
  gdk_color.blue = (guint16)(color[2]*65535.0);

  /* »öÀ» ÇÒ´çÇÑ´Ù */

  gdk_color_alloc (colormap, &gdk_color);

  /* À©µµÀÇ ¹è°æ»öÀ» Á¤ÇÑ´Ù */

  gdk_window_set_background (drawingarea->window, &gdk_color);

  /* À©µµ¸¦ Áö¿î´Ù */

  gdk_window_clear (drawingarea->window);
}

/* Drawingarea event handler */

gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
{
  gint handled = FALSE;
  GtkWidget *colorsel;

  /* ¹öÆ°ÀÌ ´­·¯Á³´ÂÁö È®ÀÎÇÑ´Ù */

  if (event->type == GDK_BUTTON_PRESS && colorseldlg == NULL)
    {
      /* Yes, we have an event and there's no colorseldlg yet! */

      handled = TRUE;

      /* color selection dialog¸¦ ¸¸µç´Ù */

      colorseldlg = gtk_color_selection_dialog_new("Select background color");

      /* GtkColorSelection widgetÀ» ±¸ÇÑ´Ù */

      colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;

      /* "color_changed" ½Ã±×³ÎÀ» widget¿¡ ¿¬°áÇÑ´Ù. */

      gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
        (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);

      /* color seclection dialog¸¦ º¸Àδ٠*/

      gtk_widget_show(colorseldlg);
    }

  return handled;
}

/* À©µµ¸¦ ´Ý°í Çڵ鷯¿¡¼­ ºüÁ®³ª°£´Ù */

void destroy_window (GtkWidget *widget, gpointer client_data)
{
  gtk_main_quit ();
}

/* Main */

gint main (gint argc, gchar *argv[])
{
  GtkWidget *window;

  /* ÅøŶÀ» ÃʱâÈ­ÇÏ°í gtk¿Í °ü·ÃµÈ ¸í·ÉÀÔ·Â ¿ä¼ÒµéÀ» ¾ø¾Ø´Ù. */

  gtk_init (&argc,&argv);

  /* toplevel À©µµ¸¦ ¸¸µé°í Á¦¸ñ°ú policy¸¦ Á¤ÇÑ´Ù */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
  gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);

  /* "delete"¿Í  "destroy" À̺¥Æ®¸¦ ¸¸³ª¸é Á¾·áÇÑ´Ù */

  gtk_signal_connect (GTK_OBJECT(window), "delete_event",
    (GtkSignalFunc)destroy_window, (gpointer)window);

  gtk_signal_connect (GTK_OBJECT(window), "destroy",
    (GtkSignalFunc)destroy_window, (gpointer)window);
  
  /* drawingarea¸¦ ¸¸µç µÚ, ±× Å©±â¸¦ Á¤ÇÏ°í ¹öÆ° À̺¥Æ®¿Í ¿¬°áÇÑ´Ù */

  drawingarea = gtk_drawing_area_new ();

  gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);

  gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);

  gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
    (GtkSignalFunc)area_event, (gpointer)drawingarea);
  
  /* drawingarea¸¦ ¸ÞÀÎ À©µµ¿¡ ºÙÀÌ°í µÑ ´Ù º¸¿©ÁØ´Ù. */

  gtk_container_add (GTK_CONTAINER(window), drawingarea);

  gtk_widget_show (drawingarea);
  gtk_widget_show (window);
  
  /* gtk main loop¿¡ µé¾î°£´Ù. (´Ù½Ã´Â µ¹¾Æ¿ÀÁö ¸øÇÑ´Ù.) */

  gtk_main ();

  /* ±î´Ù·Î¿î ÄÄÆÄÀÏ·¯µéÀ» ¸¸Á·½ÃŲ´Ù */

  return 0;
}

8.9 ÆÄÀÏ ¼±ÅÃ(file selection)

ÆÄÀϼ±Åà widgetÀº ÆÄÀÏ ´ëÈ­»óÀÚ¸¦ º¸ÀÌ´Â ºü¸£°í °£ÆíÇÑ °ÍÀÌ´Ù. ÀÌ°ÍÀº Ok, Cancel, Help ¹öÆ°À» °¡Áö°í ÀÖÀ¸¸ç, ÇÁ·Î±×·¡¹Ö ½Ã°£À» »ó´çÈ÷ ÁÙ¿©ÁØ´Ù.

»õ·Î¿î ÆÄÀϼ±Åà ¹Ú½º¸¦ ¸¸µé·Á¸é ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

GtkWidget* gtk_file_selection_new (gchar *title);

ÆÄÀÏÀ̸§À» ¼¼ÆÃÇϱâ À§Çؼ­ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void gtk_file_selection_set_filename (GtkFileSelection *filesel, gchar *filename);

»ç¿ëÀÚ°¡ Å°º¸µå ȤÀº ¸¶¿ì½º Ŭ¸¯À¸·Î ÀÔ·ÂÇÑ ÅؽºÆ®¸¦ Æ÷ÂøÇϱâ À§Çؼ­´Â ÀÌ ÇÔ¼ö¸¦ ¾´´Ù.

gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel);

ÆÄÀϼ±ÅÃwidget ³»ºÎ¿¡ Æ÷ÇÔµÈ widgetµé¿¡ ´ëÇÑ Æ÷ÀÎÅ͵鵵 ÀÖ´Ù. ±×µéÀº ´ÙÀ½°ú °°´Ù.

  • dir_list
  • file_list
  • selection_entry
  • selection_text
  • main_vbox
  • ok_button
  • cancel_button
  • help_button

¿ì¸®°¡ °¡Àå ¸¹ÀÌ ÀÌ¿ëÇÏ°Ô µÉ °ÍÀº ok_button, cancel_button, ±×¸®°í help_button Æ÷ÀÎÅÍ°¡ µÉ °ÍÀÌ´Ù.

ÀÌ°ÍÀº testgtk.c ¿¡¼­ ¹ßÃéÇÑ °ÍÀ» ¸ñÀû¿¡ ÀÇÇØ º¯ÇüÇÑ °ÍÀÌ´Ù. º¸¸é ¾Ë°ÚÁö¸¸, ¿©±â¼­´Â ÆÄÀϼ±ÅÃwidgetÀ» Çϳª ¸¸µé »ÓÀÌ´Ù. Help ¹öÆ°ÀÌ ½ºÅ©¸°¿¡ º¸ÀÌ°ÚÁö¸¸, ¾Æ¹«·± ½Ã±×³ÎÀÌ ¿¬°áµÇ¾î ÀÖÁö ¾ÊÀ¸¹Ç·Î ¾Æ¹« ±â´ÉÀÌ ¾øÀ» °ÍÀÌ´Ù.

#include <gtk/gtk.h>
/* filesel.c */

/* ¼±ÅÃµÈ ÆÄÀÏ À̸§À» ÃëÇؼ­ ±×°ÍÀ» ÄַܼΠÇÁ¸°Æ®ÇÑ´Ù. */
void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
{
    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
}

void destroy (GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
}

int main (int argc, char *argv[])
{
    GtkWidget *filew;

    gtk_init (&argc, &argv);

    /* ÆÄÀϼ±Åà widgetÀ» Çϳª ¸¸µç´Ù. */
    filew = gtk_file_selection_new ("File selection");

    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
                        (GtkSignalFunc) destroy, &filew);
    /* file_ok_sel ÇÔ¼ö·Î ok_buttonÀ» ¿¬°á½ÃŲ´Ù. */
    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
                        "clicked", (GtkSignalFunc) file_ok_sel, filew );

    /* gtk_widget_destroy ÇÔ¼ö·Î cancel_buttonÀ» ¿¬°á½ÃŲ´Ù. */
    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
                               "clicked", (GtkSignalFunc) gtk_widget_destroy,
                               GTK_OBJECT (filew));

    /* ÆÄÀÏÀ̸§À» ¼¼ÆÃÇÑ´Ù. */
    gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew),
                                     "penguin.png");

    gtk_widget_show(filew);
    gtk_main ();
    return 0;
}

9. ÄÁÅ×ÀÌ³Ê widget

9.1 ³ëÆ®ºÏ

³ëÆ®ºÏ widgetÀº ¼­·Î ¿À¹ö·¦µÇ¸ç ´Ù¸¥ Á¤º¸¸¦ °¡Áö°í ÀÖ´Â 'ÆäÀÌÁöµé'ÀÇ ¸ðÀÓÀÌ´Ù. ÀÌ·± widgetÀº ÃÖ±Ù GUI ÇÁ·Î±×·¡¹Ö¿¡¼­ ´õ ÀϹÝÈ­µÇ¾ú°í, È­¸é¿¡¼­ ºñ½ÁÇÏÁö¸¸ ±¸º°µÇ¾î¾ß ÇÒ Á¤º¸ ºí·°À» º¸ÀÌ´Â µ¥ ÁÁÀº ¹æ¹ýÀÌ´Ù.

¿ì¸®°¡ ¾Ë¾Æ¾ß ÇÒ Ã¹¹ø° ÇÔ¼ö´Â ¿¹»óÇÑ´ë·Î »õ·Î¿î ³ëÆ®ºÏ widgetÀ» ¸¸µå´Â °ÍÀÌ´Ù.

GtkWidget* gtk_notebook_new (void);

ÀÏ´Ü ³ëÆ®ºÏÀÌ ¸¸µé¾îÁö¸é, ±× ³ëÆ®ºÏ widgetÀ» ´Ù·ê 12°³ÀÇ ÇÔ¼ö°¡ ÀÖ´Ù. ±×µé ÇϳªÇϳª¸¦ »ìÆ캸ÀÚ.

¿ì¸®°¡ ¸ÕÀú ÇÒ ÀÏÀº ÆäÀÌÁö Ç¥½ÃÀÚÀÇ À§Ä¡¸¦ ¾î¶»°Ô Àâ´ÂÁö ¾Ë¾Æº¸´Â °ÍÀÌ´Ù. ÀÌ·± ÆäÀÌÁö Ç¥½ÃÀÚ È¤Àº 'tab'Àº, ³× °¡Áö ¹æ¹ýÀ¸·Î Àâ¾ÆÁÙ ¼ö ÀÖ´Ù. Áï top, bottom, left, ¶Ç´Â rightÀÌ´Ù.

void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos);

GtkPositionTypeÀº ´ÙÀ½ Áß ÇϳªÀ̸ç, »ó´çÈ÷ Á÷°üÀûÀÌ´Ù.

  • GTK_POS_LEFT
  • GTK_POS_RIGHT
  • GTK_POS_TOP
  • GTK_POS_BOTTOM

GTK_POS_TOPÀÌ µðÆúÆ®´Ù.

´ÙÀ½À¸·Î ³ëÆ®ºÏ¿¡ ¾î¶»°Ô ÆäÀÌÁö¸¦ ³Ö´ÂÁö ¾Ë¾Æº¸ÀÚ. ÀÌ·¸°Ô ÇÏ´Â °Í¿¡´Â ¼¼°¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. ¿ì¼± ¼­·Î À¯»çÇÑ µÎ°¡Áö¸¦ ¸ÕÀú »ìÆ캸ÀÚ.

void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);

void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);

ÀÌ·± ÇÔ¼öµéÀº ³ëÆ®ºÏÀÇ µÚ¿¡ »ðÀԵǴøÁö(append), ¶Ç´Â ³ëÆ®ºÏÀÇ ¾Õ¿¡¼­ »ðÀԵǴøÁö(prepend) Çؼ­ ÆäÀÌÁö¸¦ ´õÇØÁØ´Ù. *child´Â ³ëÆ®ºÏ ÆäÀÌÁö¿¡ À§Ä¡ÇÏ´Â widgetÀÌ°í, *tab_labelÀº ´õÇØÁú ÆäÀÌÁö¸¦ À§ÇÑ ¶óº§ÀÌ´Ù.

ÆäÀÌÁö¸¦ ´õÇØÁÖ´Â ¸¶Áö¸· ÇÔ¼ö´Â ¾ÕÀÇ µÎ°¡Áö°¡ °¡Áø Ư¼ºÀ» ¸ðµÎ °¡Áö°í ÀÖ´Ù. ÇÏÁö¸¸ ÀÌ°ÍÀº ¿ì¸®°¡ ³ëÆ®ºÏÀÇ ¾î´À À§Ä¡¿¡ ÆäÀÌÁö¸¦ ¼³Á¤ÇÒ Áö¸¦ Á¤Çϵµ·Ï ÇØÁØ´Ù.

void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position);

positionÀ̶ó´Â ¶Ç ÇϳªÀÇ ÀÎÀÚ¸¦ Æ÷ÇÔÇÑ´Ù´Â °Í¸¸ »©°í´Â, gtk_notebook_append_page ±×¸®°í gtk_notebook_prepend_page¿Í ÀÎÀÚ°¡ °°´Ù. position ÀÎÀÚ´Â ÀÌ ÆäÀÌÁö°¡ ¾î´À À§Ä¡¿¡ »ðÀ﵃ °ÍÀÎÁö ÁöÁ¤ÇØ ÁØ´Ù.

ÀÌÁ¦ ¾î¶»°Ô ÆäÀÌÁö¸¦ ´õÇÏ´ÂÁö ¾Ë¾ÒÀ¸¹Ç·Î, ³ëÆ®ºÏ¿¡¼­ ÆäÀÌÁö¸¦ ¾î¶»°Ô Á¦°ÅÇÏ´ÂÁö¸¦ ¾Ë¾Æº¸µµ·Ï ÇÏÀÚ.

void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num);

ÀÌ ÇÔ¼ö´Â page_num ÀÎÀÚ·Î ÁÖ¾îÁø ÆäÀÌÁö¸¦ ÃëÇؼ­, ±×°ÍÀ» *notebookÀ̶ó´Â widget¿¡¼­ Á¦°ÅÇØÁØ´Ù.

ÇöÀçÀÇ ÆäÀÌÁö¸¦ ¾Ë¾Æ³»±â À§Çؼ­´Â ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

gint gtk_notebook_current_page (GtkNotebook *notebook);

¿©±â ¼Ò°³ÇÏ´Â µÎ ÇÔ¼ö´Â ³ëÆ®ºÏÀÇ ÆäÀÌÁö¸¦ ¾ÕµÚ·Î À̵¿ÇÒ ¶§ ¾²´Â °£´ÜÇÑ ÇÔ¼öµéÀÌ´Ù. ¿ì¸®°¡ ´Ù·ê ³ëÆ®ºÏ widgetÀ» ´Ù·ç±â À§Çؼ­ Àú¸¶´ÙÀÇ ÇÔ¼ö¸¦ Áֱ⸸ ÇÏ¸é µÈ´Ù. ÁÖÀÇÇÒ °ÍÀº, ¸¶Áö¸· ÆäÀÌÁö¿¡¼­ gtk_notebook_next_page°¡ È£ÃâµÇ¸é ³ëÆ®ºÏÀÌ Ã¹¹ø° ÆäÀÌÁö·Î µ¹¾Æ°¡ ¹ö¸°´Ù´Â »ç½ÇÀÌ´Ù. ¸¶Âù°¡Áö·Î ù¹ø° ÆäÀÌÁö¿¡¼­ gtk_notebook_prev_page°¡ È£ÃâµÇ¸é ³ëÆ®ºÏÀÇ ¸¶Áö¸· ÆäÀÌÁö ·Î °¡¹ö¸°´Ù.

void gtk_notebook_next_page (GtkNoteBook *notebook);
void gtk_notebook_prev_page (GtkNoteBook *notebook);

À̹ø ÇÔ¼ö´Â 'active', Áï È°¼ºÈ­µÈ ÆäÀÌÁö¸¦ ¼¼ÆÃÇÑ´Ù. ¿¹¸¦µé¾î óÀ½ºÎÅÍ 5¹ø ÆäÀÌÁö·Î ³ëÆ®ºÏÀ» ¿­·Á¸é ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¸é µÉ °ÍÀÌ´Ù. ÀÌ°ÍÀ» ¾²Áö ¾ÊÀ¸¸é, µðÆúÆ®·Î ³ëÆ®ºÏÀº ù¹ø° ÆäÀÌÁö¿¡¼­ ¿­¸®°Ô µÈ´Ù.

void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num);

ÀÌ µÎ ÇÔ¼ö´Â °¢°¢ ³ëÆ®ºÏÀÇ ÆäÀÌÁö tab°ú °æ°è¸¦ ´õÇϰųª Á¦°ÅÇØÁØ´Ù.

void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs);
void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border);

ÀÎÀÚ show_tabs¿Í show_border´Â TRUE/FALSE Áß Çϳª°¡ µÉ ¼ö ÀÖ´Ù.

ÀÌÁ¦ ¿¹Á¦¸¦ Çϳª º¸ÀÚ. ÀÌ°ÍÀº GTK ¹èÆ÷º»°ú ÇÔ²² ÀÖ´Â testgtk.c ÇÁ·Î±×·¥ À¸·Î, 13°³ÀÇ ÇÔ¼ö¸¦ ¸ðµÎ º¸¿©ÁØ´Ù. ÀÌ ÀÛÀº ÇÁ·Î±×·¥Àº ³ëÆ®ºÏ°ú ¿©¼¸ °³ÀÇ ¹öÆ°À» °¡Áö°í ÀÖ´Â À©µµ¸¦ ¸¸µç´Ù. ³ëÆ®ºÏÀº ¼¼°¡Áö ´Ù¸¥ ¹æ¹ý, Áï append/ insert/prepend¸¦ ÅëÇØ ´õÇØÁø 11°³ ÆäÀÌÁö¸¦ °¡Áö°í ÀÖ´Ù. ¹öÆ°µéÀº tabÀÇ À§Ä¡¸¦ ¼øȯ½Ãų ¼ö ÀÖ°í, tab°ú border¸¦ ´õÇØÁְųª Áö¿ï¼ö ÀÖÀ¸¸ç, ÇÑ ÆäÀÌÁö ¸¦ Áö¿ï ¼öµµ ÀÖ´Ù. ±×¸®°í ¾ÕµÚ ¾ç¹æÇâÀ¸·Î ÆäÀÌÁö¸¦ ¹Ù²ãÁÖ¸ç, ÇÁ·Î±×·¥À» ³¡³¾ ¼öµµ ÀÖ´Ù.

/* notebook.c */

#include <gtk/gtk.h>

/* ÀÌ ÇÔ¼ö´Â tabÀÇ À§Ä¡¸¦ ·ÎÅ×ÀÌ¼Ç ½ÃŲ´Ù. */
void rotate_book (GtkButton *button, GtkNotebook *notebook)
{
                gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
}

/* page tab°ú border¸¦ ´õÇϰųª »èÁ¦ÇÑ´Ù. */
void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
{
                gint tval = FALSE;
                gint bval = FALSE;
                if (notebook->show_tabs == 0)
                                                tval = TRUE;
                if (notebook->show_border == 0)
                                                bval = TRUE;

                gtk_notebook_set_show_tabs (notebook, tval);
                gtk_notebook_set_show_border (notebook, bval);
}

/* ³ëÆ®ºÏ¿¡¼­ ÇÑ ÆäÀÌÁö¸¦ Á¦°ÅÇÑ´Ù. */
void remove_book (GtkButton *button, GtkNotebook *notebook)
{
                gint page;

                page = gtk_notebook_current_page(notebook);
                gtk_notebook_remove_page (notebook, page);
                /* Need to refresh the widget -
                 This forces the widget to redraw itself. */
                gtk_widget_draw(GTK_WIDGET(notebook), NULL);
}

void delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
                gtk_main_quit ();
}

int main (int argc, char *argv[])
{
                GtkWidget *window;
                GtkWidget *button;
                GtkWidget *table;
                GtkWidget *notebook;
                GtkWidget *frame;
                GtkWidget *label;
                GtkWidget *checkbutton;
                int i;
                char bufferf[32];
                char bufferl[32];

                gtk_init (&argc, &argv);

                window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

                gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                                                        GTK_SIGNAL_FUNC (delete), NULL);

                gtk_container_border_width (GTK_CONTAINER (window), 10);

                table = gtk_table_new(2,6,TRUE);
                gtk_container_add (GTK_CONTAINER (window), table);

                /* »õ ³ëÆ®ºÏÀ» ¸¸µé°í, tabµéÀÇ À§Ä¡¸¦ ¼³Á¤ÇÑ´Ù. */
                notebook = gtk_notebook_new ();
                gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
                gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
                gtk_widget_show(notebook);

                /* ³ëÆ®ºÏ¿¡ ÆäÀÌÁöµéÀÇ ¹­À½À» Ãß°¡ÇÑ´Ù. */
                for (i=0; i < 5; i++) {
                                sprintf(bufferf, "Append Frame %d", i+1);
                                sprintf(bufferl, "Page %d", i+1);

                                frame = gtk_frame_new (bufferf);
                                gtk_container_border_width (GTK_CONTAINER (frame), 10);
                                gtk_widget_set_usize (frame, 100, 75);
                                gtk_widget_show (frame);

                                label = gtk_label_new (bufferf);
                                gtk_container_add (GTK_CONTAINER (frame), label);
                                gtk_widget_show (label);

                                label = gtk_label_new (bufferl);
                                gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
                }

                /* ÁöÁ¤ÇÑ °÷À¸·Î ÇÑ ÆäÀÌÁö¸¦ ´õÇÑ´Ù. */
                checkbutton = gtk_check_button_new_with_label ("Check me please!");
                gtk_widget_set_usize(checkbutton, 100, 75);
                gtk_widget_show (checkbutton);

                label = gtk_label_new ("Add spot");
                gtk_container_add (GTK_CONTAINER (checkbutton), label);
                gtk_widget_show (label);
                label = gtk_label_new ("Add page");
                gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);

                /* ÀÌÁ¦ ³ëÆ®ºÏÀÇ ¼±µÎ¿¡ ÆäÀÌÁö¸¦ prependÇÑ´Ù. */
                for (i=0; i < 5; i++) {
                                sprintf(bufferf, "Prepend Frame %d", i+1);
                                sprintf(bufferl, "PPage %d", i+1);

                                frame = gtk_frame_new (bufferf);
                                gtk_container_border_width (GTK_CONTAINER (frame), 10);
                                gtk_widget_set_usize (frame, 100, 75);
                                gtk_widget_show (frame);

                                label = gtk_label_new (bufferf);
                                gtk_container_add (GTK_CONTAINER (frame), label);
                                gtk_widget_show (label);

                                label = gtk_label_new (bufferl);
                                gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
                }

                /* ½ÃÀÛÇÒ ÆäÀÌÁö¸¦ ¼¼ÆÃÇÑ´Ù(¿©±â¼­´Â page 4). */
                gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);

                /* ¹öÆ°ÀÇ ´Ù¹ß(bunch)À» Çϳª ¸¸µç´Ù. */
                button = gtk_button_new_with_label ("close");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   GTK_SIGNAL_FUNC (destroy), NULL);
                gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
                gtk_widget_show(button);

                button = gtk_button_new_with_label ("next page");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   (GtkSignalFunc) gtk_notebook_next_page,
                                   GTK_OBJECT (notebook));
                gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
                gtk_widget_show(button);

                button = gtk_button_new_with_label ("prev page");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   (GtkSignalFunc) gtk_notebook_prev_page,
                                   GTK_OBJECT (notebook));
                gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
                gtk_widget_show(button);

                button = gtk_button_new_with_label ("tab position");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
                gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
                gtk_widget_show(button);

                button = gtk_button_new_with_label ("tabs/border on/off");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   (GtkSignalFunc) tabsborder_book,
                                   GTK_OBJECT (notebook));
                gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
                gtk_widget_show(button);

                button = gtk_button_new_with_label ("remove page");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                   (GtkSignalFunc) remove_book,
                                   GTK_OBJECT(notebook));
                gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
                gtk_widget_show(button);

                gtk_widget_show(table);
                gtk_widget_show(window);

                gtk_main ();

                return 0;
}

ÀÌ°ÍÀ¸·Î ¿©·¯ºÐÀÇ GTK ¾îÇÃÀ» ¸¸µé ¶§ ³ëÆ®ºÏÀ» ´Ù·ç´Â ¹æ¹ý¿¡ ´ëÇÑ µµ¿òÀÌ µÇ±â¸¦ ¹Ù¶õ´Ù.

9.2 ½ºÅ©·ÑµÈ À©µµ

ÀÌ°ÍÀº ½ÇÁ¦ À©µµ ³»ºÎ¿¡¼­ ½ºÅ©·ÑµÈ ¿µ¿ªÀ» ¸¸µé ¶§ ¾²ÀÌ´Â °ÍÀÌ´Ù. ¿ì¸®´Â ÀÌ·± ½ºÅ©·ÑµÈ ¿µ¿ª¿¡ ¾î¶² Á¾·ùÀÇ widgetÀÌ¶óµµ »ðÀÔÇÒ ¼ö ÀÖ°í, ½ºÅ©·Ñ¹Ù¸¦ ÀÌ¿ëÇÏ¿© Å©±â¿¡ °ü°è¾øÀÌ Á¢±ÙÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

ÀÌ ÇÔ¼ö´Â »õ·Î¿î ½ºÅ©·Ñ À©µµ¸¦ ¸¸µå´Â °ÍÀÌ´Ù.

GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment,
                                    GtkAdjustment *vadjustment);

ù¹ø° ÀÎÀÚ´Â ¼öÆò¹æÇâÀ», ±×¸®°í µÎ¹ø° ÀÎÀÚ´Â ¼öÁ÷¹æÇâÀ» Á¶ÀýÇØ ÁØ´Ù. À̰͵éÀº ´ë°³ NULL·Î ¼¼ÆõȴÙ.

void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
                                     GtkPolicyType hscrollbar_policy,
                                     GtkPolicyType vscrollbar_policy);

ÀÌ°ÍÀº ½ºÅ©·Ñ¹ÙµéÀ» ¾²´Â ¹æ½ÄÀ» ¼³Á¤ÇÑ´Ù. ù¹ø° ÀÎÀÚ´Â ¿ì¸®°¡ º¯È­ ½ÃÅ°°íÀÚ ÇÏ´Â ½ºÅ©·Ñ À©µµ´Ù. µÎ¹ø°¿Í ¼¼¹ø° ÀÎÀÚµéÀº °¢°¢ ¼öÆò ½ºÅ©·Ñ¹Ù¿Í ¼öÁ÷ ½ºÅ©·Ñ¹ÙÀÇ ¹æ½ÄÀ» ¼¼ÆÃÇÑ´Ù.

ÀÌ ¹æ½ÄÀ̶õ °ÍÀº GTK_POLICY_AUTOMATIC ȤÀº GTK_POLICY_ALWAYS °¡ µÈ´Ù. GTK_POLICY_AUTOMATICÀº ½ºÅ©·Ñ¹Ù°¡ ÇÊ¿äÇÒ ¶§¸¦ ÀÚµ¿ÀûÀ¸·Î °áÁ¤ÇÏ°í, ¹Ý¸é GTK_POLICY_ALWAYS´Â ¾ðÁ¦³ª ½ºÅ©·Ñ¹Ù¸¦ ¸¸µé¾î µÐ´Ù.

ÀÌ °£´ÜÇÑ ¿¹Á¦´Â ½ºÅ©·ÑµÈ À©µµ¿¡ 100°³ÀÇ Åä±Û ¹öÆ°À» ÆÐÅ·ÇÑ´Ù. ¿©±â¼­ÀÇ ÁÖ¼®Àº ¿©·¯ºÐ¿¡°Ô »ý¼ÒÇÒ ºÎºÐ¿¡¸¸ ºÙ¿©Áú °ÍÀÌ´Ù.

/* scrolledwin.c */

#include <gtk/gtk.h>

void destroy(GtkWidget *widget, gpointer data)
{
                gtk_main_quit();
}

int main (int argc, char *argv[])
{
                static GtkWidget *window;
                GtkWidget *scrolled_window;
                GtkWidget *table;
                GtkWidget *button;
                char buffer[32];
                int i, j;

                gtk_init (&argc, &argv);

                /* ½ºÅ©·ÑµÈ À©µµ°¡ ÆÐÅ·µÇ¾î µé¾î°¥ dialog À©µµ¸¦ ¸¸µç´Ù. 
                 * Dialog À©µµ¶õ vbox¿Í ±×°Í¿¡ ÆÐÅ·µÇ¾î µé¾î°¥ ¼öÆò seperator¸¦ °¡Áö°í
                 * ÀÖ´Ù´Â °Í¸¸ »©°í´Â º¸ÅëÀÇ À©µµ¿Í µ¿ÀÏÇÑ °ÍÀÌ´Ù.  ÀÌ°ÍÀº dialog¸¦
                 * ¸¸µé°Ô µÇ´Â ÀÏÁ¾ÀÇ shortcutÀÌ´Ù. */
                window = gtk_dialog_new ();
                gtk_signal_connect (GTK_OBJECT (window), "destroy",
                                                        (GtkSignalFunc) destroy, NULL);
                gtk_window_set_title (GTK_WINDOW (window), "dialog");
                gtk_container_border_width (GTK_CONTAINER (window), 0);

                /* ½ºÅ©·ÑµÈ(scrolled) À©µµ¸¦ Çϳª ¸¸µç´Ù. */
                scrolled_window = gtk_scrolled_window_new (NULL, NULL);

                gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);

                /* ¿©±â¼­ÀÇ ¹æ½ÄÀº GTK_POLICY_AUTOMATIC ¶Ç´Â GTK_POLICY_ALWAYS Áß
                 * ÇϳªÀÌ´Ù.  GTK_POLICY_AUTOMATICÀº ½ºÅ©·Ñ¹Ù°¡ ÇÊ¿äÇÑÁö¸¦ ÀÚµ¿ÀûÀ¸·Î
                 * °áÁ¤ÇÏ°í, ¹Ý¸é GTK_POLICY_ALWAYS´Â ¾ðÁ¦³ª ½ºÅ©·Ñ¹Ù¸¦ °¡Áö°Ô ÇÑ´Ù.
                 * ù¹ø°´Â ¼öÆò¹æÇâÀÇ ½ºÅ©·Ñ¹Ù, ±×¸®°í µÎ¹ø°´Â ¼öÁ÷¹æÇâÀÇ °ÍÀÌ´Ù. */

                gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
                /* vbox°¡ ÆÐÅ·µÇ¾î µé¾î°£ dialog À©µµ¸¦ Çϳª ¸¸µç´Ù. */
                gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
                                                                                                TRUE, TRUE, 0);
                gtk_widget_show (scrolled_window);

                /* 10Çà 10¿­ÀÇ Å×À̺íÀ» ¸¸µç´Ù. */
                table = gtk_table_new (10, 10, FALSE);

                /* x¿Í y¿¡ ´ëÇØ 10 ¸¸Å­ÀÇ spacingÀ» ¼¼ÆÃÇÑ´Ù. */
                gtk_table_set_row_spacings (GTK_TABLE (table), 10);
                gtk_table_set_col_spacings (GTK_TABLE (table), 10);

                /* ½ºÅ©·ÑµÈ À©µµ¿¡ Å×À̺íÀ» ÆÐÅ·ÇÑ´Ù. */
                gtk_container_add (GTK_CONTAINER (scrolled_window), table);
                gtk_widget_show (table);

                /* ÀÌ°ÍÀº ´Ü¼øÈ÷ ½ºÅ©·ÑµÈ À©µµ¸¦ º¸¿©ÁÖ±â À§ÇØ Å×À̺í À§¿¡
                 * Åä±Û¹öÆ°µéÀÇ °ÝÀÚ(grid)¸¦ Çϳª ¸¸µç´Ù. */
                for (i = 0; i < 10; i++)
                                                for (j = 0; j < 10; j++) {
                                                                sprintf (buffer, "button (%d,%d)\n", i, j);
                                                                button = gtk_toggle_button_new_with_label (buffer);
                                                                gtk_table_attach_defaults (GTK_TABLE (table), button,
                                                                                                         i, i+1, j, j+1);
                                                                gtk_widget_show (button);
                                                }
                /* DialogÀÇ ¸Ç ¾Æ·¡ÂÊ¿¡ "close" ¹öÆ°À» Ãß°¡ÇÑ´Ù. */
                button = gtk_button_new_with_label ("close");
                gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                                                 (GtkSignalFunc) gtk_widget_destroy,
                                                                 GTK_OBJECT (window));

                /* ÀÌ°ÍÀ» µðÆúÆ® ¹öÆ°À¸·Î ÇÑ´Ù. */

                GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
                gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);

                /* ÀÌ ¹öÆ°ÀÌ µðÆúÆ® ¹öÆ°À¸·Î µÇµµ·Ï Àâ¾Ææ´Ù.  °£´ÜÈ÷ "Enter"¸¦ Ä¡¸é
                 * ÀÌ ¹öÆ°À» È°¼ºÈ­ ½Ãų °ÍÀÌ´Ù. */
                gtk_widget_grab_default (button);
                gtk_widget_show (button);

                gtk_widget_show (window);

                gtk_main();

                return(0);
}

À©µµÀÇ Å©±â¸¦ º¯ÇÏ°Ô Çغ¸¶ó. ½ºÅ©·Ñ¹Ù°¡ ¾î¶»°Ô ¹ÝÀÀÇÏ´ÂÁö ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¿ì¸®´Â ¶ÇÇÑ À©µµ³ª ´Ù¸¥ widgetÀÇ µðÆúÆ® Å©±â¸¦ ¼¼ÆÃÇϱâ À§ÇØ gtk_widget_set_usize() ÇÔ¼ö¸¦ ÀÌ¿ëÇÒ ¼öµµ ÀÖÀ» °ÍÀÌ´Ù.

9.3 Paned À©µµ widget

ÀÌ paned À©µµ widgetÀº ÇÑ ¿µ¿ªÀ» »ç¿ëÀÚ¿¡ ÀÇÇؼ­ ±× »ó´ëÀûÀÎ Å©±â¸¦ ¸¶À½´ë·Î Á¶ÀýÇÒ ¼ö ÀÖ´Â µÎ ¿µ¿ªÀ¸·Î ³ª´©¾î ¾²°í ½ÍÀ» ¶§ »ç¿ëÇÑ´Ù. µÎ ¿µ¿ª »çÀÌ¿¡´Â handleÀÌ ´Þ¸° ȨÀÌ ÀÖ°í À̸¦ ¸¶¿ì½º·Î µå·¡±×Çؼ­ »ç¿ëÀÚ´Â ¿øÇÏ´Â ´ë·Î µÎ ¿µ¿ªÀÇ ºñÀ²À» ¹Ù²Ü ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ºÐÇÒÀº ¼öÆò(HPaned)ÀûÀ̰ųª ¼öÁ÷(VPaned)ÀûÀÌ µÈ´Ù.

»õ paned À©µµ¸¦ ¸¸µé·Á¸é ´ÙÀ½Áß Çϳª¸¦ ºÎ¸¥´Ù.

GtkWidget* gtk_hpaned_new (void)
GtkWidget* gtk_vpaned_new (void)

Paned À©µµ widgetÀ» ¸¸µç ´ÙÀ½¿¡´Â ³ª´©¾îÁø ¾çÂÊ¿¡ ÀÚ½Ä widgetÀ» ÁÖ¾î¾ß ÇÑ´Ù. ÀÌ´Â ´ÙÀ½ ÇÔ¼öµéÀ» ÀÌ¿ëÇؼ­ ÀÌ·ç¾îÁø´Ù.

void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child)
void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child)

gtk_paned_add1()´Â paned À©µµ widgetÀÇ ¿ÞÂÊ È¤Àº À­ÂÊ¿¡ ÀÚ½Ä widgetÀ» ´õÇÑ´Ù. gtk_paned_add2()´Â ¹Ý´ë·Î ¿À¸¥ÂÊ È¤Àº ¾Æ·§ÂÊ¿¡ ´õÇÑ´Ù.

ÇÑ ¿¡·Î °¡»óÀûÀÎ email ÇÁ·Î±×·¥ÀÇ »ç¿ëÀÚ ÀÎÅÍÆäÀ̽º ÀϺθ¦ ¸¸µé¾î º¸±â·Î ÇÑ´Ù. À©µµ´Â email ¸Þ¼¼ÁöµéÀÇ ¸®½ºÆ®¸¦ Ç¥½ÃÇÏ´Â À­ ºÎºÐ°ú ¸Þ¼¼Áö ÀÚü¸¦ Ç¥½ÃÇÏ´Â ¾Æ·§ ºÎºÐÀ¸·Î ³ª´©¾îÁø´Ù. ÇÁ·Î±×·¡ÀÇ ´ëºÎºÐÀº ¹«Ã´ °£´ÜÇÏ´Ù. µÎ°¡Áö ÁÖÀÇÇØ¾ß ÇÒ Á¡ÀÌ ÀÖ´Ù. ÅؽºÆ®´Â ÅؽºÆ® widget¿¡ ÀÌ°ÍÀÌ realizeµÇ±â Àü¿¡´Â ´õÇØÁú ¼ö ¾ø´Ù. ÀÌ´Â gtk_widget_realize()¸¦ È£ÃâÇؼ­ ÀÌ·ç¾îÁöÁö¸¸ ¶Ç ´Ù¸¥ ¹æ¹ýÀ¸·Î text¸¦ ´õÇϱâ À§ÇØ "realize" ½Ã±×³ÎÀ» ¿¬°áÇÒ ¼öµµ ÀÖ´Ù. ¶ÇÇÑ, GTK_SHRINK ¿É¼ÇÀ» text À©µµ¿Í ½ºÅ©·Ñ¹Ù¸¦ Æ÷ÇÔÇÏ°í ÀÖ´Â Å×ÀÌºí ³»¿ë ÀϺο¡ ´õÇØÁÖ´Â °ÍÀÌ ÇÊ¿äÇÏ´Ù. ±×·¡¾ß¸¸ ¾Æ·§ ºÎºÐÀ» ÀÛ°Ô ¸¸µé¶§ À©µµÀÇ ¹Ù´ÚÀÌ ¹Ð·Á³ª´Â ´ë½Å ¿øÇÏ´ø ºÎºÐÀÌ ÁÙ¾îµé°Ô µÈ´Ù.

/* paned.c */

#include <gtk/gtk.h>
   
/* "messages"ÀÇ ¸®½ºÆ®¸¦ ¸¸µç´Ù */
GtkWidget *
create_list (void)
{

    GtkWidget *scrolled_window;
    GtkWidget *list;
    GtkWidget *list_item;
   
    int i;
    char buffer[16];
   
    /* ½ºÅ©·Ñ¹Ù(ÇÊ¿äÇÒ ¶§¸¸)°¡ µþ¸° ½ºÅ©·ÑµÈ À©µµ¸¦ ¸¸µç´Ù. */
    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                    GTK_POLICY_AUTOMATIC, 
                                    GTK_POLICY_AUTOMATIC);
   
    /* »õ·Î¿î ¸®½ºÆ®¸¦ ¸¸µé¾î À̸¦ ½ºÅ©·ÑµÈ À©µµ¿¡ Áý¾î³Ö´Â´Ù. */
    list = gtk_list_new ();
    gtk_container_add (GTK_CONTAINER(scrolled_window), list);
    gtk_widget_show (list);
   
    /* À©µµ¿¡ ¸Þ½ÃÁö ¸î°³¸¦ ´õÇÑ´Ù */
    for (i=0; i<10; i++) {

        sprintf(buffer,"Message #%d",i);
        list_item = gtk_list_item_new_with_label (buffer);
        gtk_container_add (GTK_CONTAINER(list), list_item);
        gtk_widget_show (list_item);

    }
   
    return scrolled_window;
}
   
/* ÅؽºÆ® ¸î°³¸¦ ÅؽºÆ® widget¿¡ ´õÇÑ´Ù. - ¾Æ·¡ ÇÔ¼ö´Â ¿ì¸®ÀÇ À©µµ°¡ realize µÉ
¶§ ºÒ¸®´Â callbackÀÌ´Ù. gtk_widget_realize·Î realizeµÇµµ·Ï °­Á¦ÇÒ ¼öµµ ÀÖÁö¸¸
±×°Ç ¸ÕÀú °èÃþ±¸Á¶ÀÇ ÇÑ ºÎºÐÀÌ µÇ¾î¾ß ÇÒ °ÍÀÌ´Ù.
*/
void
realize_text (GtkWidget *text, gpointer data)
{
    gtk_text_freeze (GTK_TEXT (text));
    gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
    "From: pathfinder@nasa.gov\n"
    "To: mom@nasa.gov\n"
    "Subject: Made it!\n"
    "\n"
    "We just got in this morning. The weather has been\n"
    "great - clear but cold, and there are lots of fun sights.\n"
    "Sojourner says hi. See you soon.\n"
    " -Path\n", -1);
   
    gtk_text_thaw (GTK_TEXT (text));
}
   
/* "message"¸¦ º¸¿©ÁÖ´Â ½ºÅ©·ÑµÈ ÅؽºÆ® ¿µ¿ªÀ» ¸¸µç´Ù. */
GtkWidget *
create_text (void)
{
    GtkWidget *table;
    GtkWidget *text;
    GtkWidget *hscrollbar;
    GtkWidget *vscrollbar;
   
    /* ÅؽºÆ® À§Á¬°ú ½ºÅ©·Ñ¹Ù¸¦ °®´Â Å×À̺íÀ» ¸¸µç´Ù */
    table = gtk_table_new (2, 2, FALSE);
   
    /* ÅؽºÆ® À§Á¬À» ¿ÞÂÊ À§¿¡ ³õ´Â´Ù. Y Ãà ¹æÇâÀ¸·Î GTK_SHRINK°¡ ¾²ÀÎ °ÍÀ»
     * ÁÖ¸ñÇÒ °Í. */
    text = gtk_text_new (NULL, NULL);
    gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
                      GTK_FILL | GTK_EXPAND,
                      GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
    gtk_widget_show (text);
   
    /* HScrollbar¸¦ ¿ÞÂÊ ¾Æ·¡¿¡ ³õ´Â´Ù. */
    hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
    gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
                      GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
    gtk_widget_show (hscrollbar);
   
    /* VScrollbar¸¦ ¿À¸¥ÂÊ À§¿¡ ³õ´Â´Ù. */
    vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
    gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
                      GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
    gtk_widget_show (vscrollbar);
   
    /* ÅؽºÆ® widgetÀÌ realizeµÇ¾úÀ» ¶§ ±× widgetÀÌ °®°í ÀÖ´Â ¸Þ½ÃÁö¸¦
     * Ãâ·ÂÇÏ¿©ÁÖ´Â ½Ã±×³Î Çڵ鷯¸¦ ´õÇÑ´Ù. */
    gtk_signal_connect (GTK_OBJECT (text), "realize",
                        GTK_SIGNAL_FUNC (realize_text), NULL);
   
    return table;
}
   
int
main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *vpaned;
    GtkWidget *list;
    GtkWidget *text;

    gtk_init (&argc, &argv);
   
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
    gtk_container_border_width (GTK_CONTAINER (window), 10);
   
    /* vpaned widgetÀ» ¸¸µé¾î¼­ toplevel À©µµ¿¡ ´õÇÑ´Ù. */
   
    vpaned = gtk_vpaned_new ();
    gtk_container_add (GTK_CONTAINER(window), vpaned);
    gtk_widget_show (vpaned);
   
    /* ÀÌÁ¦ À©µµ µÎ ºÎºÐÀÇ ³»¿ëÀ» ¸¸µç´Ù. */
   
    list = create_list ();
    gtk_paned_add1 (GTK_PANED(vpaned), list);
    gtk_widget_show (list);
   
    text = create_text ();
    gtk_paned_add2 (GTK_PANED(vpaned), text);
    gtk_widget_show (text);
    gtk_widget_show (window);
    gtk_main ();
    return 0;
}

9.4 Aspect ÇÁ·¹ÀÓ

Aspect ÇÁ·¹ÀÓÀº ¸î°¡Áö Ư¡À» »©¸é ÇÁ·¹ÀÓ widget°ú ºñ½ÁÇÏ´Ù. ÀÌ widgetÀº ÀÚ½Ä widgetÀÇ aspect ºñÀ²(°¡·Î¿Í ¼¼·Î ºñÀ²)ÀÌ ¹Ýµå½Ã ¾î¶² ƯÁ¤ÇÑ °ªÀÌ µÇµµ·Ï ¶§¿¡ µû¶ó ¿©ºÐÀÇ °ø°£À» ´õÇؼ­¶óµµ °­Á¦ÇÑ´Ù. ÀÌ°ÍÀº ¿¹¸¦ µé¸é »ó´çÈ÷ Å« À̹ÌÁöÀÇ ¹Ì¸®º¸±â¸¦ º¸´Â ¶§ °°Àº °æ¿ì À¯¿ëÇÏ´Ù. ÀÌ ¹Ì¸®º¸±âÀÇ Å©±â´Â »ç¿ëÀÚ°¡ À©µµÀÇ Å©±â¸¦ ¹Ù²Ü ¶§¸¶´Ù ´Þ¶óÁöÁö¸¸ °¡·Î¼¼·Î ºñÀ²Àº ¾ðÁ¦³ª ¿ø·¡ À̹ÌÁö¿Í °°¾Æ¾ß¸¸ ÇÑ´Ù.

»õ·Î¿î aspect ÇÁ·¹ÀÓÀ» ¸¸µå·Á¸é,

GtkWidget* gtk_aspect_frame_new  (const gchar *label,
                                        gfloat xalign,
                                        gfloat yalign,
                                        gfloat ratio,
                                        gint obey_child)

xalign¿Í yalignÀº Alignment widget¿¡¼­Ã³·³ widgetÀÇ alignment °ªÀ» Á¤ÇÑ´Ù. ¸¸ÀÏ obey_child °ªÀÌ true¸é, ÀÚ½Ä widgetÀÇ °¡·Î¼¼·Î ºñÀ²Àº ¿ø·¡ ¸¸µé¾îÁ³À» ¶§ÀÇ ÀÌ»óÀûÀÎ ºñÀ²°ú °°°Ô µÈ´Ù. ¹Ý´ë·Î falseÀÌ¸é ±× ºñÀ²Àº ratio·Î Á÷Á¢ ÁÖ¾îÁø´Ù.

ÀÌ¹Ì Á¸ÀçÇÏ°í ÀÖ´Â aspect ÇÁ·¹ÀÓÀÇ ¿É¼ÇÀ» ¹Ù²Ù·Á¸é ´ÙÀ½ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
                           gfloat xalign,
                           gfloat yalign,
                           gfloat ratio,
                           gint obey_child)

¿¹Á¦ÀÎ ´ÙÀ½ ÇÁ·Î±×·¥Àº »ç¿ëÀÚ°¡ toplevel À©µµÀÇ Å©±â¸¦ ¾î¶»°Ô ¹Ù²Ùµç ¾ðÁ¦³ª °¡·Î¼¼·Î ºñÀ²ÀÌ 2:1ÀÎ drawing area¸¦ Ç¥ÇöÇϴµ¥ AspectFrameÀ» ¾²°í ÀÖ´Ù.

/* aspectframe.c */

#include <gtk/gtk.h>
   
int
main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *aspect_frame;
    GtkWidget *drawing_area;
    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_main_quit), NULL);
    gtk_container_border_width (GTK_CONTAINER (window), 10);
   
    /* aspect_frameÀ» ¸¸µé¾î toplevel À©µµ¿¡ ´õÇÑ´Ù */
   
    aspect_frame = gtk_aspect_frame_new ("2x1", /* ·¹À̺í */
                                         0.5, /* center x */
                                         0.5, /* center y */
                                         2, /* xsize/ysize = 2 */
                                         FALSE /* ÀÚ½ÄÀÇ °¡·Î¼¼·Î ºñÀ² ¹«½Ã*/);
   
    gtk_container_add (GTK_CONTAINER(window), aspect_frame);
    gtk_widget_show (aspect_frame);
   
    /* aspect frame¿¡ ´õÇÒ ÀÚ½Ä widgetÀ» ¸¸µç´Ù*/
   
    drawing_area = gtk_drawing_area_new ();
   
    /* 200x200 À©µµ¸¦ ¿äûÇßÁö¸¸ AspectFrameÀº 2:1 ºñÀ²À» °­Á¦Çϱ⠶§¹®¿¡
     * 200x100 À©µµ¸¦ ÁØ´Ù. */
    gtk_widget_set_usize (drawing_area, 200, 200);
    gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
    gtk_widget_show (drawing_area);
   
    gtk_widget_show (window);
    gtk_main ();
    return 0;
}  

10. ¸®½ºÆ® widget

GtkList widgetÀº GtkListItemÇüÀÇ widgetµé À§ÇÑ ¼öÁ÷ÀÇ ÄÁÅ×À̳Êó·³ ÀÛµ¿Çϵµ·Ï ¼³°èµÇ¾ú´Ù.

ÇϳªÀÇ GtkList widgetÀº À̺¥Æ®¸¦ ¹ÞÀ» ÀڽŸ¸ÀÇ À©µµ¿Í, º¸Åë whiteÀÎ ÀڽŸ¸ÀÇ background »öÀ» °¡Áö°í ÀÖ´Ù. GtkContainer·ÎºÎÅÍ ÆÄ»ýµÇ¾ú±â¿¡ GTK_CONTAINER(List) ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇØ ´Ù·ê ¼ö Àִµ¥, ÀÌ°Í¿¡ ´ëÇؼ­´Â GtkContainer widget¿¡ ´ëÇÑ ºÎºÐÀ» Âü°íÇϱ⠹ٶõ´Ù.

GtkList widgetÀÇ ±¸Á¶Ã¼ Á¤ÀÇ¿¡´Â ÈξÀ ´õ Èï¹Ì·Î¿î ÇϳªÀÇ Çʵ尡 ÀÖ´Ù. ¹Ù·Î ÀÌ°ÍÀÌ´Ù.

struct _GtkList
{
  ...
  GList *selection;
  guint selection_mode;
  ...
};

GtkListÀÇ selection Çʵå´Â ÇöÀç ¼±ÅÃµÈ ¸ðµç ¾ÆÀÌÅÛµéÀÇ ¿¬°á¸®½ºÆ®¸¦ °¡¸®Å°°í ÀÖ°í, ¸¸¾à ¼±ÅÃµÈ °Ô ¾ø´Ù¸é 'NULL'ÀÌ´Ù. ±×·¡¼­ ¿ì¸®´Â ÇöÀçÀÇ ¼±ÅÃµÈ °ÍÀ» ¾Ë±âÀ§ÇØ GTK_LIST()->selection Çʵ带 ÂüÁ¶ÇÏÁö¸¸, ±× ³»ºÎÀÇ ÇʵåµéÀÌ gtk_list*() ÇÔ¼öµé·Î½á À¯ÁöµÇ°í ÀÖÀ¸¹Ç·Î ±×°ÍÀ» º¯ÇüÇؼ­´Â ¾ÈµÈ´Ù. GtkListÀÇ selection_mode´Â GtkList Áï GTK_LIST()->selection ÇʵåÀÇ °Íµé¿¡ ´ëÇÑ ¼±Åà ¼Ó¼ºÀ» °áÁ¤ÇÑ´Ù.

selection_mode´Â À̰͵é Áß Çϳª°¡ µÉ °ÍÀÌ´Ù.

  • GTK_SELECTION_SINGLE - ¼±ÅÃÀº 'NULL'À̰ųª ÇϳªÀÇ ¼±ÅÃµÈ ¾ÆÀÌÅÛÀ» ÇâÇÑ GList* Çü Æ÷ÀÎÅÍ´Ù.
  • GTK_SELECTION_BROWSE - ¸®½ºÆ®°¡ widgetÀ» °¡Áö°í ÀÖÁö ¾Ê°Å³ª ¶Ç´Â ¹«°üÇÑ °Í¸¸À» °¡Áö°í ÀÖÀ» ¶§ ¼±ÅÃÀº 'NULL'ÀÌ´Ù. ¾Æ´Ï¸é ±×°ÍÀº ÇϳªÀÇ GList ±¸Á¶Ã¼¸¦ ÇâÇÑ GList* Æ÷ÀÎÅ͸¦ Æ÷ÇÔÇÏ°í, µû¶ó¼­ Á¤È®È÷ ÇϳªÀÇ ¸®½ºÆ® ¾ÆÀÌÅÛ À» Æ÷ÇÔÇÏ°Ô µÈ´Ù.
  • GTK_SELECTION_MULTIPLE - ¾Æ¹«·± ¾ÆÀÌÅÛÀÌ ¼±ÅõÇÁö ¾Ê¾Ò´Ù¸é 'NULL'ÀÌ°í, ¶Ç´Â ù¹ø° ¼±ÅÃµÈ ¾ÆÀÌÅÛÀ» ÇâÇÑ GList* Æ÷ÀÎÅÍ°¡ µÈ´Ù. ÀÌ°ÍÀº µÎ¹ø° ¼±ÅÃµÈ ¾ÆÀÌÅÛÀÇ ±¸Á¶Ã¼¸¦ °¡¸®Å°°Ô µÇ°í, ±×·¸°Ô µ¹¾Æ°£´Ù.
  • GTK_SELECTION_EXTENDED - ¼±ÅÃÀº ¾ðÁ¦³ª 'NULL'ÀÌ´Ù.

µðÆúÆ®´Â GTK_SELECTION_MULTIPLEÀÌ´Ù.

10.1 ½Ã±×³Î

void GtkList::selection_changed (GtkList *LIST)

ÀÌ ½Ã±×³ÎÀº GtkListÀÇ selection Çʵ尡 º¯È­ÇßÀ» ¶§¸¶´Ù ¿äûµÈ´Ù. ÀÌ°ÍÀº GtkListÀÇ child°¡ ¼±Åõǰųª ¼±ÅÃÀÌ ÇØÁ¦µÇ¾úÀ» ¶§ ¹ß»ýÇÑ´Ù.

void GtkList::select_child (GtkList *LIST, GtkWidget *CHILD)

ÀÌ ½Ã±×³ÎÀº GtkListÀÇ child°¡ ¼±ÅõǷÁ°í ÇÒ ¶§ ¹ß»ýÇÑ´Ù. ÀÌ°ÍÀº ÁÖ·Î gtk_list_select_item()³ª gtk_list_select_child()¸¦ È£ÃâÇÒ ¶§, ¹öÆ°À» ´­·¶À» ¶§ µî¿¡ ¹ß»ýÇϸç, ¶§¶§·Î childµéÀÌ GtkList¿¡ ´õÇØÁö°Å³ª »èÁ¦µÇ¾úÀ» ¶§ ´Ù¸¥ ¿øÀε鿡 ÀÇÇØ °£Á¢ÀûÀ¸·Î ¹ß»ýÇϱ⵵ ÇÑ´Ù.

void GtkList::unselect_child (GtkList *LIST, GtkWidget *CHILD)

ÀÌ°ÍÀº GtkListÀÇ child°¡ ¼±Åà ÇØÁ¦µÉ ¶§ ¿äûµÈ´Ù. ÀÌ°ÍÀº ÁÖ·Î gtk_list_ unselect_item()À̳ª gtk_list_unselect_child()ÇÔ¼ö¸¦ ºÎ¸¦ ¶§³ª ¹öÆ°À» ´­·¶À» ¶§ ¹ß»ýÇϸç, ¿ª½Ã GtkList¿¡ childµéÀÌ ´õÇØÁö°Å³ª »èÁ¦µÉ ¶§ ¶Ç´Ù¸¥ ¿øÀο¡ ÀÇÇØ °£Á¢ÀûÀ¸·Î ¹ß»ýÇÑ´Ù.

10.2 ÇÔ¼ö

guint gtk_list_get_type (void)

ÀÌ°ÍÀº GtkListÇüÀÇ ½Äº°ÀÚ¸¦ ¸®ÅÏÇÑ´Ù.

GtkWidget* gtk_list_new (void)

ÀÌ°ÍÀº »õ·Î¿î GtkList object¸¦ ¸¸µç´Ù. ÀÌ »õ widget Àº GtkWidget object¸¦ ÇâÇÑ Æ÷ÀÎÅÍÀÇ ÇüÅ·Π¸®ÅϵȴÙ. ½ÇÆÐÇßÀ» °æ¿ì¿£ 'NULL'À» ¸®ÅÏÇÑ´Ù.

void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION)

POSITION¿¡¼­ ½ÃÀÛÇؼ­, ¸®½ºÆ® ¾ÆÀÌÅÛÀ» LIST¿¡ »ðÀÔÇÑ´Ù. ITEMS´Â °¢ ³ëµåÀÇ µ¥ÀÌÅÍ Æ÷ÀÎÅÍ°¡ »õ·Ó°Ô ¸¸µé¾îÁø GtkListItem¸¦ °¡¸®Å°µµ·Ï µÇ¾îÀÖ´Â, ÀÌÁßÀÇ ¿¬°á¸®½ºÆ®´Ù. ITEMSÀÇ GList³ëµåµéÀº LIST¿¡ ÀÇÇØ ÃëÇØÁø´Ù.

void gtk_list_append_items (GtkList *LIST, GList *ITEMS)

LISTÀÇ ¸¶Áö¸·¿¡ gtk_list_insert_items() ó·³ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» »ðÀÔÇÑ´Ù. ITEMSÀÇ GList ³ëµåµéÀº LIST¿¡ ÀÇÇØ ÃëÇØÁø´Ù.

void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS)

LISTÀÇ ¸Ç ùºÎºÐ¿¡ gtk_list_insert_items() ó·³ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» »ðÀÔÇÑ´Ù. ¿ª½Ã ITEMSÀÇ GList ³ëµåµéÀº LIST¿¡ ÀÇÇØ ÃëÇØÁø´Ù.

void gtk_list_remove_items (GtkList *LIST, GList *ITEMS)

LIST·ÎºÎÅÍ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» Á¦°ÅÇÑ´Ù. ITEMS´Â °¢ ³ëµåÀÇ µ¥ÀÌŸ Æ÷ÀÎÅÍ°¡ LISTÀÇ Á÷°è child¸¦ °¡¸®Å°µµ·Ï µÇ¾î ÀÖ´Â ÀÌÁß ¿¬°á¸®½ºÆ®´Ù. °è¼ÓÇؼ­ g_list_free(ITEMS)¸¦ ºÎ¸£´Â °ÍÀº È£ÃâÇÏ´Â »ç¶÷ÀÇ Ã¥ÀÓÀÌ´Ù. ¶ÇÇÑ È£ÃâÀÚ´Â ¸®½ºÆ® ¾ÆÀÌÅÛ ±× ÀÚüµµ Æı«ÇØ ÁÖ¾î¾ß ÇÑ´Ù.

void gtk_list_clear_items (GtkList *LIST, gint START, gint END)

LIST·ÎºÎÅÍ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» »èÁ¦ÇÏ°í Æı«ÇØÁØ´Ù. LIST¿¡¼­ÀÇ ÇöÀç À§Ä¡°¡ START¿¡¼­ END »çÀÌ·Î ¼³Á¤µÈ ¿µ¿ª¿¡ ÀÖ´Â widgetÀÌ ¿µÇâÀ» ¹ÞÀ» °ÍÀÌ´Ù.

void gtk_list_select_item (GtkList *LIST, gint ITEM)

LIST¿¡¼­ÀÇ ÇöÀç À§Ä¡¸¦ ÅëÇØ ÁöÁ¤µÈ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» À§ÇØ GtkList::select_ child ½Ã±×³ÎÀ» ¿äûÇÑ´Ù.

void gtk_list_unselect_item (GtkList *LIST, gint ITEM)

À§¿Í ¸¶Âù°¡Áö °æ¿ì¿¡ GtkList::unselect_child ½Ã±×³ÎÀ» ¿äûÇÑ´Ù.

void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD)

ÁÖ¾îÁø CHILD¸¦ À§ÇØ GtkList::select_child ½Ã±×³ÎÀ» ¿äûÇÑ´Ù.

void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD)

ÁÖ¾îÁø CHILD¸¦ À§ÇØ GtkList::unselect_child ½Ã±×³ÎÀ» ¿äûÇÑ´Ù.

gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD)

LIST¿¡¼­ÀÇ CHILDÀÇ À§Ä¡¸¦ ¸®ÅÏÇÑ´Ù. '-1'Àº ½ÇÆÐÇßÀ» ¶§ÀÇ ¸®ÅÏ°ªÀÌ´Ù.

void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE)

¼±Åà ¸ðµå MODE·Î LIST¸¦ ¼¼ÆÃÇÑ´Ù. ¸ðµå´Â GTK_SELECTION_SINGLE, GTK_ SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, GTK_SELECTION_EXTENDED Áß¿¡¼­ Çϳª°¡ µÈ´Ù.

GtkList* GTK_LIST (gpointer OBJ)

´ëºÎºÐ Æ÷ÀÎÅ͸¦ GtkList* ÇüÀ¸·Î ij½ºÆ®ÇÑ´Ù. ´õ ÀÚ¼¼È÷ ¾Ë·Á¸é ÀϹÝÀûÀÎ ¸ÅÅ©·Î¸¦ ÂüÁ¶Ç϶ó.

GtkListClass* GTK_LIST_CLASS (gpointer CLASS)

´ëºÎºÐÀÇ Æ÷ÀÎÅ͸¦ GtkListClass* ÇüÀ¸·Î ij½ºÆ®ÇÑ´Ù. ÀϹÝÀûÀÎ ¸ÅÅ©·Î¸¦ ÂüÁ¶Ç϶ó.

gint GTK_IS_LIST (gpointer OBJ)

¾î¶² ´ëºÎºÐÀÇ Æ÷ÀÎÅÍ°¡ GtkList object¸¦ ÂüÁ¶ÇÏ´ÂÁö °áÁ¤ÇÑ´Ù. ÀÚ¼¼È÷ ¾Ë·Á¸é ÀϹÝÀûÀÎ ¸ÅÅ©·Î¸¦ ÂüÁ¶Ç϶ó.

10.3 ¿¹Á¦

À̹ø ¿¹Á¦´Â GtkListÀÇ ¼±ÅÃÀ» º¯È­½ÃÅ°´Â °ÍÀ» º¸¿©ÁÙ °ÍÀÌ´Ù. ±×¸®°í ¸®½ºÆ® ¾ÆÀÌÅÛµéÀ» ¸¶¿ì½º ¿À¸¥ÂÊ ¹öÆ°À¸·Î ¼±ÅÃÇÔÀ¸·Î½á ±×µéÀ» Àâ¾ÆµÑ ¼ö ÀÖ°Ô ÇÒ °ÍÀÌ´Ù.

/* ÀÌ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÏ·Á¸é ÀÌ·¸°Ô ÇÑ´Ù.
 * $ gcc -I/usr/local/include/ -lgtk -lgdk -lglib -lX11 -lm -Wall main.c
 */

/* GTK+ÀÇ Çì´õ¸¦ includeÇÑ´Ù.
 * printf()ÇÔ¼ö ¶§¹®¿¡ <stdio.h>µµ includeÇÑ´Ù.
 */
#include        <gtk/gtk.h>
#include        <stdio.h>

/* ÀÌ°ÍÀº ¸®½ºÆ® ¾ÆÀÌÅÛ¿¡ µ¥ÀÌÅ͸¦ ÀúÀåÇϱâ À§ÇÑ µ¥ÀÌÅÍ ½Äº°ÀÚ´Ù. */
const   gchar   *list_item_data_key="list_item_data";

/* ¿ì¸®°¡ GtkList widget¿¡ ¿¬°á½Ãų ½Ã±×³Î Çڵ鷯µéÀÇ ÇÔ¼ö¿øÇü. */
static  void    sigh_print_selection    (GtkWidget      *gtklist,
                                         gpointer       func_data);
static  void    sigh_button_event       (GtkWidget      *gtklist,
                                         GdkEventButton *event,
                                         GtkWidget      *frame);

/* »ç¿ëÀÚ ÀÎÅÍÆäÀ̽º¸¦ ¼¼ÆÃÇÏ´Â main ÇÔ¼ö */

gint main (int argc, gchar *argv[])
{
                GtkWidget       *separator;
                GtkWidget       *window;
                GtkWidget       *vbox;
                GtkWidget       *scrolled_window;
                GtkWidget       *frame;
                GtkWidget       *gtklist;
                GtkWidget       *button;
                GtkWidget       *list_item;
                GList           *dlist;
                guint           i;
                gchar           buffer[64];

                /* gtk+(±×¸®°í °á°úÀûÀ¸·Î gdkµµ)¸¦ ÃʱâÈ­ÇÑ´Ù. */

                gtk_init(&argc, &argv);

                /* ¸ðµç widgetÀ» ³Ö¾îµÑ À©µµ¸¦ ¸¸µç´Ù.
                 * À©µµ ¸Å´ÏÀúÀÇ close-window-event¸¦ ´Ù·ç±â À§ÇØ gtk_main_quit()
                 * ÇÔ¼ö¸¦ À©µµÀÇ "destroy" À̺¥Æ®¿¡ ¿¬°á½ÃŲ´Ù. */
                window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
                gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
                gtk_signal_connect(GTK_OBJECT(window),
                                                                                         "destroy",
                                                                                         GTK_SIGNAL_FUNC(gtk_main_quit),
                                                                                         NULL);

                /* À©µµ ³»ºÎ¿¡ widgetµéÀ» ¼öÁ÷À¸·Î Á¤·ÄÇÒ ¹Ú½º°¡ ÀÖ¾î¾ß ÇÑ´Ù. */
                vbox=gtk_vbox_new(FALSE, 5);
                gtk_container_border_width(GTK_CONTAINER(vbox), 5);
                gtk_container_add(GTK_CONTAINER(window), vbox);
                gtk_widget_show(vbox);
                /* GtkList widgetÀ» ³Ö¾îµÎ°íÀÚ ÇÏ´Â ½ºÅ©·ÑµÈ À©µµ´Ù. */
                scrolled_window=gtk_scrolled_window_new(NULL, NULL);
                gtk_widget_set_usize(scrolled_window, 250, 150);
                gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
                gtk_widget_show(scrolled_window);

                /* GtkList widgetÀ» ¸¸µç´Ù.  selectionÀÌ º¯ÇÒ ¶§¸¶´Ù ±× ¼±ÅõÈ
                 * ¾ÆÀÌÅÛÀ» ÇÁ¸°Æ®ÇØ º¸¿©ÁÖ±â À§ÇØ sigh_print_selection()
                 * ½Ã±×³Î Çڵ鷯 ÇÔ¼ö¸¦ GtkListÀÇ "selection_changed" ½Ã±×³Î¿¡
                 * ¿¬°á½ÃÄÑ µÐ´Ù. */
                gtklist=gtk_list_new();
                gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist);
                gtk_widget_show(gtklist);
                gtk_signal_connect(GTK_OBJECT(gtklist),
                                                                                         "selection_changed",
                                                                                         GTK_SIGNAL_FUNC(sigh_print_selection),
                                                                                         NULL);

                /* ¸®½ºÆ® ¾ÆÀÌÅÛÀ» °¡µÎ¾î µÑ "Prison"À» ¸¸µç´Ù. ;) */
                frame=gtk_frame_new("Prison");
                gtk_widget_set_usize(frame, 200, 50);
                gtk_container_border_width(GTK_CONTAINER(frame), 5);
                gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
                gtk_container_add(GTK_CONTAINER(vbox), frame);
                gtk_widget_show(frame);

                /* ¸®½ºÆ® ¾ÆÀÌÅÛÀÇ "arresting"À» ´Ù·ê GtkList¿¡ sigh_button_event()
                 * ½Ã±×³Î Çڵ鷯¸¦ ¿¬°á½ÃŲ´Ù. */
                gtk_signal_connect(GTK_OBJECT(gtklist),
                                                                                         "button_release_event",
                                                                                         GTK_SIGNAL_FUNC(sigh_button_event),
                                                                                         frame);

                /* Separator¸¦ ¸¸µç´Ù. */
                separator=gtk_hseparator_new();
                gtk_container_add(GTK_CONTAINER(vbox), separator);
                gtk_widget_show(separator);

                /* ³¡À¸·Î ¹öÆ°À» ¸¸µé°í ±×°ÍÀÇ "clicked" ½Ã±×³ÎÀ» À©µµÀÇ Æı«¿¡
                 * ¿¬°á½ÃŲ´Ù. */
                button=gtk_button_new_with_label("Close");
                gtk_container_add(GTK_CONTAINER(vbox), button);
                gtk_widget_show(button);
                gtk_signal_connect_object(GTK_OBJECT(button),
                                  "clicked",
                                  GTK_SIGNAL_FUNC(gtk_widget_destroy),
                                  GTK_OBJECT(window));

                /* ÀÌÁ¦ °¢°¢ ¶óº§À» °¡Áö°í ÀÖ´Â 5°³ÀÇ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» ¸¸µé°í,
                 * gtk_container_add()·Î½á ±×µéÀ» GtkList¿¡ ÷°¡ÇÑ´Ù.
                 * ¶ÇÇÑ ¶óº§ÀÇ ÅؽºÆ® ¹®ÀÚ¿­À» Á¶»çÇÏ°í ±×°ÍÀ» °¢ ¸®½ºÆ® ¾ÆÀÌÅÛÀÇ
                 * list_item_data_key¿¡ °áÇÕ½ÃŲ´Ù. */
                for (i=0; i<5; i++) {
                                GtkWidget       *label;
                                gchar           *string;

                                sprintf(buffer, "ListItemContainer with Label #%d", i);
                                label=gtk_label_new(buffer);
                                list_item=gtk_list_item_new();
                                gtk_container_add(GTK_CONTAINER(list_item), label);
                                gtk_widget_show(label);
                                gtk_container_add(GTK_CONTAINER(gtklist), list_item);
                                gtk_widget_show(list_item);
                                gtk_label_get(GTK_LABEL(label), &string);
                                gtk_object_set_data(GTK_OBJECT(list_item),
                                    list_item_data_key,
                                    string);
                }
                /* ¿©±â¼­´Â, gtk_list_item_new_with_label()À» ÀÌ¿ëÇؼ­
                 * ´Ù¸¥ 5°³ÀÇ ¶óº§À» ¸¸µç´Ù.
                 * À̹ø¿¡´Â ¶óº§µé¿¡ ´ëÇÑ Æ÷ÀÎÅÍ°¡ ¾øÀ¸¹Ç·Î ¶óº§ÀÇ ÅؽºÆ®
                 * ¹®ÀÚ¿­À» Á¶»çÇÒ ¼ö ¾ø°í, ±×·¯¹Ç·Î °¢ ¸®½ºÆ® ¾ÆÀÌÅÛÀÇ
                 * list_item_data_key¸¦ ¶È°°Àº ÅؽºÆ® ¹®ÀÚ¿­¿¡ °áÇÕÇÑ´Ù.
                 * ¸®½ºÆ® ¾ÆÀÌÅÛÀ» Ãß°¡Çϱâ À§Çؼ­ ¿ì¸®´Â ±×µéÀ» ÀÌÁß ¿¬°á
                 * ¸®½ºÆ®(GList)¿¡ ¹Ð¾î³Ö°í, gtk_list_append_items()¸¦ 
                 * È£ÃâÇØÁØ´Ù.  ¿ì¸®°¡ ¾ÆÀÌÅÛµéÀ» ÀÌÁß ¿¬°á ¸®½ºÆ®¿¡ ¹Ð¾î³Ö±â
                 * À§ÇØ g_list_prepend()¸¦ »ç¿ëÇϱ⠶§¹®¿¡, ±×µéÀÇ ¼ø¼­´Â
                 * µÚ·Î À̾îÁö´Â(descending) °ÍÀÌ µÈ´Ù.  ¹Ý´ë·Î g_list_append()
                 * ¸¦ ÀÌ¿ëÇß´Ù¸é ¾Õ¿¡¼­ ºÙ¿©Áö´Â(ascending)ÀÌ µÉ °ÍÀÌ´Ù. */
                dlist=NULL;
                for (; i<10; i++) {
                                sprintf(buffer, "List Item with Label %d", i);
                                list_item=gtk_list_item_new_with_label(buffer);
                                dlist=g_list_prepend(dlist, list_item);
                                gtk_widget_show(list_item);
                                gtk_object_set_data(GTK_OBJECT(list_item),
                                    list_item_data_key,
                                    "ListItem with integrated Label");
                }
                gtk_list_append_items(GTK_LIST(gtklist), dlist);

                /* ³¡À¸·Î ¿ì¸®´Â À©µµ¸¦ º¸°í ½Í¾î ÇÑ´Ù, ¾Æ´Ñ°¡? ;) */
                gtk_widget_show(window);

                /* GTKÀÇ main À̺¥Æ® ·çÇÁ¸¦ ½Ãµ¿ÇÑ´Ù. */
                gtk_main();

                /* gtk_main_quit()ÀÌ È£ÃâµÇ¸é Á¦¾î´Â ¿©±â·Î ¿Â´Ù. */
                return 0;
}

/* GtkListÀÇ ¹öÆ° press/release À̺¥Æ®µé°ú ¿¬°áµÈ ½Ã±×³Î
 * Çڵ鷯 ÇÔ¼öµéÀÌ´Ù. */
void
sigh_button_event       (GtkWidget      *gtklist,
                         GdkEventButton *event,
                         GtkWidget      *frame)
{
                /* ¼¼¹ø°, Áï °¡Àå ¿À¸¥ÂÊ¿¡ ÀÖ´Â ¸¶¿ì½º ¹öÆ°ÀÌ ³õ¿©Á³À» ¶§¸¸
                 * ¾î¶² ÀÏÀ» Çϵµ·Ï ÇÑ´Ù. */
                if (event->type==GDK_BUTTON_RELEASE &&
                                event->button==3) {
                                GList           *dlist, *free_list;
                                GtkWidget       *new_prisoner;

                                /* ÇöÀç ¼±ÅÃµÈ ¾ÆÀÌÅÛÀ» °¡Á®¿Í¼­ ¿ì¸®ÀÇ ´ÙÀ½ prisoner·Î
                                 * ÇÑ´Ù. */
                                dlist=GTK_LIST(gtklist)->selection;
                                if (dlist)
                                                                new_prisoner=GTK_WIDGET(dlist->data);
                                else
                                                                new_prisoner=NULL;

                                /* ÀÌ¹Ì »ç·ÎÀâÀº ¸®½ºÆ® ¾ÆÀÌÅÛÀ» Á¶»çÇÏ°í, ±×µéÀ»
                                 * ´Ù½Ã ¸®½ºÆ®·Î µ¹·ÁÁØ´Ù.
                                 * gtk_container_children()ÀÌ ¸®ÅÏÇÏ´Â ÀÌÁß ¿¬°á ¸®½ºÆ®¸¦
                                 * ²À ÇØÁ¦(free)ÇØÁà¾ß ÇÔÀ» ±â¾ïÇ϶ó. */
                                dlist=gtk_container_children(GTK_CONTAINER(frame));
                                free_list=dlist;
                                while (dlist) {
                                                GtkWidget       *list_item;

                                                list_item=dlist->data;

                                                gtk_widget_reparent(list_item, gtklist);

                                                dlist=dlist->next;
                                }
                                g_list_free(free_list);

                                /* »õ·Î prisoner¸¦ °¡Áö°Ô µÇ¸é, GtkList·ÎºÎÅÍ ±×°ÍÀ»
                                 * Á¦°ÅÇÏ°í "Prison" ÇÁ·¹ÀÓÀ¸·Î ¹Ð¾î³Ö´Â´Ù.
                                 * ¾ÆÀÌÅÛÀº ¸ÕÀú unselectµÇ¾î¾ß ÇÑ´Ù. */
                                if (new_prisoner) {
                                                GList   static_dlist;

                                                static_dlist.data=new_prisoner;
                                                static_dlist.next=NULL;
                                                static_dlist.prev=NULL;

                                                gtk_list_unselect_child(GTK_LIST(gtklist),
                                                new_prisoner);
                                                gtk_widget_reparent(new_prisoner, frame);
                                }
                }
}

/* ÀÌ°ÍÀº GtkList°¡ "selection_changed" ½Ã±×³ÎÀ» ¹ß»ý½ÃÅ°¸é
 * È£ÃâµÇ´Â ½Ã±×³Î Çڵ鷯´Ù. */
void
sigh_print_selection    (GtkWidget      *gtklist,
                                         gpointer       func_data)
{
                GList   *dlist;

                /* GtkListÀÇ ¼±ÅÃµÈ ¾ÆÀÌÅÛÀÇ ÀÌÁß ¿¬°á ¸®½ºÆ®¸¦ °¡Á®¿Â´Ù.
                 * ÀÌ°ÍÀ» read-only·Î ´Ù·ï¾ß ÇÔÀ» ÀØÁö ¸»ÀÚ! */
                dlist=GTK_LIST(gtklist)->selection;

                /* ¼±ÅÃµÈ ¾ÆÀÌÅÛÀÌ ¾øÀ» ¶§´Â ¾Æ¹« ÀÛ¾÷µµ ÇÒ °Ô ¾ø°í ±×°É
                 * »ç¿ëÀÚ¿¡°Ô ¾Ë·ÁÁØ´Ù. */
                if (!dlist) {
                                g_print("Selection cleared\n");
                                return;
                }
                /* ¹º°¡¸¦ ¼±ÅÃÇß°í ±×°ÍÀ» ÇÁ¸°Æ®ÇÑ´Ù. */
                g_print("The selection is a ");

                /* ÀÌÁß ¿¬°á ¸®½ºÆ®¿¡¼­ ¸®½ºÆ® ¾ÆÀÌÅÛÀ» ÃëÇÏ°í
                 * list_item_data_key¿Í °ü·ÃµÈ µ¥ÀÌÅ͸¦ Á¶»çÇÑ´Ù.
                 * ±×¸®°í ³ª¼­ ±×°É ÇÁ¸°Æ®ÇÑ´Ù. */
                while (dlist) {
                                GtkObject       *list_item;
                                gchar           *item_data_string;

                                list_item=GTK_OBJECT(dlist->data);
                                item_data_string=gtk_object_get_data(list_item,
                                                                                                         list_item_data_key);
                                g_print("%s ", item_data_string);

                                dlist=dlist->next;
                }
                g_print("\n");
}

10.4 ¸®½ºÆ® ¾ÆÀÌÅÛ widget

GtkListItem widgetÀº ÇϳªÀÇ child¸¦ ³Ö¾îµÑ ¼ö ÀÖ´Â ÄÁÅ×À̳Êó·³ ÀÛµ¿Çϵµ·Ï ¼³°èµÇ¾úÀ¸¸ç, GtkList widgetÀÌ ±×ÀÇ childµéÀ» À§ÇØ ±×·¯ÇϵíÀÌ ÀÌ°Í ¿ª½Ã selection/deselection ÇÔ¼öµéÀ» Á¦°øÇÏ°í ÀÖ´Ù.

GtkListItemÀº À̺¥Æ®¸¦ ¹Þ±â À§Çؼ­ ÀڽŸ¸ÀÇ À©µµ¸¦ °¡Áö°í ÀÖ°í, ¶ÇÇÑ º¸Åë whiteÀÎ ÀڽŸ¸ÀÇ background »ö±òµµ °¡Áö°í ÀÖ´Ù.

ÀÌ°ÍÀÌ GtkItemÀ¸·ÎºÎÅÍ Á÷Á¢ÀûÀ¸·Î ÆÄ»ýµÇ¾ú±â ¶§¹®¿¡ ¿ª½Ã GTK_ITEM( ListItem) ¸ÅÅ©·Î·Î ´Ù·ç¾îÁú ¼ö ÀÖÀ¸¸ç, ÀÚ¼¼ÇÑ °ÍÀº GtkItem widgetÀ» ÂüÁ¶ÇÏ¸é µÉ °ÍÀÌ´Ù. ´ë°³ GtkListItemÀº ½Äº°µÇ±â À§ÇÑ ¶óº§À» °¡Áö°í ÀÖ´Ù, ¿¹¸¦ µé¸é GtkList¿¡ ÀÖ´Â filenameó·³. µû¶ó¼­ convenient ÇÔ¼ö gtk_list_item_new_with _label()ÀÌ Á¦°øµÈ´Ù. °°Àº È¿°ú¸¦ ÀڽŸ¸ÀÇ GtkLabelÀ» ¸¸µêÀ¸·Î½á ¾òÀ» ¼ö ÀÖ´Ù. GtkListItem¿¡ µÚÀ̾îÁö´Â ÄÁÅ×ÀÌ³Ê¿Í ÇÔ²² xalign=0, yalign=0.5·Î ¼¼ÆÃÇÏ¸é µÈ´Ù.

GtkListItem¿¡ ²À GtkLabelÀ» ´õÇØ ÁÖ´Â °ÍÀº ¾Æ´Ï¸ç, ¿ì¸®´Â GtkVBox ¶Ç´Â GtkArrow µîÀ» ´õÇØÁÙ ¼öµµ ÀÖ´Ù.

10.5 ½Ã±×³Î

GtkListItemÀº ÀڽŸ¸ÀÇ ½Ã±×³ÎÀ» »õ·Î ¸¸µéÁö´Â ¾Ê°í, GtkItemÀÇ ½Ã±×³ÎÀ» »ó¼Ó¹Þ´Â´Ù. ÀÚ¼¼ÇÑ °ÍÀº GtkItem¿¡ ´ëÇؼ­ ÂüÁ¶Ç϶ó.

10.6 ÇÔ¼ö

guint gtk_list_item_get_type (void)

GtkListItemÇüÀÇ ½Äº°ÀÚ¸¦ ¸®ÅÏÇÑ´Ù.

GtkWidget* gtk_list_item_new (void)

»õ·Î¿î GtkListItem object¸¦ ¸¸µç´Ù. ÀÌ »õ·Î¿î widgetÀº GtkWidget object ¸¦ ÇâÇÑ Æ÷ÀÎÅͷμ­ ¸®ÅϵȴÙ. 'NULL'Àº ½ÇÆÐÇßÀ» °æ¿ìÀÇ ¸®ÅÏ°ªÀÌ´Ù.

GtkWidget* gtk_list_item_new_with_label (gchar *LABEL)

Çϳª»ÓÀÎ child·Î ÇϳªÀÇ GtkLabelÀ» °¡Áö¸ç GtkListItem object¸¦ ¸¸µç´Ù. ÀÌ »õ·Î¿î widgetÀº GtkWidget object¸¦ ÇâÇÑ Æ÷ÀÎÅͷμ­ ¸®ÅϵȴÙ. 'NULL'Àº ½ÇÆÐÇßÀ» ¶§ÀÇ ¸®ÅÏ°ªÀÌ´Ù.

void gtk_list_item_select (GtkListItem *LIST_ITEM)

ÀÌ°ÍÀº ±Ùº»ÀûÀ¸·Î, GtkItem::select ½Ã±×³ÎÀ» ¹ß»ýÇÒ gtk_item_select¸¦ È£ÃâÇÏ´Â µ¥ À־ÀÇ wrapper´Ù(GTK_ITEM(list_item)). ÀÚ¼¼ÇÑ °ÍÀº GtkItemÀ» ÂüÁ¶Ç϶ó.

void gtk_list_item_deselect (GtkListItem *LIST_ITEM)

ÀÌ°ÍÀº GtkItem::deselect ½Ã±×³ÎÀ» ¹ß»ýÇÒ gtk_item_deselect¸¦ È£ÃâÇÏ´Â µ¥ À־ÀÇ wrapper´Ù(GTK_ITEM(list_item)). ¿ª½Ã ÀÚ¼¼ÇÑ °ÍÀº GtkItemÀ» ÂüÁ¶ Ç϶ó.

GtkListItem* GTK_LIST_ITEM (gpointer OBJ)

´ëºÎºÐÀÇ Æ÷ÀÎÅ͸¦ GtkListItem*À¸·Î ij½ºÆ®ÇÑ´Ù. ÀÚ¼¼ÇÑ °ÍÀº ÀϹÝÀûÀÎ ¸ÅÅ©·Î¸¦ ÂüÁ¶Ç϶ó.

GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS)

´ëºÎºÐÀÇ Æ÷ÀÎÅ͸¦ GtkListItemClass*·Î ij½ºÆ®ÇÑ´Ù. ¿ª½Ã ÀϹÝÀûÀÎ ¸ÅÅ©·Î¿¡ ´ëÇÑ ºÎºÐÀ» ÂüÁ¶Ç϶ó.

gint GTK_IS_LIST_ITEM (gpointer OBJ)

¾î¶² Æ÷ÀÎÅÍ°¡ GtkListItem object¸¦ ÂüÁ¶ÇÏ°í ÀÖ´ÂÁö¸¦ °áÁ¤ÇÑ´Ù. ÀÚ¼¼ÇÑ °ÍÀº ÀϹÝÀûÀÎ ¸ÅÅ©·Î¿¡ ´ëÇؼ­ ÂüÁ¶Ç϶ó.

10.7 ¿¹Á¦

GtkList¿¡ ´ëÇÑ ¿¹Á¦¸¦ ÂüÁ¶Ç϶ó. ±×°ÍÀº GtkListItemÀÇ ÀÌ¿ë¹ý¿¡ ´ëÇؼ­µµ Àß ´Ù·ç°í ÀÖ´Ù.

11. ¸Þ´º widget

¸Þ´º¸¦ ¸¸µé±â À§ÇØ ½¬¿î ¹æ¹ý°ú ¾î·Á¿î ¹æ¹ý µÎ°¡Áö°¡ ÀÖ´Ù. °¢°¢ ¾²ÀÏ µ¥°¡ ÀÖ´Â °ÍµéÀÌÁö¸¸, ¿ì¸®´Â º¸Åë ½¬¿î ¹æ¹ýÀ¸·Î menu_factory¸¦ ¾²´Â ÂÊÀ» ÅÃÇÒ °ÍÀÌ´Ù. "¾î·Á¿î" ¹æ¹ýÀ̶õ ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ Á÷Á¢ÀûÀ¸·Î ¸Þ´º¸¦ ¸¸µå´Â °ÍÀÌ´Ù. ±×¸®°í ½¬¿î ¹æ¹ýÀº gtk_menu_factory ÇÔ¼öµéÀ» ¾²´Â °ÍÀÌ´Ù. ÀÌ°ÍÀº ÈξÀ °£´ÜÇÏÁö¸¸, ³ª¸§´ë·Î ÀåÁ¡°ú ´ÜÁ¡À» °¡Áö°í ÀÖ´Ù.

¼öµ¿ÀûÀÎ ¹æ¹ýÀ¸·Î ¸î °¡Áö wrapper ÇÔ¼öµéÀ» ½á °¡¸ç ¸Þ´º¸¦ ¸¸µå´Â °ÍÀÌ À¯¿ë¼º¿¡ À־ ÈξÀ À¯¸®ÇÔ¿¡µµ ºÒ±¸ÇÏ°í, menufactory¸¦ ÀÌ¿ëÇÏ´Â ¹æ¹ýÀº ÈξÀ »ç¿ëÇϱ⠽±°í ¶Ç »õ·Î¿î ¸Þ´º¸¦ Ãß°¡Çϱ⵵ ½±´Ù. Menufactory¸¦ ÀÌ¿ëÇÏ°Ô µÇ¸é, ¸Þ´º¿¡ À̹ÌÁö¶óµç°¡ '/'¸¦ ¾²´Â °ÍÀÌ ºÒ°¡´ÉÇØÁø´Ù.

11.1 ¼öµ¿ÀûÀ¸·Î ¸Þ´º ¸¸µé±â

±³À°ÀÇ ¹Ù¶÷Á÷ÇÑ ÀüÅë¿¡ µû¶ó, ¸ÕÀú ¾î·Á¿î ¹æ¹ýºÎÅÍ º¸ÀÌ°Ú´Ù.:)

¸Þ´º¹Ù¿Í ÇÏÀ§¸Þ´º(submenu)µé¸¦ ¸¸µå´Âµ¥ ¾²´Â ¼¼°¡Áö widgetÀÌ ÀÖ´Ù.

  • ¸Þ´º ¾ÆÀÌÅÛ(menu item) : »ç¿ëÀÚ°¡ ¼±ÅÃÇÏ´Â ¹Ù·Î ±×°ÍÀÌ´Ù. (¿¹: 'Save')
  • ¸Þ´º(menu) : ¸Þ´º ¾ÆÀÌÅÛµéÀÇ ÄÁÅ×À̳ÊÀÌ´Ù.
  • ¸Þ´º¹Ù(menubar) : °¢°¢ÀÇ ¸Þ´ºµéÀ» Æ÷ÇÔÇÏ´Â ÄÁÅ×À̳ÊÀÌ´Ù.

¸Þ´º ¾ÆÀÌÅÛ widgetÀÌ µÎ°¡Áö ´Ù¸¥ ¿ëµµ·Î ¾²ÀÏ ¼ö ÀÖ´Ù´Â Á¡¶§¹®¿¡ ¾à°£ º¹ÀâÇÑ ¸éÀÌ ÀÖ´Ù. ¸Þ´º ¾ÆÀÌÅÛÀº ´Ü¼øÈ÷ ¸Þ´º À§¿¡ ³õÀÏ ¼öµµ ÀÖ°í ¶Ç´Â ¸Þ´º¹Ù À§¿¡ ³õ¿©¼­ ¼±ÅõǾúÀ» ¶§ ƯÁ¤ ¸Þ´º¸¦ È°¼ºÈ­½ÃÅ°µµ·Ï ¾²ÀÏ ¼öµµ ÀÖ´Ù.

¸Þ´º¿Í ¸Þ´º¹Ù¸¦ ¸¸µé±â À§ÇØ ¾²ÀÌ´Â ÇÔ¼öµéÀ» »ìÆ캸ÀÚ. ÀÌ Ã¹¹ø° ÇÔ¼ö´Â »õ·Î¿î ¸Þ´º¹Ù¸¦ ¸¸µé±â À§ÇØ ¾²ÀδÙ.

GtkWidget *gtk_menu_bar_new()

ÀÌ°ÍÀº À̸§ ±×´ë·Î »õ·Î¿î ¸Þ´º¹Ù¸¦ ¸¸µç´Ù. ¹öÆ°°ú ¸¶Âù°¡Áö·Î, ¿ì¸®´Â ÀÌ°ÍÀ» À©µµ¿¡ ÆÐÅ·Çϱâ À§ÇØ gtk_container_add¸¦ ÀÌ¿ëÇÒ¼öµµ ÀÖ°í, ¶Ç´Â ¹Ú½º¿¡ ÆÐÅ·Çϱâ À§ÇØ box_pack ÇÔ¼öµéÀ» ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. - ¹öÆ°°ú °°´Ù.

GtkWidget *gtk_menu_new();

ÀÌ ÇÔ¼ö´Â »õ·Î¿î ¸Þ´º¸¦ ÇâÇÑ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇϴµ¥, ÀÌ°ÍÀº ½ÇÁ¦·Î º¸¿©ÁöÁö´Â ¾Ê°í(gtk_widget_show¸¦ ÅëÇØ) ´Ù¸¸ ¸Þ´º ¾ÆÀÌÅÛµéÀ» °¡Áö°í¸¸ ÀÖ´Ù. ÀÌ ¾Æ·¡¿¡ ³ª¿À´Â ¿¹Á¦¸¦ º¸¸ç ´õ ¸íÈ®È÷ ÀÌÇØÇϱ⸦ ¹Ù¶õ´Ù.

À̹øÀÇ µÎ ÇÔ¼ö´Â ¸Þ´º³ª ¸Þ´º¹Ù ¾ÈÀ¸·Î ÆÐÅ·µÇ´Â ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µé±â À§ÇØ ¾²ÀδÙ.

GtkWidget *gtk_menu_item_new()

GtkWidget *gtk_menu_item_new_with_label(const char *label)

ÀÌ ÇÔ¼öµéÀº º¸¿©Áö±â À§ÇÑ ¸Þ´º¸¦ ¸¸µé ¶§ ¾²ÀδÙ. gtk_menu_new·Î½á ¸¸µé¾îÁö´Â "¸Þ´º"¿Í gtk_menu_item_new·Î½á ¸¸µé¾îÁö´Â "¸Þ´º ¾ÆÀÌÅÛ"À» ²À ±¸º°ÇØ¾ß ÇÑ´Ù. ¸Þ´º ¾ÆÀÌÅÛÀº ¿¬°áµÈ µ¿ÀÛÀÌ ÀÖ´Â ½ÇÁ¦ÀÇ ¹öÆ°ÀÌ µÉ °ÍÀÌÁö¸¸, ¹Ý¸é ¸Þ´º´Â À̰͵éÀ» °¡Áö°í ÀÖ´Â ÄÁÅ×À̳ʰ¡ µÉ °ÍÀÌ´Ù.

gtk_menu_new_with_label°ú ´Ü¼øÇÑ gtk_menu_new ÇÔ¼ö´Â ¿©·¯ºÐÀÌ ¹öÆ°¿¡ ´ëÇØ °øºÎÇÑ ÈÄ¿¡ ÁüÀÛÇÏ´Â ±×´ë·Î´Ù. gtk_menu_new_with_labelÀº ¶óº§ÀÌ ÀÌ¹Ì ÆÐÅ·µÇ¾î ÀÖ´Â ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µé°í, gtk_menu_new´Â ºñ¾îÀÖ´Â ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µç´Ù.

Çѹø ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µé¸é ¹Ýµå½Ã À̸¦ ¸Þ´º ¾È¿¡ ³Ö¾î¾ß¸¸ ÇÑ´Ù. ÀÌ´Â gtk_menu_append ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ ÀÌ·ç¾îÁø´Ù. ¾î¶² ¾ÆÀÌÅÛÀÌ »ç¿ëÀÚ¿¡ ÀÇÇØ ¼±ÅõǾúÀ» ¶§ À̸¦ ¾Ë¾Æ³»¾î ó¸®Çϱâ À§Çؼ­´Â activate ½Ã±×³ÎÀ» Åë»óÀûÀ¸·Î ÇϵíÀÌ ¿¬°áÇÑ´Ù. ±×·¡¼­ ¸¸ÀÏ Open, Save, Quit ¿É¼ÇÀ» °¡Áø Ç¥ÁØ File ¸Þ´º¸¦ ¸¸µé°íÀÚ ÇÑ´Ù¸é ¼Ò½º ÄÚµå´Â ´ÙÀ½°ú °°ÀÌ µÈ´Ù.

file_menu = gtk_menu_new();    /* ¸Þ´º¸¦ º¸¿©ÁÙ ÇÊ¿ä´Â ¾ø´Ù. */

/* ¸Þ´º ¾ÆÀÌÅÛµéÀ» ¸¸µç´Ù. */
open_item = gtk_menu_item_new_with_label("Open");
save_item = gtk_menu_item_new_with_label("Save");
quit_item = gtk_menu_item_new_with_label("Quit");

/* ±×°ÍµéÀ» ¸Þ´º¿¡ ºÙÀδÙ. */
gtk_menu_append( GTK_MENU(file_menu), open_item);
gtk_menu_append( GTK_MENU(file_menu), save_item);
gtk_menu_append( GTK_MENU(file_menu), quit_item);

/* "activate" ½Ã±×³Î°ú callback ÇÔ¼ö¸¦ ¿¬°áÇÑ´Ù. */
gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
                   GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
                   GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");

/* Quit ¸Þ´º ¾ÆÀÌÅÛ¿¡  exit ÇÔ¼ö¸¦ ¿¬°áÇÑ´Ù. */
gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
                   GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");

/* ÀÌÁ¦ ¸Þ´º ¾ÆÀÌÅÛµéÀ» º¸¿©Áà¾ß ÇÑ´Ù. */
gtk_widget_show( open_item );
gtk_widget_show( save_item );
gtk_widget_show( quit_item );

¿©±â±îÁöÇϸé ÇÊ¿äÇÑ ¸Þ´º´Â ÀÏ´Ü ¸¸µç °ÍÀÌ´Ù. ÀÌÁ¦ Áö±Ý±îÁö ¸¸µç ¸Þ´º¸¦ ºÙÀÏ File ¸Þ´º ¾ÆÀÌÅÛ°ú ¸Þ´º¹Ù¸¦ ¸¸µé¾î¾ß ÇÑ´Ù. ÄÚµå´Â ÀÌ·¸°Ô µÈ´Ù.

menu_bar = gtk_menu_bar_new();
gtk_container_add( GTK_CONTAINER(window), menu_bar);
gtk_widget_show( menu_bar );

file_item = gtk_menu_item_new_with_label("File");
gtk_widget_show(file_item);

ÀÌÁ¦ file_itemÀ» ¸Þ´º¿Í ¿¬°áÇØ¾ß ÇÑ´Ù. ÀÌ°ÍÀº ´ÙÀ½ ÇÔ¼ö¸¦ ÅëÇØ ÀÌ·ç¾îÁø´Ù.

void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, GtkWidget *submenu);

±×·¡¼­ ¿ì¸® ¿¹Á¦´Â ´ÙÀ½ ÄÚµå·Î À̾îÁø´Ù.

gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu);

ÇؾßÇÒ ³²Àº ¸ðµç ÀÏÀº ¸Þ´º¸¦ ¸Þ´º¹Ù¿¡ ºÙÀÌ´Â ÀÏÀÌ´Ù. ÀÌ´Â ´ÙÀ½ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);

¿ì¸® Äڵ忡¼­´Â ´ÙÀ½°ú °°ÀÌ µÈ´Ù.

gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );

¸¸ÀÏ ¸Þ´ºµéÀÌ help ¸Þ´º°¡ ÀÚÁÖ ±×·¯´Â °Íó·³ ¸Þ´º¹ÙÀÇ ¿À¸¥ÂÊ¿¡ À§Ä¡ÇÏ°Ô ÇÏ°í ½Í´Ù¸é ¸Þ´º¹Ù¿¡ ¸Þ´º¸¦ ºÙÀ̱â Àü¿¡ ´ÙÀ½ ÇÔ¼ö¸¦ ¾´´Ù. (ÇöÀç ¿¹Á¦¶ó¸é ÀÎÀÚ·Î file_itemÀ» ÁÖ¸é µÈ´Ù.)

void gtk_menu_item_right_justify (GtkMenuItem *menu_item);

´ÙÀ½Àº ¸Þ´ºµéÀÌ ´Þ·ÁÀÖ´Â ¸Þ´º¹Ù¸¦ ¸¸µå´Â ´Ü°èµé¿¡ ´ëÇÑ ¿ä¾àÀÌ´Ù.

  • gtk_menu_new()¸¦ ÀÌ¿ëÇؼ­ »õ·Î¿î ¸Þ´º¸¦ ¸¸µç´Ù.
  • gtk_menu_item_new()¸¦ ¿©·¯¹ø ÀÌ¿ëÇؼ­ ¸Þ´º¿¡ ÇÊ¿äÇÑ °¢°¢ÀÇ ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µç´Ù. ±×¸®°í gtk_menu_append()¸¦ ÀÌ¿ëÇؼ­ »õ ¾ÆÀÌÅÛµéÀ» ¸Þ´º¿¡ ³Ö´Â´Ù.
  • gtk_menu_item_new()¸¦ »ç¿ëÇؼ­ ¸Þ´º ¾ÆÀÌÅÛÀ» Çϳª ¸¸µç´Ù. ÀÌ ¾ÆÀÌÅÛÀº ÀÚ½ÅÀÇ ÅؽºÆ®°¡ ¸Þ´º¹Ù À§¿¡ Á÷Á¢ ³ªÅ¸³ª´Â root ¸Þ´º ¾ÆÀÌÅÛÀÌ µÈ´Ù.
  • gtk_menu_item_set_submenu()¸¦ »ç¿ëÇؼ­ ¸Þ´º¸¦ root ¸Þ´º ¾ÆÀÌÅÛ¿¡ ºÙÀδÙ.(¹Ù·Î À§ ´Ü°è¿¡¼­ ¸¸µç ¸Þ´º ¾ÆÀÌÅÛ)
  • gtk_menu_bar_new()¸¦ ÀÌ¿ëÇؼ­ »õ·Î¿î ¸Þ´º¹Ù¸¦ ¸¸µç´Ù. ÀÌ ´Ü°è´Â ÇÑ ¸Þ´º¹Ù À§¿¡ ¿©·¯ ÀÏ·ÃÀÇ ¸Þ´º¸¦ ¸¸µé¾úÀ» ¶§ Çѹø¸¸ ÇÊ¿äÇÏ´Ù.
  • gtk_menu_bar_append()¸¦ ÀÌ¿ëÇؼ­ ¸Þ´º¹Ù À§¿¡ root ¸Þ´º¸¦ ³õ´Â´Ù.

Æ˾÷¸Þ´º¸¦ ¸¸µå´Â °Íµµ °ÅÀÇ °°´Ù. ´Ù¸¥ Á¡ÀÌ ÀÖ´Ù¸é ¸Þ´º´Â ¸Þ´º¹Ù¿¡ ÀÇÇØ ÀÚµ¿ÀûÀ¸·Î ºÙ¿©Áö´Â °ÍÀÌ ¾Æ´Ï¶ó, button_press À̺¥Æ®·ÎºÎÅÍ gtk_menu_popup() ÇÔ¼ö¸¦ È£ÃâÇÔÀ¸·Î½á ºÙ¿©Áø´Ù´Â °ÍÀÌ´Ù. ÀÌ °úÁ¤À» µû¶óº¸ÀÚ.

  • À̺¥Æ® Çڵ鸵 ÇÔ¼ö¸¦ ¸¸µç´Ù. ÀÌ°ÍÀº ÀÌ·± ¿øÇüÀ» °¡Á®¾ß ÇÑ´Ù.
    static gint handler(GtkWidget *widget, GdkEvent *event);
    ±×¸®°í ÀÌ°ÍÀº ¸Þ´º¸¦ Æ˾÷½Ãų °÷À» ã±â À§ÇØ À̺¥Æ®¸¦ ÀÌ¿ëÇÒ °ÍÀÌ´Ù.
  • À̺¥Æ® Çڵ鷯¿¡¼­´Â, ¸¸¾à À̺¥Æ®°¡ ¸¶¿ì½º ¹öÆ°À» ´©¸£´Â °ÍÀ̶ó¸é, À̺¥Æ®¸¦ ¹öÆ° À̺¥Æ®·Î ´Ù·ç°í, gtk_menu_popup()¿¡ Á¤º¸¸¦ ³Ñ°ÜÁÖ´Â ¿¹Á¦ Äڵ忡¼­ º¸Àδë·Î ÀÌ¿ëÇ϶ó.
  • ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© À̺¥Æ® Çڵ鷯¸¦ widget¿¡ °áÇÕ½ÃŲ´Ù.
    gtk_signal_connect_object(GTK_OBJECT(widget), "event", GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu));
    ¿©±â¼­ widget ÀÎÀÚ´Â ¿ì¸®°¡ ¹ÙÀεùÇÒ widgetÀÌ°í, handler ÀÎÀÚ´Â Çڵ鸵 ÇÔ¼ö´Ù. ±×¸®°í menu ÀÎÀÚ´Â gtk_menu_new()·Î½á ¸¸µé¾îÁø ¸Þ´º´Ù. ¿¹Á¦ Äڵ忡¼­ º¸Àδë·Î, ÀÌ°ÍÀº ¸Þ´º¹Ù¿¡ ºÙ¿©Á® ÀÖ´Â ¸Þ´º°¡ µÉ ¼öµµ ÀÖ´Ù.

11.2 ¼öµ¿À¸·Î ¸Þ´º¸¦ ¸¸µå´Â ¿¹Á¦

ÀÌÁ¦ ºÐ¸íÈ÷ Çصαâ À§ÇØ ¿¹Á¦¸¦ º¸µµ·Ï ÇÏÀÚ.

/* menu.c */

#include <gtk/gtk.h>

static gint button_press (GtkWidget *, GdkEvent *);
static void menuitem_response (GtkWidget *, gchar *);

int main (int argc, char *argv[])
{

    GtkWidget *window;
    GtkWidget *menu;
    GtkWidget *menu_bar;
    GtkWidget *root_menu;
    GtkWidget *menu_items;
    GtkWidget *vbox;
    GtkWidget *button;
    char buf[128];
    int i;

    gtk_init (&argc, &argv);

    /* À©µµ¸¦ ¸¸µç´Ù. */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
    gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
    gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                       (GtkSignalFunc) gtk_main_quit, NULL);

    /* menu-widgetÀ» ½ÃÀÛÇÑ´Ù.  ¿©±â¼­ ¸Þ´º widgetµé¿¡ ´ëÇØ
     * gtk_show_widget()À» ¾²¸é ¾ÈµÈ´Ù!
     * ÀÌ°ÍÀº ¸Þ´º ¾ÆÀÌÅÛÀ» °¡Áö°í ÀÖ´Â ¸Þ´º°í, ¿ì¸®°¡ ¾îÇÿ¡¼­
     * "Root Menu"¸¦ Ŭ¸¯ÇßÀ» ¶§ Æ˾÷µÉ °ÍÀÌ´Ù. */
    menu = gtk_menu_new();

    /* ´ÙÀ½À¸·Î ¿ì¸®´Â ¼¼ ¸Þ´º¿£Æ®¸®¸¦ ¸¸µé±â À§ÇØ ÀÛÀº ·çÇÁ¸¦
     * ±¸ÇöÇÑ´Ù.  º¸ÅëÀ̶ó¸é, ¿ì¸®´Â °¢ ¸Þ´º ¾ÆÀÌÅ۵鿡 ´ëÇØ
     * "clicked" ½Ã±×³ÎÀ» Àâ¾Æ³¾ °ÍÀÌ°í, ±×°ÍÀ» À§ÇØ callbackÀ»
     * ¼¼ÆÃÇÒ °ÍÀÌ´Ù.  ±×·¯³ª °ø°£À» Àý¾àÇϱâ À§ÇØ ±× °úÁ¤Àº
     * »ý·«ÇÑ´Ù. */

    for(i = 0; i < 3; i++)
        {
            /* buf·Î ¸Þ´º À̸§À» º¹»çÇÑ´Ù. */
            sprintf(buf, "Test-undermenu - %d", i);

            /* À̸§À» °¡Áø »õ ¸Þ´º ¾ÆÀÌÅÛÀ» ¸¸µç´Ù. */
            menu_items = gtk_menu_item_new_with_label(buf);

            /* ÀÌ°ÍÀ» ¸Þ´º¿¡ ÷°¡ÇÑ´Ù. */
            gtk_menu_append(GTK_MENU (menu), menu_items);

            /* ¸Þ´º ¾ÆÀÌÅÛÀÌ ¼±ÅÃµÇ¸é ¹º°¡ ¾µ¸¸ÇÑ µ¿ÀÛÀ» ½ÃŲ´Ù. */
            gtk_signal_connect (GTK_OBJECT(menu_items), "activate",
                GTK_SIGNAL_FUNC(menuitem_response), (gpointer)
                g_strdup(buf));

            /* widgetÀ» º¸ÀδÙ. */
            gtk_widget_show(menu_items);
        }

    /* ÀÌ°ÍÀº root ¸Þ´º¸ç, ¸Þ´º¹Ù¿¡ ³ªÅ¸³¯ ¸Þ´ºÀÇ À̸§ Áï ¶óº§ÀÌ
     * µÉ °ÍÀÌ´Ù.  ÀÌ°ÍÀº ´ÜÁö ´­·¯Á³À» ¶§ ¸Þ´ºÀÇ ³ª¸ÓÁö ºÎºÐÀÌ
     * Æ˾÷µÇ±â¸¸ ÇÒ °ÍÀ̹ǷΠƯº°È÷ ½Ã±×³Î Çڵ鷯°¡ °áÇյǾî
     * ÀÖÀ» ÇÊ¿ä´Â ¾ø´Ù. */
    root_menu = gtk_menu_item_new_with_label("Root Menu");

    gtk_widget_show(root_menu);

      /* ÀÌÁ¦ ¿ì¸®ÀÇ »õ·Ó°Ô ¸¸µé¾îÁø "menu"¸¦, "root menu"°¡ µÇµµ·Ï
       * ¼³Á¤ÇØ º¸ÀÚ. */
      gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);

      /* ¸Þ´º¿Í ¹öÆ°À» µé¿©³õÀ» vbox */
      vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_add(GTK_CONTAINER(window), vbox);
      gtk_widget_show(vbox);

      /* ¸Þ´º¸¦ ´ã°í ÀÖÀ» menu-bar¸¦ ¸¸µé°í ±×°ÍÀ» ¿ì¸®ÀÇ main À©µµ¿¡
       * Ãß°¡ÇÑ´Ù. */
      menu_bar = gtk_menu_bar_new();
      gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
      gtk_widget_show(menu_bar);

      /* ¸Þ´º¸¦ Æ˾÷½ÃÅ°µµ·Ï ¿¬°áµÉ ÇÑ ¹öÆ°À» ¸¸µç´Ù. */
      button = gtk_button_new_with_label("press me");
      gtk_signal_connect_object(GTK_OBJECT(button), "event",
          GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
      gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
      gtk_widget_show(button);

      /* ³¡À¸·Î menu-itemÀ» menu-bar¿¡ À̾îÁØ´Ù.  ÀÌ°ÍÀÌ ¹Ù·Î
       * ³»°¡ Áö±Ý²¯ Áö²¬¿© ¿Â "root" ¸Þ´º ¾ÆÀÌÅÛÀÌ´Ù. =) */
      gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);

      /* ¾ðÁ¦³ª Àüü À©µµ¸¦ ¸¶Áö¸·¿¡ º¸¿©ÁØ´Ù. */
      gtk_widget_show(window);

      gtk_main ();

    return 0;
}

/* "widget"À¸·Î ³Ñ°Ü¹ÞÀº ¸Þ´º¸¦ º¸ÀÓÀ¸·Î½á button-press¿¡ ÀÀ´äÇÑ´Ù.
 *
 * ÀÎÀÚ "widget"Àº ´­·ÁÁø ¹öÆ°ÀÌ ¾Æ´Ï¶ó º¸¿©Áú ¸Þ´º¶ó´Â °É ±â¾ïÇÏÀÚ. */

static gint button_press (GtkWidget *widget, GdkEvent *event)
{

      if (event->type == GDK_BUTTON_PRESS) {
          GdkEventButton *bevent = (GdkEventButton *) event;
          gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
                          bevent->button, bevent->time);
          /* ¿ì¸®°¡ ÀÌ À̺¥Æ®¸¦ ´Ù·ç¾úÀ½À» ¸»ÇÑ´Ù.  ¿©±â¼­ ¸ØÃá´Ù. */
          return TRUE;
      }

      /* ¿ì¸®°¡ ÀÌ À̺¥Æ®¸¦ ´Ù·çÁö ¾Ê¾ÒÀ½À» ¸»ÇÑ´Ù.  °è¼Ó Áö³ªÄ£´Ù. */
      return FALSE;
}

/* ¸Þ´º ¾ÆÀÌÅÛÀÌ ¼±ÅõǾúÀ» ¶§ ¹®ÀÚ¿­À» ÇÁ¸°Æ®ÇÑ´Ù. */

static void menuitem_response (GtkWidget *widget, gchar *string)
{
    printf("%s\n", string);
}

¿ì¸®´Â ¶ÇÇÑ ¸Þ´º ¾ÆÀÌÅÛÀ» ¹ÝÀÀÀ» º¸ÀÌÁö ¾Ê°Ôµµ ¸¸µé ¼ö ÀÖ°í, Ç¥¸¦ ÂüÁ¶ Çؼ­ ¸Þ´º ÇÔ¼öµé¿¡ Å°º¸µå ¹ÙÀεùÀ» ÇØÁÙ ¼öµµ ÀÖ´Ù.

11.3 GtkMenuFactory¸¦ ÀÌ¿ëÇϱâ

ÀÌÁ¦ ¾î·Á¿î ¹æ¹ýÀ» º¸¿´°í, gtk_menu_factory ÇÔ¼öµéÀ» ÀÌ¿ëÇÏ´Â ¹æ¹ýÀÌ ¿©±â ÀÖ´Ù.

11.4 Menu factoryÀÇ ¿¹Á¦

ÀÌ°ÍÀº GTK menu factory¸¦ ÀÌ¿ëÇÏ´Â ¿¹Á¦ÀÌ´Ù. ÀÌ°ÍÀº ù¹ø° ÆÄÀÏ menus.h ´Ù. ¿ì¸®´Â menus.c¿¡¼­ ¾²ÀÎ globalº¯¼öµéÀ» °í·ÁÇؼ­ menus.c ¿Í main.c¸¦ ºÐ¸®ÇÒ °ÍÀÌ´Ù.

/* menufactory.h */

#ifndef __MENUFACTORY_H__
#define __MENUFACTORY_H__

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);
void menus_create(GtkMenuEntry *entries, int nmenu_entries);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __MENUFACTORY_H__ */

±×¸®°í ÀÌ°ÍÀº menufactory.c ÆÄÀÏÀÌ´Ù.

/* menufactory.c */

#include <gtk/gtk.h>
#include <strings.h>

#include "mfmain.h"

static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path);
static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path);
void menus_init(void);
void menus_create(GtkMenuEntry * entries, int nmenu_entries);

/* ÀÌ°ÍÀº »õ·Î¿î ¸Þ´º¸¦ ¸¸µé±â À§ÇØ ¾´ GtkMenuEntry ±¸Á¶Ã¼´Ù.
 * ù¹ø° ¸â¹ö´Â ¸Þ´º¸¦ Á¤ÀÇÇÏ´Â ¹®ÀÚ¿­ÀÌ´Ù.  µÎ¹ø°´Â ÀÌ ¸Þ´ºÇÔ¼ö¸¦
 * Å°º¸µå·Î ºÒ·¯³¾ ¶§ ¾²ÀÌ´Â µðÆúÆ® ´ÜÃàÅ°´Ù.  ¼¼¹ø° ¸â¹ö´Â ÀÌ ¸Þ´º
 * ¾ÆÀÌÅÛÀÌ ¼±ÅõǾúÀ»(¸¶¿ì½º ȤÀº ´ÜÃàÅ°·Î½á) ¶§ È£ÃâµÉ callback ÇÔ¼ö´Ù.
 * ±×¸®°í ¸¶Áö¸· ¸â¹ö´Â ÀÌ callbackÇÔ¼ö¿¡ ³Ñ°ÜÁú µ¥ÀÌÅÍ´Ù. */

static GtkMenuEntry menu_items[] =
{
    {"<Main>/File/New", "<control>N", NULL, NULL},
    {"<Main>/File/Open", "<control>O", NULL, NULL},
    {"<Main>/File/Save", "<control>S", NULL, NULL},
    {"<Main>/File/Save as", NULL, NULL, NULL},
    {"<Main>/File/<separator>", NULL, NULL, NULL},
    {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"},
    {"<Main>/Options/Test", NULL, NULL, NULL}
};

/* ¸Þ´º ¾ÆÀÌÅÛÀÇ °¹¼ö¸¦ °è»êÇÑ´Ù. */
static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);

static int initialize = TRUE;
static GtkMenuFactory *factory = NULL;
static GtkMenuFactory *subfactory[1];
static GHashTable *entry_ht = NULL;

void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table)
{
    if (initialize)
            menus_init();

    if (menubar)
            *menubar = subfactory[0]->widget;
    if (table)
            *table = subfactory[0]->table;
}

void menus_init(void)
{
    if (initialize) {
        initialize = FALSE;

        factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
        subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);

        gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>");
        menus_create(menu_items, nmenu_items);
    }
}

void menus_create(GtkMenuEntry * entries, int nmenu_entries)
{
    char *accelerator;
    int i;

    if (initialize)
            menus_init();

    if (entry_ht)
            for (i = 0; i < nmenu_entries; i++) {
                accelerator = g_hash_table_lookup(entry_ht, entries[i].path);
                if (accelerator) {
                    if (accelerator[0] == '\0')
                            entries[i].accelerator = NULL;
                    else
                            entries[i].accelerator = accelerator;
                }
            }
    gtk_menu_factory_add_entries(factory, entries, nmenu_entries);

    for (i = 0; i < nmenu_entries; i++)
            if (entries[i].widget) {
                gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator",
                         (GtkSignalFunc) menus_install_accel,
                         entries[i].path);
                gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator",
                         (GtkSignalFunc) menus_remove_accel,
                         entries[i].path);
            }
}

static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path)
{
    char accel[64];
    char *t1, t2[2];

    accel[0] = '\0';
    if (modifiers & GDK_CONTROL_MASK)
            strcat(accel, "<control>");
    if (modifiers & GDK_SHIFT_MASK)
            strcat(accel, "<shift>");
    if (modifiers & GDK_MOD1_MASK)
            strcat(accel, "<alt>");

    t2[0] = key;
    t2[1] = '\0';
    strcat(accel, t2);

    if (entry_ht) {
        t1 = g_hash_table_lookup(entry_ht, path);
        g_free(t1);
    } else
            entry_ht = g_hash_table_new(g_string_hash, g_string_equal);

    g_hash_table_insert(entry_ht, path, g_strdup(accel));

    return TRUE;
}

static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path)
{
    char *t;

    if (entry_ht) {
        t = g_hash_table_lookup(entry_ht, path);
        g_free(t);

        g_hash_table_insert(entry_ht, path, g_strdup(""));
    }
}

void menus_set_sensitive(char *path, int sensitive)
{
    GtkMenuPath *menu_path;

    if (initialize)
            menus_init();

    menu_path = gtk_menu_factory_find(factory, path);
    if (menu_path)
            gtk_widget_set_sensitive(menu_path->widget, sensitive);
    else
            g_warning("Unable to set sensitivity for menu which doesn't exist: %s", path);
}

ÀÌ°ÍÀº mfmain.h´Ù.

/* mfmain.h */

#ifndef __MFMAIN_H__
#define __MFMAIN_H__

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

void file_quit_cmd_callback(GtkWidget *widget, gpointer data);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __MFMAIN_H__ */

±×¸®°í ÀÌ°ÍÀÌ mfmain.c´Ù.

/* mfmain.c */

#include <gtk/gtk.h>

#include "mfmain.h"
#include "menufactory.h"

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *main_vbox;
    GtkWidget *menubar;

    GtkAcceleratorTable *accel;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect(GTK_OBJECT(window), "destroy",
                       GTK_SIGNAL_FUNC(file_quit_cmd_callback),
                       "WM destroy");
    gtk_window_set_title(GTK_WINDOW(window), "Menu Factory");
    gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);

    main_vbox = gtk_vbox_new(FALSE, 1);
    gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
    gtk_container_add(GTK_CONTAINER(window), main_vbox);
    gtk_widget_show(main_vbox);

    get_main_menu(&menubar, &accel);
    gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
    gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
    gtk_widget_show(menubar);

    gtk_widget_show(window);
    gtk_main();

    return(0);
}

/* ¿©±â¼­´Â menufactory¸¦ ÀÌ¿ëÇÒ ¶§ callbackµéÀÌ ¾î¶»°Ô ÀÛµ¿ÇÏ´ÂÁö¸¦
 * º¸¿©ÁØ´Ù.  Á¾Á¾, »ç¶÷µéÀº ¸Þ´ºµé·ÎºÎÅÍÀÇ ¸ðµç callbackÀ» º°µµÀÇ ÆÄÀÏ¿¡
 * ¸ð¾ÆµÎ°í, °Å±â¼­ ÀûÀýÇÑ ÇÔ¼ö¸¦ È£ÃâÇØ ¾²´Â ¹æ¹ýÀ» ÅÃÇϱ⵵ ÇÑ´Ù. */
void file_quit_cmd_callback (GtkWidget *widget, gpointer data)
{
    g_print ("%s\n", (char *) data);
    gtk_exit(0);
}

±×¸®°í ÄÄÆÄÀÏÀ» ½±°Ô ÇØÁÖ´Â makefileÀÌ´Ù.

# Makefile.mf

CC      = gcc
PROF    = -g
C_FLAGS =  -Wall $(PROF) -L/usr/local/include -DDEBUG
L_FLAGS =  $(PROF) -L/usr/X11R6/lib -L/usr/local/lib
L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm
PROGNAME = menufactory

O_FILES = menufactory.o mfmain.o

$(PROGNAME): $(O_FILES)
    rm -f $(PROGNAME)
    $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS)

.c.o:
    $(CC) -c $(C_FLAGS) $<

clean:
    rm -f core *.o $(PROGNAME) nohup.out
distclean: clean
    rm -f *~

Áö±Ý ´çÀåÀº ÀÌ ¿¹Á¦»ÓÀÌ´Ù. ÀÚ¼¼ÇÑ ¼³¸í°ú ÄÚ¸àÆ®µéÀº ³ªÁß¿¡ Ãß°¡µÉ °ÍÀÌ´Ù.

12. ÅؽºÆ® widget

ÅؽºÆ® widgetÀº ¿©·¯ ÁÙÀÇ ÅؽºÆ®¸¦ º¸¿©Áְųª ÆíÁýÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ¿©·¯°¡Áö »öÀ̳ª ±Û²ÃÀ» ¿øÇÏ´Â ´ë·Î µ¿½Ã¿¡ ¼¯¾î¼­ ¾µ ¼ö ÀÖ´Ù. ¶ÇÇÑ Å°ÀԷ¿¡ ¹ÙÅÁÀ» µÐ ¸¹Àº ¼öÀÇ Emacs¿Í ȣȯ ÅؽºÆ® ÆíÁý ¸í·Éµéµµ Áö¿øÇÑ´Ù.

ÅؽºÆ® widgetÀº ÇÑ ´Ü¾î³ª ÇÑÁÙ Àüü¸¦ ¼±ÅÃ(select)ÇÏ´Â ´õºí Ŭ¸¯, Æ®¸®Çà Ŭ¸¯À» Æ÷ÇÔÇؼ­ ¿ÏÀüÇÑ cut-and-paste ±â´ÉÀ» °®°í ÀÖ´Ù.

12.1 ÅؽºÆ® »óÀÚ ¸¸µé±â¿Í ¼³Á¤.

ÅؽºÆ® widgetÀ» ¸¸µå´Â ÇÔ¼ö´Â ´Ü Çϳª»ÓÀÌ´Ù.

GtkWidget* gtk_text_new (GtkAdjustment *hadj,
                         GtkAdjustment *vadj);

ÀÎÀÚµéÀº ÇöÀç widgetÀÌ º¸¿©ÁÖ°í ÀÖ´Â ÅؽºÆ®ÀÇ À§Ä¡¸¦ ÃßÀûÇÒ ¼ö ÀÖ°Ô ÇØÁÖ´Â AdjustmentÀÇ Æ÷ÀÎÅÍÀÌ´Ù. µÎ ÀÎÀÚ Áß Çϳª³ª µÑ ¸ðµÎ¿¡ NULLÀ» ³Ñ°ÜÁÖ¸é gtk_text_new ÇÔ¼ö´Â ÀÚ±â ÀÚ½ÅÀÇ °ÍÀ» »õ·ÎÀÌ ¸¸µç´Ù.

void gtk_text_set_adjustments (GtkText       *text,
                               GtkAdjustment *hadj,
                               GtkAdjustment *vadj);

À§ ÇÔ¼ö´Â ¾Æ¹« ¶§³ª ÅؽºÆ® widgetÀÇ ¼öÁ÷, ¼öÆò adjustment¸¦ ¹Ù²Ü ¼ö ÀÖ°Ô ÇØÁØ´Ù.

ÅؽºÆ® À§Á¬Àº ÅؽºÆ®ÀÇ ¾çÀÌ À©µµ¿¡ ´Ù Ãâ·ÂµÇ±â¿¡ ³Ê¹« ±æ¾îµµ ÀÚµ¿ÀûÀ¸·Î ½ºÅ©·Ñ ¹Ù¸¦ ¸¸µéÁö´Â ¾Ê´Â´Ù. ±×·¯¹Ç·Î ¿ì¸®´Â Á÷Á¢ ±×°ÍµéÀ» ¸¸µé¾î¼­ Ãâ·Â ·¹À̾ƿô¿¡ Ãß°¡ÇÏ¿©¾ß ÇÑ´Ù.

  vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
  gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
  gtk_widget_show (vscrollbar);

À§ÀÇ ÄÚµå´Â ¼öÁ÷ ½ºÅ©·Ñ¹Ù¸¦ Çϳª ¸¸µé°í À̸¦ ÅؽºÆ® widgetÀÎ textÀÇ ¼öÁ÷ adjustment¿¡ ºÙÀδÙ. ±×¸®°í´Â Á¤»óÀûÀÎ ¹æ¹ý´ë·Î box¿¡ ³Ö´Â´Ù.

ÅؽºÆ® widgetÀ» »ç¿ëÇÏ´Â ÁÖµÈ µÎ°¡Áö ±æÀÌ ÀÖ´Ù. »ç¿ëÀÚ¿¡°Ô ÅؽºÆ®ÀÇ ³»¿ëÀ» ÆíÁýÇÒ ¼ö ÀÖ°Ô Çϰųª ¶Ç´Â »ç¿ëÀÚ¿¡°Ô ¿©·¯ ÁÙÀÇ ÅؽºÆ®¸¦ º¸¿©Áֱ⸸ ÇÒ ¼ö ÀÖ´Ù. ÀÌ µÎ°¡Áö ¸ðµå »çÀ̸¦ ¿Ô´Ù°¬´ÙÇϱâ À§Çؼ­ ÅؽºÆ® widgetÀº ´ÙÀ½ ÇÔ¼ö¸¦ °®°í ÀÖ´Ù.

void gtk_text_set_editable    (GtkText *text,
                               gint    editable);

ÀÎÀÚ editable¿¡ TRUE³ª FALSE¸¦ Á־ »ç¿ëÀÚ°¡ ÅؽºÆ® widgetÀÇ ³»¿ëÀ» ÆíÁý °¡´É, ¶Ç´Â ºÒ°¡´ÉÇϵµ·Ï ¸¸µé ¼ö ÀÖ´Ù. ÅؽºÆ® widgetÀÌ ÆíÁý °¡´ÉÇÑ »óŸé ÇöÀç ÀÔ·Â À§Ä¡¿¡ Ä¿¼­°¡ ³ªÅ¸³­´Ù.

ÀÌ µÎ°¡Áö ¸ðµå¿¡¼­ ÅؽºÆ® widgetÀ» ¾²´Â °ÍÀº º°´Ù¸¥ Á¦ÇÑÀÌ ¾ø´Ù. ¾Æ¹« ¶§³ª ÅؽºÆ® widgetÀÇ ÆíÁý °¡´É»óŸ¦ ¹Ù²Ü ¼ö ÀÖ°í ¾Æ¹« ¶§³ª ÅؽºÆ®¸¦ ÀÔ·ÂÇÒ ¼ö ÀÖ´Ù.

ÅؽºÆ® widgetÀº Ãâ·Â À©µµÀÇ ÇÑÁÙ¿¡ ´Ù º¸¿©Áú ¼ö ¾øÀ» ¸¸Å­ ±ä ÁÙµéÀ» wrappingÇÏ´Â ´É·ÂÀÌ ÀÖ´Ù. ÁÙÀÌ ³Ñ¾î°¡´Â À§Ä¡¿¡ ÀÖ´Â ´Ü¾î¸¦ ¾çÂÊÀ¸·Î ÂÉ°³´Â °ÍÀÌ ±âº» µ¿ÀÛÀÌ´Ù. ÀÌ´Â ´ÙÀ½ ÇÔ¼ö·Î ¹Ù²Ü ¼ö ÀÖ´Ù.

void gtk_text_set_word_wrap (GtkText *text,
                             gint    word_wrap);

ÀÌ ÇÔ¼ö¸¦ ½á¼­ ÅؽºÆ® widgetÀÌ ´Ü¾î¸¦ ÂÉ°³Áö ¾Ê°í wrapÇϵµ·Ï ÁöÁ¤ÇØ ÁÙ ¼ö ÀÖ´Ù. ÀÎÀÚ word_wrap´Â TRUE³ª FALSEÀÇ °ªÀ» °®´Â´Ù.

12.2 ÅؽºÆ® ´Ù·ç±â

ÅؽºÆ® widgetÀÇ ÀÔ·Â Æ÷ÀÎÆ®´Â ´ÙÀ½ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ÁöÁ¤ÇÑ´Ù.

void gtk_text_set_point (GtkText *text,
                         guint   index);
index°¡ ÀÔ·Â Æ÷ÀÎÆ®ÀÇ À§Ä¡ÀÌ´Ù.

ÇöÀç ÀÔ·Â Æ÷ÀÎÆ®¸¦ ±¸ÇÏ´Â °Íµµ À¯»çÇÏ´Ù.

guint gtk_text_get_point (GtkText *text);

À§ÀÇ µÎ ÇÔ¼ö¿Í °°ÀÌ ¾²¸é ÁÁÀº ÇÔ¼ö´Â

guint gtk_text_get_length (GtkText *text);
ÀÌ´Ù. ÀÌ´Â ÅؽºÆ® widgetÀÇ ±æÀ̸¦ µ¹·Áº¸³½´Ù. ÀÌ ±æÀÌ´Â ÇÑ ÁÙÀÇ ³¡À» ³ªÅ¸³»´Â ij¸®Áö-¸®ÅÏÀ» Æ÷ÇÔÇÑ ÅؽºÆ® ¾ÈÀÇ ¸ðµç ij¸¯ÅÍ ¼ýÀÚÀÌ´Ù.

ÇöÀç ÀÔ·Â Æ÷ÀÎÆ®¿¡ ÅؽºÆ®¸¦ ³ÖÀ¸·Á¸é ÅؽºÆ®ÀÇ »ö, ¹ÙÅÁ»ö, ±Û²ÃÀ» ÁöÁ¤µµ ÇÏ´Â gtk_text_insert ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.

void gtk_text_insert (GtkText    *text,
                      GdkFont    *font,
                      GdkColor   *fore,
                      GdkColor   *back,
                      const char *chars,
                      gint       length);

»ö, ¹ÙÅÁ»ö, ±Û²ÃÀ» ÁöÁ¤ÇÏ´Â ÀÎÀÚ¿¡ NULLÀ» ³ÖÀ¸¸é ÀÌ Àü¿¡ ¾²ÀÎ widget style ³»ÀÇ °ªÀÌ ÀÌ¿ëµÈ´Ù. ÀÎÀÚ length¿¡ -1À» ³ÖÀ¸¸é ÁÖ¾îÁø ÅؽºÆ®ÀÇ ÀüºÎ°¡ ´Ù ÀԷµȴÙ.

ÅؽºÆ® widgetÀº gtk_main ÇÔ¼ö ¹Û¿¡¼­µµ ½º½º·Î¸¦ µ¿ÀûÀ¸·Î ´Ù½Ã ±×¸®´Â(redraw) GTK ³»¿¡¼­ ¸î ¾ÈµÇ´Â Á¸ÀçÀÌ´Ù. ÀÌ´Â ÅؽºÆ® widgetÀÇ ³»¿ëÀ» º¯°æÇϸé Áï½Ã ±× È¿°ú°¡ ±×´ë·Î ³ªÅ¸³­´Ù´Â ÀǹÌÀÌ´Ù. ÀÌ·¯ÇÑ °ÍÀº ÅؽºÆ®ÀÇ ³»¿ëÀ» ÇѲ¨¹ø¿¡ ¿©·¯¹ø º¯°æÇÏ´Â °æ¿ì ¹Ù¶óÁö ¾Ê´Â ÀÏÀÏ ¼öµµ ÀÖ´Ù. ÅؽºÆ® widgetÀÌ ²÷ÀÓ¾øÀÌ ½º½º·Î¸¦ ´Ù½Ã ±×¸®´Â ÀÏ ¾øÀÌ ¿©·¯¹ø º¯°æÇϱâ À§Çؼ­ widgetÀ» ±×·¯Áö ¸øÇϵµ·Ï Àӽ÷Π°íÁ¤ÇØ ¹ö¸± ¼ö ÀÖ´Ù. ±×¸®°í º¯°æÀÌ ´Ù ¿Ïº®È÷ ³¡³­ µÚ¿¡ ´Ù½Ã widgetÀ» Ç®¾îÁÖ¸é µÈ´Ù.

´ÙÀ½ µÎ ÇÔ¼ö·Î °íÁ¤Çϰųª Ç®¾îÁÖ´Â ÀÏÀ» ÇÒ ¼ö ÀÖ´Ù.

void gtk_text_freeze (GtkText *text);
void gtk_text_thaw   (GtkText *text);         

ÅؽºÆ®´Â ´ÙÀ½ ÇÔ¼öµéÀ» ½á¼­ ÇöÀç ÀÔ·Â Æ÷ÀÎÆ®¿¡¼­ ¾ÕÂÊÀ¸·Î³ª µÞÂÊ ¹æÇâÀ¸·Î ÅؽºÆ® widget¿¡¼­ Áö¿öÁú ¼ö ÀÖ´Ù.

gint gtk_text_backward_delete (GtkText *text,
                               guint   nchars);
gint gtk_text_forward_delete  (GtkText *text,
                               guint   nchars);

ÅؽºÆ® widgetÀÇ ³»¿ëÀ» ²¨³»°í ½Í´Ù¸é ¸ÅÅ©·Î GTK_TEXT_INDEX(t, index)°¡ ÅؽºÆ® widget tÀÇ index À§Ä¡ÀÇ Ä³¸¯Å͸¦ ²¨³¾ ¼ö ÀÖ°Ô ÇØÁØ´Ù.

´õ ¸¹Àº ¾çÀÇ ÅؽºÆ®¸¦ ÇѲ¨¹ø¿¡ ²¨³¾·Á¸é ´ÙÀ½ ÇÔ¼ö¸¦ ¾´´Ù.

gchar *gtk_editable_get_chars (GtkEditable *editable,
                               gint        start_pos,
                               gint        end_pos);   

ÀÌ°ÍÀº ÅؽºÆ® widgetÀÇ ºÎ¸ð Ŭ·¡½ºÀÇ ÇÔ¼öÀÌ´Ù. end_posÀÇ °ªÀÌ -1À̸é ÀÌ´Â ÅؽºÆ®ÀÇ ³¡À» ÀǹÌÇÑ´Ù. ÅؽºÆ®ÀÇ ½ÃÀÛÀº 0ÀÌ´Ù.

ÀÌ ÇÔ¼ö´Â ²¨³¾ ÅؽºÆ®¸¦ À§ÇÑ »õ·Î¿î ¸Þ¸ð¸® ¿µ¿ªÀ» ÇÒ´çÇÑ´Ù. ±×·¯¹Ç·Î ´Ù ÀÌ¿ëÇÑ µÚ¿¡´Â g_free ÇÔ¼ö¸¦ È£ÃâÇÏ¿© ¸Þ¸ð¸® ¿µ¿ªÀ» Ç®¾îÁÖ´Â °ÍÀ» ÀØÁö¸»¶ó.

12.3 Å°º¸µå ´ÜÃàÅ°

ÅؽºÆ® widgetÀº ÆíÁý, À̵¿, ¼±ÅÃ(selection)À» À§ÇÑ ¹Ì¸® ÁöÁ¤µÈ Å°º¸µå ´ÜÃàÅ°µéÀ» °®°í ÀÖ´Ù. À̵éÀº Control, Alt Å°¿ÍÀÇ Á¶ÇÕÀÌ´Ù.

¿©±â¿¡ µ¡ºÙ¿© Ä¿¼­Å°·Î À̵¿ÇÒ ¶§ Control¸¦ ´©¸£°í ÀÖÀ¸¸é Ä¿¼­°¡ ÇÑ ¹®ÀÚ ´ÜÀ§°¡ ¾Æ´Ï¶ó ÇÑ ´Ü¾î ´ÜÀ§·Î ¿òÁ÷ÀδÙ. Shift¸¦ ´©¸£°í ÀÖÀ¸¸é Ä¿¼­°¡ À̵¿ÇÑ ºÎºÐÀÌ ÀÚµ¿ÀûÀ¸·Î ¼±ÅõȴÙ.

À̵¿ ´ÜÃàÅ°

  • Ctrl-A ÁÙÀÇ Ã³À½À¸·Î
  • Ctrl-E ÁÙÀÇ ³¡À¸·Î
  • Ctrl-N ´ÙÀ½ ÁÙ·Î
  • Ctrl-P ÀÌÀü ÁÙ·Î
  • Ctrl-B ÇÑ ¹®ÀÚ µÚ?
  • Ctrl-F ÇÑ ¹®ÀÚ ¾ÕÀ¸·Î
  • Alt-B ÇÑ ´Ü¾î µÚ·Î
  • Alt-F ÇÑ ´Ü¾î ¾ÕÀ¸·Î

ÆíÁý ´ÜÃàÅ°

  • Ctrl-H µÞÂÊÀÇ ÇÑ ¹®ÀÚ¸¦ Áö¿î´Ù. (Backspace)
  • Ctrl-D ¾ÕÂÊÀÇ ÇÑ ¹®ÀÚ¸¦ Áö¿î´Ù. (Delete)
  • Ctrl-W µÞÂÊÀÇ ÇÑ ´Ü¾î¸¦ Áö¿î´Ù.
  • Alt-D ¾ÕÂÊÀÇ ÇÑ ´Ü¾î¸¦ Áö¿î´Ù.
  • Ctrl-K ÁÙÀÇ ³¡±îÁö Áö¿î´Ù.
  • Ctrl-U ÇÑ ÁÙÀ» Áö¿î´Ù.

Selection ´ÜÃàÅ°

  • Ctrl-X Ŭ¸³º¸µå¿¡ À߶󳽴Ù. (Cut)
  • Ctrl-C Ŭ¸³º¸µå¿¡ º¹»çÇÑ´Ù. (Copy)
  • Ctrl-V Ŭ¸³º¸µå¿¡¼­ ²¨³» ºÙÀδÙ. (Paste)

13. ¹®¼­È­µÇÁö ¾ÊÀº widgetµé

À̵éÀº ¸ðµÎ ÀúÀÚ¸¦ ±â´Ù¸®°í ÀÖ´Ù! :) ¿ì¸®ÀÇ ÀÌ ¹®¼­¿¡ ´ç½ÅÀÌ °øÇåÇØ º¸´Â °Íµµ °í·ÁÇØ º¸±â¸¦.

¸¸¾à ´ç½ÅÀÌ ¹®¼­È­µÇÁö ¾ÊÀº ÀÌ widgetÀ» ¾²°Ô µÈ´Ù¸é, GTK ¹èÆ÷ÆÇ¿¡ ÀÖ´Â ±×µé °¢°¢ÀÇ Çì´õÆÄÀÏÀ» »ìÆ캸±â¸¦ Àû±Ø ±ÇÀåÇÑ´Ù. GTKÀÇ ÇÔ¼öÀ̸§µéÀº ¸Å¿ì ¼­¼úÀûÀÌ´Ù. ÀÏ´Ü ¹«¾ùÀÌ ¾î¶»°Ô ÀÛµ¿ÇÏ´ÂÁö ÀÌÇØÇÑ´Ù¸é, ¾î¶² widget°ú °ü·ÃµÈ ÇÔ¼öÀÇ ¼±¾ð¸¸ º¸´õ¶óµµ ±× widgetÀ» ¾î¶»°Ô ÀÌ¿ëÇÏ´ÂÁö ½±°Ô ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù.

¸¸¾à ¿©·¯ºÐÀÌ ¹®¼­È­µÇÁö ¾ÊÀº widgetÀÇ ¸ðµç ÇÔ¼öµéÀ» ÀÌÇØÇÏ°Ô µÇ¸é, ´ç½ÅÀÌ tutorialÀ» ½á¼­ ´Ù¸¥ »ç¶÷µé¿¡°Ô µµ¿òÀ» ÁÖ´Â °ÍÀ» °í·ÁÇØ ÁáÀ¸¸é ÇÑ´Ù.

13.1 Range Controls

13.2 Previews

13.3 Curves

14. À̺¥Æ®¹Ú½º widget

¾î¶² GTK widgetµéÀº ±×µé¸¸ÀÇ XÀ©µµ¸¦ °¡ÁöÁö ¾Ê°í ´ÜÁö ±×µéÀÇ parentÀ©µµ¿¡ ±×·ÁÁú »ÓÀÌ´Ù. ÀÌ·Î ÀÎÇØ ±×µéÀº À̺¥Æ®¸¦ ¹ÞÀ» ¼ö ¾ø°í ¶Ç ºÎÁ¤È®ÇÑ Å©±â·Î º¯ÇßÀ» ¶§ Ŭ¸³µÇÁö ¾Ê±â ¶§¹®¿¡ ¾îÁö·´°Ô µ¡Ä¥µÇ¾î ¹ö¸± ¼öµµ ÀÖ´Ù. ÀÌ·± widget¿¡ ´ëÇØ Á»´õ ¸¹Àº °ÍÀ» ±â´ëÇÏ·Á¸é ¹Ù·Î ÀÌ EventBox¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.

¾óÇÍ º¸±â¿¡, EventBox widgetÀº ÀüÇô ¾µ¸ð¾øÀ» ¼öµµ ÀÖ´Ù. ÀÌ°ÍÀº ½ºÅ©¸°¿¡ ¾Æ¹«°Íµµ ±×¸®Áö ¾ÊÀ¸¸ç À̺¥Æ®¿¡µµ ÀÀ´äÇÏÁö ¾Ê´Â´Ù. ÇÏÁö¸¸ ÀÌ°ÍÀº ÀÚ½ÅÀÇ child widgetÀ¸·Î XÀ©µµ¸¦ Á¦°øÇÏ´Â ÇÑ ÇÔ¼ö¸¦ Áö¿øÇÑ´Ù. ÀÌ°ÍÀº ¸¹Àº GTK widgetµéÀÌ °ü·ÃµÈ XÀ©µµ¸¦ °¡ÁöÁö ¾Ê´Â´Ù´Â Á¡¿¡¼­ Áß¿äÇÏ´Ù. XÀ©µµ¸¦ °¡ÁöÁö ¾Ê´Â °ÍÀº ¸Þ¸ð¸®¸¦ Àý¾àÇÏ°í ÆÛÆ÷¸Õ½º¸¦ Áõ´ëÇÏÁö¸¸, ¶ÇÇÑ ¸î°¡Áö ¾àÁ¡µµ ÀÖ´Ù. XÀ©µµ°¡ ¾ø´Â widgetÀº À̺¥Æ®¸¦ ¹ÞÀ» ¼ö ¾ø°í, ±×¸®°í ±×ÀÇ Ç׸ñµé¿¡ ´ëÇÑ Å¬¸®Çεµ ÇÏÁö ¾Ê´Â´Ù. EventBox¶ó´Â À̸§Àº À̺¥Æ®¸¦ ´Ù·ç´Â ÇÔ¼ö¶ó´Â Àǹ̵µ ÀÖÁö¸¸, widgetµéÀÌ Å¬¸®Ç뵃 ¼öµµ ÀÖ´Ù´Â °ÍÀ» ÀǹÌÇϱ⵵ ÇÑ´Ù. (±×¸®°í ´õ ÀÖ´Ù.. ¾Æ·¡ÀÇ ¿¹Á¦¸¦ º¸ÀÚ.)

»õ·Î¿î EventBox widgetÀ» ¸¸µé±â À§Çؼ­ ÀÌ°ÍÀ» ÀÌ¿ëÇÑ´Ù.

GtkWidget* gtk_event_box_new (void);

ÀÌ EventBox¿¡´Â child widgetÀÌ ´õÇØÁú ¼ö ÀÖ´Ù.

gtk_container_add (GTK_CONTAINER(event_box), widget);

À̹øÀÇ ¿¹Á¦´Â ÇÑ EventBoxÀÇ µÎ°¡Áö ¾²ÀÓ»õ¸¦ ´Ù º¸¿©ÁØ´Ù. Áï ÀÛÀº ¹Ú½º·Î Ŭ¸®ÇÎµÈ ¶óº§ÀÌ ÀÖ°í, ÀÌ°Í¿¡ ´ë°í ¸¶¿ì½º¸¦ Ŭ¸¯Çϸé ÇÁ·Î±×·¥ÀÌ ³¡³ª°Ô µÈ´Ù.

#include <gtk/gtk.h>

int
main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *event_box;
    GtkWidget *label;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Event Box");

    gtk_signal_connect (GTK_OBJECT (window), "destroy",
              GTK_SIGNAL_FUNC (gtk_exit), NULL);

    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* EventBox¸¦ Çϳª ¸¸µé°í ±×°ÍÀ» toplevel À©µµ¿¡ ´õÇØÁØ´Ù. */

    event_box = gtk_event_box_new ();
    gtk_container_add (GTK_CONTAINER(window), event_box);
    gtk_widget_show (event_box);

    /* ±ä ¶óº§À» ¸¸µç´Ù. */

    label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
    gtk_container_add (GTK_CONTAINER (event_box), label);
    gtk_widget_show (label);

    /* ÀÌ°ÍÀ» ÀÛ°Ô Å¬¸®ÇÎÇÑ´Ù. */
    gtk_widget_set_usize (label, 110, 20);

    /* ÀÌ°Í¿¡ µ¿ÀÛ(action)À» ¿¬°á½ÃÄÑ ÁØ´Ù. */
    gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
    gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
              GTK_SIGNAL_FUNC (gtk_exit), NULL);

    /* ¾î¶² X À©µµ¸¦ À§ÇØ ÇÑ °¡Áö ´õ ÇÊ¿äÇÑ °Ô ÀÖ´Ù... */

    gtk_widget_realize (event_box);
    gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));

    gtk_widget_show (window);

    gtk_main ();

    return 0;
}

15. WidgetÀÇ ¼Ó¼ºÀ» ¼¼ÆÃÇϱâ

¿©±â¼­´Â widgetµéÀ» Á¶ÀÛÇϱâ À§ÇÑ ÇÔ¼öµéÀÌ ¼Ò°³µÈ´Ù. À̰͵éÀº style, padding, size µîÀ» ¼¼ÆÃÇϱâ À§ÇØ ¾²ÀδÙ.

(Accelerator¿¡ ´ëÇÑ º°µµÀÇ ¼½¼ÇÀÌ ÇÊ¿äÇÑ °Í °°´Ù.)

void       gtk_widget_install_accelerator (GtkWidget           *widget,
                                           GtkAcceleratorTable *table,
                                           gchar               *signal_name,
                                           gchar                key,
                                           guint8               modifiers);

void       gtk_widget_remove_accelerator  (GtkWidget           *widget,
                                           GtkAcceleratorTable *table,
                                           gchar               *signal_name);

void       gtk_widget_activate            (GtkWidget           *widget);

void       gtk_widget_set_name            (GtkWidget           *widget,
                                           gchar               *name);
gchar*     gtk_widget_get_name            (GtkWidget           *widget);

void       gtk_widget_set_sensitive       (GtkWidget           *widget,
                                           gint                 sensitive);

void       gtk_widget_set_style           (GtkWidget           *widget,
                                           GtkStyle            *style);

GtkStyle*    gtk_widget_get_style     (GtkWidget *widget);

GtkStyle*    gtk_widget_get_default_style    (void);

void       gtk_widget_set_uposition       (GtkWidget           *widget,
                                           gint                 x,
                                           gint                 y);
void       gtk_widget_set_usize           (GtkWidget           *widget,
                                             gint                 width,
                                             gint                 height);

void       gtk_widget_grab_focus          (GtkWidget           *widget);

void       gtk_widget_show                (GtkWidget           *widget);

void       gtk_widget_hide                (GtkWidget           *widget);

16. ŸÀӾƿô, ±×¸®°í I/O¿Í Idle ÇÔ¼öµé

16.1 ŸÀӾƿô

¾Æ¸¶ gtk_main¿¡¼­ ¾î¶»°Ô GTK¿¡°Ô À¯¿ëÇÑ ÀÛ¾÷À» ÇÏ°Ô ¸¸µéÁö ±Ã±ÝÇÒ °ÍÀÌ´Ù. ¿©±â¿¡´Â ¸î°¡Áö ¿É¼ÇÀÌ ÀÖ´Ù. ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¸é ¸Å millisecond¸¶´Ù È£ÃâµÉ ŸÀӾƿô ÇÔ¼ö¸¦ ¸¸µé¼ö ÀÖ´Ù.

gint gtk_timeout_add (guint32 interval,
                      GtkFunction function,
                      gpointer data);

ù¹ø° ÀÎÀÚ´Â ¿ì¸®°¡ ÇÔ¼ö¸¦ È£ÃâÇϴµ¥ °É¸° ½Ã°£ÀÌ´Ù. µÎ¹ø°´Â ºÎ¸£·Á Çß´ø ÇÔ¼ö°í, ¼¼¹ø°´Â ÀÌ callbackÇÔ¼ö·Î ³Ñ°ÜÁø µ¥ÀÌÅÍ´Ù. ¸®ÅÏ°ªÀº Á¤¼öÇüÀÇ "tag"À¸·Î ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÔÀ¸·Î½á ŸÀӾƿôÀ» ÁßÁöÇϱâ À§ÇØ ¾²ÀδÙ.

void gtk_timeout_remove (gint tag);

¿ì¸®´Â callbackÇÔ¼ö¿¡¼­ 0¶Ç´Â FALSE¸¦ ¸®ÅÏÇÔÀ¸·Î½á ÀÌ Å¸ÀӾƿô ÇÔ¼ö¸¦ ÁßÁö½Ãų ¼öµµ ÀÖ´Ù. ´ç¿¬È÷ ÀÌ°ÍÀº ¿ì¸®ÀÇ ÇÔ¼ö°¡ °è¼ÓµÇ±â À§Çؼ­´Â 0ÀÌ ¾Æ´Ñ °ª, ¸»ÇÏÀÚ¸é TRUE¸¦ ¸®ÅÏÇØ¾ß ÇÔÀ» ÀǹÌÇÑ´Ù.

¿ì¸®ÀÇ callbackÇÔ¼öÀÇ ¼±¾ðÀº ÀÌ·± ÇüÅ·ΠÇؾßÇÑ´Ù.

gint timeout_callback (gpointer data);

16.2 IO¸¦ °¨½ÃÇϱâ

GTKÀÇ ¶Ç´Ù¸¥ ±¦ÂúÀº ±â´É Çϳª´Â, ¿ì¸®¸¦ À§ÇØ ÆÄÀÏ ½Äº°ÀÚ(file descriptor) ÀÇ µ¥ÀÌÅ͸¦ üũÇØ Áشٴ Á¡ÀÌ´Ù(open(2) ȤÀº socket(2)·Î ¸®ÅϵǴ´ë·Î). ÀÌ°ÍÀº ƯÈ÷ ³×Æ®¿÷ ¾îÇÿ¡ À¯¿ëÇÏ´Ù. ÀÌ ÇÔ¼ö¸¦ º¸ÀÚ.

gint gdk_input_add (gint source,
                    GdkInputCondition condition,
                    GdkInputFunction  function,
                    gpointer data);

ù¹ø° ÀÎÀÚ´Â º¸°íÀÚ ÇÏ´Â file descriptor°í, µÎ¹ø°´Â GDK°¡ ãÀ» °ÍÀ» ¼³Á¤ÇØ ÁØ´Ù. ÀÌ°ÍÀº À̵é Áß Çϳª°¡ µÉ °ÍÀÌ´Ù.

GDK_INPUT_READ - ¿ì¸®ÀÇ file descriptor¸¦ ÀÐÀ» Áغñ°¡ µÈ µ¥ÀÌÅÍ°¡ ÀÖÀ» ¶§ ¿ì¸®ÀÇ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù.

GDK_INPUT_WRITE - ¿ì¸®ÀÇ file descriptor°¡ ¾µ(write) Áغñ°¡ µÇ¾úÀ» ¶§ ¿ì¸®ÀÇ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù.

ÀÌ¹Ì ´«Ä¡Ã«°ÚÁö¸¸, ¼¼¹ø° ÀÎÀÚ´Â À§ÀÇ Á¶°ÇÀÌ ¸¸Á·µÉ ¶§ È£ÃâµÉ ÇÔ¼ö°í, ³×¹ø°´Â ÀÌ ÇÔ¼ö¿¡ ³Ñ°ÜÁú µ¥ÀÌÅÍ´Ù.

¸®ÅÏ°ªÀº GDK°¡ file descriptor¸¦ ¸ð´ÏÅÍÇÏ´Â °ÍÀ» ¾Æ·¡ÀÇ ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ ¸ØÃß°Ô ÇÒ tagÀÌ´Ù.

void gdk_input_remove (gint tag);

CallbackÇÔ¼ö°¡ ¼±¾ðµÇ¾î¾ß ÇÑ´Ù.

void input_callback (gpointer data, gint source,
                     GdkInputCondition condition);

16.3 Idle ÇÔ¼ö

´õÀÌ»ó ¾Æ¹«°Íµµ ÀϾÁö ¾ÊÀ» ¶§ È£ÃâÇÒ ÇÔ¼ö´Â ¹«¾ùÀΰ¡?

gint gtk_idle_add (GtkFunction function,
                   gpointer data);

ÀÌ°ÍÀº ´õÀÌ»ó ¾Æ¹«°Íµµ ¹ß»ýÇÏÁö ¾ÊÀ» ¶§ GTK°¡ ÁöÁ¤µÈ ÇÔ¼ö¸¦ È£ÃâÇϵµ·Ï ÇØÁØ´Ù.

void gtk_idle_remove (gint tag);

ÀÌ ÇÔ¼öÀÇ ÀÎÀÚµéÀº À§¿¡¼­ ¼³¸íÇÑ ¾î´À °Í°ú ¸Å¿ì ºñ½ÁÇϱ⠶§¹®¿¡ ¿©±â¼­ ¶Ç ¼³¸íÇÏÁø ¾Ê°Ú´Ù. gtk_idle_addÀÇ Ã¹¹ø° ÀÎÀÚ·Î ÁÖ¾îÁø ÇÔ¼ö´Â ±âȸ°¡ ¿À¸é ¾ðÁ¦µçÁö È£ÃâµÉ °ÍÀÌ´Ù. ´Ù¸¥ °Íµé°ú ¸¶Âù°¡Áö·Î, FALSE¸¦ ¸®ÅÏÇÏ°Ô µÇ¸é idle ÇÔ¼ö´Â È£ÃâÀÌ Áß´ÜµÉ °ÍÀÌ´Ù.

17. Selection °ü¸®Çϱâ

17.1 °³¿ä

GTK°¡ Á¦°øÇÏ´Â ÇÁ·Î¼¼½º »çÀÌÀÇ Åë½ÅÇüÅ Áß Çϳª´Â selectionÀÌ´Ù. SelectionÀº »ç¿ëÀÚ°¡ ¸¶¿ì½º·Î ±Ü°Å³ª Çؼ­ ¼±ÅÃµÈ ÅؽºÆ®ÀÇ ÀϺΰ°Àº, µ¥ÀÌÅÍ Á¶°¢µéÀ» ÀνÄÇÑ´Ù. »ç¿ëÀÚ°¡ ¾î¶² ¼ø°£¿¡ ¼±ÅÃÇÏ°í ÀÖÀ» ¼ö ÀÖ´Â ¾îÇÃÀº Çϳª »ÓÀ̸ç, µû¶ó¼­ ¾î¶² ¾îÇÿ¡ ÀÇÇØ ¼±ÅÃÀÌ ¿ä±¸µÇ¾úÀ» ¶§, ÀÌÀüÀÇ ¼ÒÀ¯ÀÚ´Â selectionÀÌ Æ÷±âµÇ¾úÀ½À» »ç¿ëÀÚ¿¡°Ô Ç¥½ÃÇØ ÁÖ¾î¾ß ÇÑ´Ù. ´Ù¸¥ ¾îÇõéÀº targetÀ̶ó ºÒ¸®´Â, ´Ù¸¥ ÇüÅÂÀÇ selectionÀ» ¿äûÇÑ´Ù. SelectionÀÇ °¹¼ö´Â Á¦ÇÑÀÌ ¾øÁö¸¸, ´ëºÎºÐÀÇ XÀ©µµ ¾îÇõéÀº primary selectionÀ̶ó°í ºÎ¸£´Â ´Ü Çϳª¸¸À» ´Ù·é´Ù.

´ëºÎºÐ °æ¿ì, GTK ¾îÇÃÀÌ selection ÀÚü¸¦ ´Ù·ê ÇÊ¿ä´Â ¾ø´Ù. Entry widget µî Ç¥ÁØÀûÀÎ widgetµéÀº »ç¿ëÀÚ°¡ ÅؽºÆ® À§·Î ¸¶¿ì½º¸¦ µå·¡±×ÇÏ´Â µîÀÇ ÇÕ´çÇÑ °æ¿ì¿¡ selectionÀ» Á¦±âÇÒ ´É·ÂÀ» ÀÌ¹Ì °¡Áö°í ÀÖÀ¸¸ç, ±×¸®°í »ç¿ëÀÚ°¡ ¸¶¿ì½º ÀÇ µÎ¹ø° ¹öÆ°À» Ŭ¸¯ÇÏ´Â °æ¿ìó·³ ´Ù¸¥ ¾îÇÃÀ̳ª widget¿¡ ÀÇÇØ ¼ÒÀ¯µÈ selection Ç׸ñµéÀ» µÇãÀ» ¼öµµ ÀÖ´Ù. ±×·¯³ª ¿ì¸®°¡ ´Ù¸¥ widgetµéÀÌ selection À» Á¦°øÇÏ´Â ´É·ÂÀ» °¡Áöµµ·Ï ÇÏ°í½ÍÀº °æ¿ìµµ ÀÖÀ» °ÍÀ̸ç, µðÆúÆ®·Î Á¦°øµÇÁö ¾Ê´Â targetÀ» µÇã°í ½ÍÀ» ¶§µµ ÀÖÀ» °ÍÀÌ´Ù.

Selection ´Ù·ç±â¸¦ ÀÌÇØÇϱâ À§ÇØ ÇÊ¿äÇÑ ±âº»ÀûÀÎ °³³äÀº atomÀ̶ó´Â °ÍÀÌ´Ù. AtomÀ̶õ ¾î¶² display¿¡¼­, ÇÑ ¹®ÀÚ¿­À» À¯ÀÏÇÏ°Ô ±¸º°ÇÒ ¼ö ÀÖ´Â ¿ÏÀüÇÑ °ÍÀÌ´Ù. ¾î¶² atomµéÀº X ¼­¹ö¿¡ ÀÇÇØ ¹Ì¸® Á¤ÀǵǾî ÀÖÀ¸¸ç, ¾î¶² °æ¿ì¿£ ÀÌ·± atomµé¿¡ ´ëÇÑ constantµéÀÌ gtk.h¿¡ ÀÖÀ» ¼öµµ ÀÖ´Ù. ¿¹¸¦µé¾î »ó¼ö GDK_PRIMARY_SELECTIONÀº ¹®ÀÚ¿­ "PRIMARY"¿¡ ÇØ´çµÈ´Ù. ´Ù¸¥ °æ¿ì¶ó¸é, ¿ì¸®´Â ¾î¶² ¹®ÀÚ¿­ ¿¡ ´ëÀÀÇÏ´Â atomÀ» ÃëÇϱâ À§ÇØ gdk_atom_interm()À», ±×¸®°í atomÀÇ À̸§À» ÃëÇϱâ À§Çؼ± gdk_atom_name()À» ÀÌ¿ëÇØ¾ß ÇÑ´Ù. Selection°ú targetµéÀº ¸ðµÎ atom¿¡ ÀÇÇÏ¿© ½Äº°µÈ´Ù.

17.2 SelectionÀ» º¹±¸Çϱâ

SelectionÀ» µÇã´Â´Ù´Â °ÍÀº ÇϳªÀÇ ºñµ¿½Ã¼ºÀÇ °úÁ¤ÀÌ´Ù. ÀÌ °úÁ¤À» ½ÃÀÛ Çϱâ À§ÇØ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

gint gtk_selection_convert   (GtkWidget           *widget,
                              GdkAtom              selection,
                              GdkAtom              target,
                              guint32              time)

ÀÌ°ÍÀº target¿¡ ÀÇÇØ ¼³Á¤µÈ ÇüÅ·ΠselectionÀ» º¯È¯ÇÑ´Ù. ¸¸¾à °¡´ÉÇÏ´Ù¸é, time ÀÎÀÚ´Â selectionÀ» °áÁ¤ÇÑ À̺¥Æ®·ÎºÎÅÍÀÇ ½Ã°£ÀÌ µÇ¾î¾ß ÇÑ´Ù. ÀÌ°ÍÀº »ç¿ëÀÚ°¡ ¿äûÇÑ ¼ø¼­´ë·Î À̺¥Æ®°¡ ¹ß»ýÇÏ´Â °ÍÀ» È®½ÇÈ÷ ÇØÁØ´Ù. ±×·¯³ª ¸¸¾à ÀÌ°ÍÀÌ ¾²¿©Áú ¼ö ¾ø´Ù¸é(¿¹¸¦µé¾î º¯È¯ÀÌ "clicked"½Ã±×³Î¿¡ ÀÇÇØ ÀÌ·ç¾îÁ³´Ù¸é) ¿ì¸®´Â »ó¼ö GDK_CURRENT_TIME¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

Selecting owner°¡ ¾î¶² ¿ä±¸¿¡ ¹ÝÀÀÇϸé "selection_received"¶ó´Â ½Ã±×³ÎÀÌ ¿ì¸®ÀÇ ¾îÇÿ¡ º¸³»Áö°Ô µÈ´Ù. ÀÌ ½Ã±×³Î¿¡ ´ëÇÑ Çڵ鷯´Â ¾Æ·¡¿Í °°ÀÌ Á¤ÀÇµÈ GtkSelectionData ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ¹Þ´Â´Ù.

struct _GtkSelectionData
{
  GdkAtom selection;
  GdkAtom target;
  GdkAtom type;
  gint    format;
  guchar *data;
  gint    length;
};

ÀÎÀÚ selection°ú targetÀº ¿ì¸®°¡ gtk_selection_convert()ÇÔ¼ö¿¡ ÁØ °ªµéÀÌ´Ù. ÀÎÀÚ typeÀº selection owner¿¡ ÀÇÇØ ¸®ÅÏµÈ µ¥ÀÌÅÍ Å¸ÀÔÀ» ½Äº°ÇÏ´Â atomÀÌ´Ù. ¸î°¡Áö °¡´ÉÇÑ °ªÀ¸·Î´Â ¶óƾ ¹®ÀÚÀÇ ¹®ÀÚ¿­ "STRING", atomÀÇ ½Ã¸®Áî "ATOM", ÇϳªÀÇ Á¤¼ö "INTEGER" µîÀÌ ÀÖ´Ù. ´ëºÎºÐÀÇ targetµéÀº ¿ÀÁ÷ ÇÑ °¡Áö typeÀ» ¸®ÅÏÇÒ ¼ö ÀÖ´Ù. ÀÎÀÚ formatÀº °¢ ´ÜÀ§ÀÇ ±æÀ̸¦ ºñÆ® ´ÜÀ§·Î ÁØ °ÍÀÌ´Ù. º¸Åë, µ¥ÀÌÅ͸¦ ¹ÞÀ» ¶© ÀÌ°Í¿¡ ´ëÇؼ­ ½Å°æ¾µ ÇÊ¿ä°¡ ¾ø´Ù. ÀÎÀÚ data´Â ¸®ÅÏµÈ µ¥ÀÌÅÍ¿¡ ´ëÇÑ Æ÷ÀÎÅ͸ç, length´Â ÀÌ µ¥ÀÌÅÍÀÇ ±æÀ̸¦ ¹ÙÀÌÆ® ´ÜÀ§·Î ÁØ °ÍÀÌ´Ù. ¸¸¾à length°¡ À½¼ö¶ó¸é ¿¡·¯°¡ ¹ß»ýÇÑ °ÍÀÌ°í selectionÀº º¹±¸µÉ ¼ö ¾øÀ» °ÍÀÌ ´Ù. ÀÌ°ÍÀº ±× selectionÀ» ¼ÒÀ¯ÇÑ ¾îÇÃÀÌ ¾ø°Å³ª, ¶Ç´Â ¾îÇÃÀÌ Áö¿øÇÏÁö ¾Ê´Â targetÀ» ¿äûÇßÀ» ¶§ ÀϾ ¼ö ÀÖ´Â ÀÏÀÌ´Ù. ½ÇÁ¦·Î ¹öÆÛ´Â lengthº¸´Ù 1¹ÙÀÌÆ® ±æ°Ô µÇ´Â °ÍÀ» º¸Àå¹Þ´Â´Ù. ³²´Â ¹ÙÀÌÆ®´Â ¾ðÁ¦³ª zero°¡ µÉ °ÍÀÌ°í, µû¶ó¼­ NULL·Î½á ¹®ÀÚ¿­À» ³¡³»±â À§ÇØ µû·Î ¹®ÀÚ¿­ÀÇ º¹»çº»À» ¸¸µé¾î µÑ ÇÊ¿ä°¡ ¾ø´Ù.

À̹ø ¿¹Á¦¿¡¼­, ¿ì¸®´Â "TARGETS"¶ó´Â Ưº°ÇÑ targetÀ» º¹±¸ÇÒ °ÍÀÌ´Ù. ÀÌ°ÍÀº selectionÀÌ º¯È¯µÉ ¼ö ÀÖ´Â ¸ðµç targetÀÇ ¸®½ºÆ®ÀÌ´Ù.

#include <gtk/gtk.h>

void selection_received (GtkWidget *widget,
                         GtkSelectionData *selection_data,
                         gpointer data);

/* »ç¿ëÀÚ°¡ "Get Targets" ¹öÆ°À» Ŭ¸¯ÇßÀ» ¶§ ¿äûµÇ´Â ½Ã±×³Î Çڵ鷯 */
void
get_targets (GtkWidget *widget, gpointer data)
{
  static GdkAtom targets_atom = GDK_NONE;

  /* ¹®ÀÚ¿­ "TARGETS"¿¡ ÇØ´çÇÏ´Â atomÀ» ÃëÇÑ´Ù. */
  if (targets_atom == GDK_NONE)
    targets_atom = gdk_atom_intern ("TARGETS", FALSE);

  /* ±×¸®°í primary selectionÀ¸·Î¼­ "TARGETS"¶ó´Â targetÀ» ¿äûÇÑ´Ù. */
  gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
                         GDK_CURRENT_TIME);
}

/* Selection owner°¡ µ¥ÀÌÅ͸¦ ¸®ÅÏÇßÀ» ¶§ ºÒ·ÁÁö´Â ½Ã±×³Î Çڵ鷯 */
void
selection_received (GtkWidget *widget, GtkSelectionData *selection_data,
                      gpointer data)
{
  GdkAtom *atoms;
  GList *item_list;
  int i;

  /* **** Áß¿ä **** SelectionÀÇ º¹±¸°¡ ¼º°øÇÏ´ÂÁö üũÇÒ °Í. */
  if (selection_data->length < 0)
    {
      g_print ("Selection retrieval failed\n");
      return;
    }
  /* ±â´ëÇÑ ÇüÅ·Πµ¥ÀÌÅ͸¦ ÃëÇßÀ½À» È®ÀÎÇÑ´Ù. */
  if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
    {
      g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
      return;
    }

  /* ¿ì¸®°¡ ÀüÇعÞÀº atomÀ» ÇÁ¸°Æ®ÇÑ´Ù. */
  atoms = (GdkAtom *)selection_data->data;

  item_list = NULL;
  for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
    {
      char *name;
      name = gdk_atom_name (atoms[i]);
      if (name != NULL)
        g_print ("%s\n",name);
      else
        g_print ("(bad atom)\n");
    }

  return;
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_init (&argc, &argv);

  /* Toplevel À©µµ¸¦ ¸¸µç´Ù. */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Event Box");
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* »ç¿ëÀÚ°¡ targetÀ» ÃëÇÏ·Á°í Ŭ¸¯ÇÒ ¼ö ÀÖ´Â ¹öÆ°À» ¸¸µç´Ù. */

  button = gtk_button_new_with_label ("Get Targets");
  gtk_container_add (GTK_CONTAINER (window), button);

  gtk_signal_connect (GTK_OBJECT(button), "clicked",
                        GTK_SIGNAL_FUNC (get_targets), NULL);
  gtk_signal_connect (GTK_OBJECT(button), "selection_received",
                        GTK_SIGNAL_FUNC (selection_received), NULL);

  gtk_widget_show (button);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}

17.3 SelectionÀ» Á¦°øÇϱâ

SelectionÀ» Á¦°øÇÏ´Â °ÍÀº Á¶±Ý ´õ º¹ÀâÇÏ´Ù. ¿ì¸®´Â ¿ì¸®ÀÇ selectionÀÌ ¿äûµÇ¾úÀ» ¶§ È£ÃâµÉ Çڵ鷯µéÀ» µî·ÏÇØ µÖ¾ß ÇÑ´Ù. ¿ì¸®°¡ ´Ù·ê °¢°¢ÀÇ selection/target ½Öµé¿¡ ´ëÇØ ÀÌ·± È£ÃâÀ» ÇÏ´Â °ÍÀÌ´Ù.

void gtk_selection_add_handler (GtkWidget           *widget,
                                GdkAtom              selection,
                                GdkAtom              target,
                                GtkSelectionFunction function,
                                GtkRemoveFunction    remove_func,
                                gpointer             data);

widget, selection, targetÀº ÀÌ Çڵ鷯°¡ °ü¸®ÇÒ ¿äû(request)À» ½Äº°ÇÑ´Ù. remove_func ÀÎÀÚ´Â ½Ã±×³Î Çڵ鷯°¡ Á¦°ÅµÉ ¶§ NULLÀÌ ¾Æ´Ñ °ªÀÌ µÈ´Ù. ÀÌ°Ç ¿¹¸¦µé¾î, ÀÎÅÍÇÁ¸®ÅÍ ¾ð¾î°°ÀÌ µ¥ÀÌÅÍ¿¡ ´ëÇÑ reference countÀÇ Æ®·¢À» À¯ÁöÇÒ Çʿ伺ÀÌ ÀÖ´Â °æ¿ì µî¿¡ À¯¿ëÇÏ´Ù.

ÀÌ·± ¸ð¾çÀÇ callback ÇÔ¼ö¸¦ º¸ÀÚ.

typedef void (*GtkSelectionFunction) (GtkWidget *widget,
                                      GtkSelectionData *selection_data,
                                      gpointer data);

GtkSelectionData´Â À§¿¡¼­ÀÇ °æ¿ì¿Í °°Àº °ÍÀÌÁö¸¸, À̹ø¿£ ¿ì¸®´Â Çʵ带 type, format, data, ±×¸®°í length·Î ä¿ö¾ß ÇÑ´Ù. (Çʵå formatÀº ¿©±â¼­ ½ÇÁ¦·Î Áß¿äÇÏ´Ù. X ¼­¹ö´Â µ¥ÀÌÅÍ°¡ byte-swapµÇ¾î¾ß ÇÏ´ÂÁöÀÇ ¿©ºÎ¸¦ ÀÌ°Í À¸·Î½á °áÁ¤ÇÑ´Ù. º¸Åë ÀÌ°ÍÀº 8 Áï ÇϳªÀÇ ¹®ÀÚÀ̰ųª, ¶Ç´Â 32 Áï Á¤¼ö°¡ µÈ´Ù.) ÀÌ°Ç ÀÌ ÇÔ¼ö¸¦ È£ÃâÇؼ­ ÀÌ·ç¾îÁø´Ù.

void gtk_selection_data_set (GtkSelectionData *selection_data,
                             GdkAtom           type,
                             gint              format,
                             guchar           *data,
                             gint              length);

ÀÌ ÇÔ¼ö´Â ÀûÀýÈ÷ µ¥ÀÌÅÍÀÇ º¹»çº»À» ¸¸µéµµ·Ï ÇØÁֱ⠶§¹®¿¡ ¿ì¸®´Â µû·Î ÀÌ°Í¿¡ ½Å°æ¾µ ÇÊ¿ä°¡ ¾ø´Ù. (¿ì¸®´Â Á÷Á¢ GtkSelectionDataÀÇ ÇʵåµéÀ» ä¿ö ÁÖÁö ¾Ê¾Æµµ µÈ´Ù´Â ¸»ÀÌ´Ù.)

¿ì¸®´Â ´ÙÀ½ ÇÔ¼ö¸¦ È£ÃâÇؼ­ selectionÀÇ ¼ÒÀ¯±Ç(ownership)À» Á¦½ÃÇÒ ¼ö ÀÖ´Ù.

gint gtk_selection_owner_set (GtkWidget           *widget,
                              GdkAtom              selection,
                              guint32              time);

¸¸¾à ¶Ç´Ù¸¥ ¾îÇÃÀÌ selectionÀÇ ¼ÒÀ¯±ÇÀ» Á¦½ÃÇÑ´Ù¸é, ¿ì¸®´Â "selection_ clear_event"¸¦ ¹Þ°ÔµÉ °ÍÀÌ´Ù.

SelectionÀ» Á¦°øÇÏ´Â ¿¹Á¦·Î¼­, ´ÙÀ½ ÇÁ·Î±×·¥Àº ¾î¶² Åä±Û¹öÆ°¿¡ selection ±â´ÉÀ» ÷°¡ÇÒ °ÍÀÌ´Ù. ÀÌ Åä±Û¹öÆ°ÀÌ ´­·ÁÁø »óŶó¸é, ÇÁ·Î±×·¥Àº primary selectionÀ» Á¦±âÇÒ °ÍÀÌ´Ù. GTK ÀÚü¿¡ ÀÇÇØ ÁÖ¾îÁö´Â "TARGETS" °°Àº °ÍÀº Á¦ÃÄ µÎ°í, ¿©±â¼­ ÁÖ¾îÁø À¯ÀÏÇÑ targetÀº "STRING" targetÀÌ´Ù. ÀÌ targetÀÌ ¿äûµÇ¸é, ½Ã°¢À» º¸¿©ÁÖ´Â ÇÑ ¹®ÀÚ¿­ÀÌ ¸®ÅϵȴÙ.

#include <gtk/gtk.h>
#include <time.h>

/* »ç¿ëÀÚ°¡ selectionÀ» Åä±ÛÇÒ ¶§ È£ÃâµÇ´Â callback. */
void
selection_toggled (GtkWidget *widget, gint *have_selection)
{
  if (GTK_TOGGLE_BUTTON(widget)->active)
    {
      *have_selection = gtk_selection_owner_set (widget,
                                                 GDK_SELECTION_PRIMARY,
                                                 GDK_CURRENT_TIME);
      /* SelectionÀ» ¿ä±¸ÇÏ´Â µ¥ ½ÇÆÐÇϸé, out state·Î ±× ¹öÆ°À»
       * ¸®ÅÏÇÑ´Ù. */
      if (!*have_selection)
        gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
    }
  else
    {
      if (*have_selection)
        {
          /* Selection owner¸¦ NULL·Î Çؼ­ selectionÀ» ºñ¿ì±â Àü¿¡,
           * ¿ì¸®°¡ ÇöÀç ½ÇÁ¦ÀÇ ownerÀÎÁö üũÇÏÀÚ. */
          if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
            gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
                                     GDK_CURRENT_TIME);
          *have_selection = FALSE;
        }
    }
}

/* ´Ù¸¥ ¾îÇÃÀÌ selectionÀ» Á¦±âÇßÀ» ¶§ È£ÃâµÈ´Ù. */
gint
selection_clear (GtkWidget *widget, GdkEventSelection *event,
                 gint *have_selection)
{
  *have_selection = FALSE;
  gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);

  return TRUE;
}

/* SelectionÀ¸·Î¼­ ÇöÀç ½Ã°¢À» Á¦°øÇÑ´Ù. */
void
selection_handle (GtkWidget *widget,
                  GtkSelectionData *selection_data,
                  gpointer data)
{
  gchar *timestr;
  time_t current_time;

  current_time = time (NULL);
  timestr = asctime (localtime(&current_time));
  /* ¿ì¸®°¡ ÇϳªÀÇ ½ºÆ®¸µÀ» ¸®ÅÏÇÒ ¶§, µû·Î NULL ¹®ÀÚ·Î ³¡À» ³»Áö
   * ¾Ê¾Æµµ µÈ´Ù.  ÀÌ¹Ì Ã³¸®µÇ¾î Àֱ⠶§¹®ÀÌ´Ù. */

  gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
                          8, timestr, strlen(timestr));
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;

  GtkWidget *selection_button;
  static int have_selection = FALSE;

  gtk_init (&argc, &argv);

  /* Toplevel À©µµ¸¦ ¸¸µç´Ù. */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Event Box");
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* SelectionÀ¸·Î¼­ µ¿ÀÛÇÒ Åä±Û¹öÆ°À» Çϳª ¸¸µç´Ù. */

  selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
  gtk_container_add (GTK_CONTAINER (window), selection_button);
  gtk_widget_show (selection_button);

  gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
                      GTK_SIGNAL_FUNC (selection_toggled), &have_selection);
  gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
                      GTK_SIGNAL_FUNC (selection_clear), &have_selection);

  gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
                             GDK_SELECTION_TYPE_STRING,
                             selection_handle, NULL, NULL);

  gtk_widget_show (selection_button);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}

18. glib

glib´Â GDK ¹× GTK ¾îÇÃÀ» °³¹ßÇÒ ¶§ ¸¹Àº À¯¿ëÇÑ ÇÔ¼ö¿Í Á¤ÀǵéÀ» Á¦°øÇÑ´Ù. ³ª´Â ¿©±â¼­ ±×µéÀ» °£´ÜÇÑ ¼³¸í°ú ÇÔ²² º¸ÀÏ °ÍÀÌ´Ù. »ó´ç¼ö´Â Ç¥ÁØÀÇ libc¿Í Áߺ¹µÇ±â ¶§¹®¿¡ ±×µé¿¡ ´ëÇØ ÀÚ¼¼È÷ ´Ù·çÁø ¾Ê´Â´Ù. ÀÌ°ÍÀº ÁÖ·Î ÇϳªÀÇ Âü°í·Î¼­, ¾î¶² °ÍÀ» ÀÌ¿ëÇÒ ¼ö Àִ°¡¸¦ ÆľÇÇÏ°Ô ÇÒ °ÍÀÌ´Ù.

18.1 Á¤ÀÇ

¸¹Àº ÀÚ·áÇüµé¿¡ ´ëÇÑ extreme °ªµéÀÇ Á¤ÀÇ´Â ÀÌ·¸´Ù.

G_MINFLOAT
G_MAXFLOAT
G_MINDOUBLE
G_MAXDOUBLE
G_MINSHORT
G_MAXSHORT
G_MININT
G_MAXINT
G_MINLONG
G_MAXLONG

¶ÇÇÑ, typedefµéµµ ÀÖ´Ù. ¿ÞÂÊÀÇ °ÍµéÀº ±â°èÀÇ architecture¿¡ ÀÇÇØ ´Ù¸£°Ô ¼¼ÆõȴÙ. ȣȯ¼ºÀ» À¯ÁöÇÏ·Á¸é Æ÷ÀÎÅÍÀÇ Å©±â¸¦ Àç¾î¼­´Â ¾ÈµÈ´Ù´Â °ÍÀ» ¸í½É Ç϶ó. ÇϳªÀÇ Æ÷ÀÎÅÍ´Â Alpha ¿¡¼­ 8¹ÙÀÌÆ®, ÇÏÁö¸¸ Intel¿¡¼­´Â 4¹ÙÀÌÆ®ÀÌ´Ù.

char   gchar;
short  gshort;
long   glong;
int    gint;
char   gboolean;

unsigned char   guchar;
unsigned short  gushort;
unsigned long   gulong;
unsigned int    guint;

float   gfloat;
double  gdouble;
long double gldouble;

void* gpointer;

gint8
guint8
gint16
guint16
gint32
guint32

18.2 ÀÌÁß ¿¬°á ¸®½ºÆ®µé

¾Æ·¡ÀÇ ÇÔ¼öµéÀº ÀÌÁß ¿¬°á ¸®½ºÆ®µéÀ» ¸¸µé°í, °ü¸®ÇÏ°í, ¶Ç Æı«Çϱâ À§ÇØ ¾²ÀÌ´Â °ÍµéÀÌ´Ù. ÀÌ ¹®¼­¿¡¼­ ¿¬°á¸®½ºÆ®°¡ ¹«¾ùÀÎÁö ´Ù·ê ¼ø ¾ø±â¿¡, ³ª´Â ¿©·¯ºÐÀÌ ±×°ÍÀ» ÀÌ¹Ì ¾Ë°í ÀÖ´Ù°í °¡Á¤ÇÑ´Ù. ¹°·Ð, ±×°ÍÀº GTKÀÇ ÀϹÝÀûÀÎ ¾²ÀÓ»õ¸¦ ¾Ë±â À§ÇØ ²À ÇÊ¿äÇÑ °ÍÀº ¾Æ´ÏÁö¸¸, ±×·¡µµ ¾Ë¸é ÁÁÀº °ÍÀÌ´Ù.

GList* g_list_alloc       (void);

void   g_list_free        (GList     *list);

void   g_list_free_1      (GList     *list);

GList* g_list_append      (GList     *list,
                           gpointer   data);
                           
GList* g_list_prepend     (GList     *list,
                           gpointer   data);
                        
GList* g_list_insert      (GList     *list,
                           gpointer   data,
                           gint       position);

GList* g_list_remove      (GList     *list,
                           gpointer   data);
                           
GList* g_list_remove_link (GList     *list,
                           GList     *link);

GList* g_list_reverse     (GList     *list);

GList* g_list_nth         (GList     *list,
                           gint       n);
                           
GList* g_list_find        (GList     *list,
                           gpointer   data);

GList* g_list_last        (GList     *list);

GList* g_list_first       (GList     *list);

gint   g_list_length      (GList     *list);

void   g_list_foreach     (GList     *list,
                           GFunc      func,
                           gpointer   user_data);

18.3 ¿¬°á ¸®½ºÆ®

À§¿¡ ÀÖ´Â ¸¹Àº ÇÔ¼öµéÀº ´ÜÀÏ ¿¬°á¸®½ºÆ®µé¿¡ ´ëÇؼ­µµ ¾²ÀÏ ¼ö ÀÖ´Â °Íµé ÀÌ´Ù. ¿©±â ¿ÏÀüÇÑ ÇÔ¼öÀÇ ¸®½ºÆ®°¡ ÀÖ´Ù.

GSList* g_slist_alloc       (void);

void    g_slist_free        (GSList   *list);

void    g_slist_free_1      (GSList   *list);

GSList* g_slist_append      (GSList   *list,
                             gpointer  data);

GSList* g_slist_prepend     (GSList   *list,
                             gpointer  data);

GSList* g_slist_insert      (GSList   *list,
                             gpointer  data,
                             gint      position);

GSList* g_slist_remove      (GSList   *list,
                             gpointer  data);

GSList* g_slist_remove_link (GSList   *list,
                             GSList   *link);

GSList* g_slist_reverse     (GSList   *list);

GSList* g_slist_nth         (GSList   *list,
                             gint      n);

GSList* g_slist_find        (GSList   *list,
                             gpointer  data);

GSList* g_slist_last        (GSList   *list);

gint    g_slist_length      (GSList   *list);

void    g_slist_foreach     (GSList   *list,
                             GFunc     func,
                             gpointer  user_data);

18.4 ¸Þ¸ð¸® °ü¸®

gpointer g_malloc      (gulong    size);

ÀÌ°ÍÀº malloc()À» ´ëüÇÏ´Â °ÍÀÌ´Ù. ÀÌ ÇÔ¼öÀÇ ³»ºÎ¿¡¼­ ¸®ÅÏ°ª¿¡ ´ëÇÑ Ã¼Å©°¡ ÀÌ·ç¾îÁö¹Ç·Î ¿ì¸®°¡ µû·Î ±×°ÍÀ» ÇØÁÙ ÇÊ¿ä´Â ¾ø´Ù.

gpointer g_malloc0     (gulong    size);

À§¿Í °°Áö¸¸, ±×°ÍÀ» ÇâÇÑ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇϱâ Àü±îÁø 0ÀÌ´Ù.

gpointer g_realloc     (gpointer  mem,
                        gulong    size);

"mem"¿¡¼­ ½ÃÀÛÇÏ¿© "size"¸¸Å­ÀÇ ¹ÙÀÌÆ®¸¦ ´Ù½Ã ÇÒ´çÇÑ´Ù. ¹°·Ð ±× ¸Þ¸ð¸®´Â ÀÌÀü¿¡ ÇÒ´çµÇ¾î ÀÖ¾î¾ß ÇÑ´Ù.

void     g_free        (gpointer  mem);

°£´ÜÇÏ´Ù, ¸Þ¸ð¸®¸¦ ¹Ý³³ÇÑ´Ù.

void     g_mem_profile (void);

»ç¿ëµÈ ¸Þ¸ð¸®ÀÇ profileÀ» ½ñ¾Æ³» ÁØ´Ù. ÇÏÁö¸¸ ÀÌ°ÍÀ» ¾²±â À§Çؼ± ¿ì¸®´Â glib/gmem.cÀÇ Á¦ÀÏ À­ºÎºÐ¿¡ #define MEM_PROFILEÀ» ´õÇØÁÖ°í make¸¦ ´Ù½Ã ÇØ¾ß ÇÑ´Ù.

void     g_mem_check   (gpointer  mem);

¸Þ¸ð¸®ÀÇ À§Ä¡°¡ À¯È¿ÇÑ °ÍÀÎÁö üũÇÑ´Ù. gmem.cÀÇ Á¦ÀÏ À­ºÎºÐ¿¡ #define MEM_CHECKÀ» ´õÇØÁÖ°í make¸¦ ´Ù½Ã ÇØ¾ß ÇÑ´Ù.

18.5 ŸÀ̸Ó

ŸÀÌ¸Ó ÇÔ¼öµéÀÌ´Ù.

GTimer* g_timer_new     (void);

void    g_timer_destroy (GTimer  *timer);

void    g_timer_start   (GTimer  *timer);

void    g_timer_stop    (GTimer  *timer);

void    g_timer_reset   (GTimer  *timer);

gdouble g_timer_elapsed (GTimer  *timer,
                         gulong  *microseconds);

18.6 ¹®ÀÚ¿­ ´Ù·ç±â

¹®ÀÚ¿­À» ´Ù·ç´Â ÇÔ¼öµéÀÌ´Ù. À̵éÀº ¸ðµÎ »ó´çÈ÷ Èï¹Ì·Ó°í, ¶ÇÇÑ Ç¥ÁØ C ¹®ÀÚ¿­ ÇÔ¼öµéº¸´Ù ´õ ¸¹Àº ±â´ÉµéÀÌ ÀÖÀ» °ÍÀÌ´Ù. ÇÏÁö¸¸ À̵鿡 ¹®¼­°¡ ÇÊ¿ä ÇÒ °ÍÀÌ´Ù.

GString* g_string_new       (gchar   *init);
void     g_string_free      (GString *string,
                             gint     free_segment);

GString* g_string_assign    (GString *lval,
                             gchar   *rval);

GString* g_string_truncate  (GString *string,
                             gint     len);

GString* g_string_append    (GString *string,
                             gchar   *val);

GString* g_string_append_c  (GString *string,
                             gchar    c);

GString* g_string_prepend   (GString *string,
                             gchar   *val);

GString* g_string_prepend_c (GString *string,
                             gchar    c);

void     g_string_sprintf   (GString *string,
                             gchar   *fmt,
                             ...);

void     g_string_sprintfa  (GString *string,
                             gchar   *fmt,
                             ...);

18.7 Utility ¿Í Error ÇÔ¼öµé

gchar* g_strdup    (const gchar *str);

strdupÇÔ¼ö¸¦ ´ëüÇÑ´Ù. ¿ø·¡ÀÇ ¹®ÀÚ¿­À» »õ·Ó°Ô ÇÒ´çµÈ ¸Þ¸ð¸®¿¡ º¹»çÇÏ°í, ±× °÷¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù.

gchar* g_strerror  (gint errnum);

¸ðµç ¿¡·¯ ¸Þ½ÃÁö¿¡ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÒ °ÍÀ» ±ÇÇÑ´Ù. ÀÌ°ÍÀº perror()³ª ´Ù¸¥ °Íº¸´Ù ÈξÀ ¸ÚÁö°í, È®À强 ÁÁÀº °ÍÀÌ´Ù. Ãâ·ÂÀº º¸Åë ÀÌ·± Çü½ÄÀÌ´Ù.

program name:function that failed:file or further description:strerror

ÀÌ°ÍÀº ¿ì¸®ÀÇ hello_world ÇÁ·Î±×·¥¿¡ ¾²ÀÎ ¿¹Á¦ÀÌ´Ù.

g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));

void g_error   (gchar *format, ...);

¿¡·¯ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÑ´Ù. Çü½ÄÀº printf¿Í °°Áö¸¸, Ãâ·ÂÀÇ ¾Õ¸Ó¸®¿¡ "** ERROR **: "¸¦ ºÙÀÌ°í, ±×¸®°í ÇÁ·Î±×·¥À» ³¡³½´Ù. Ä¡¸íÀûÀÎ ¿¡·¯¿¡¸¸ »ç¿ëÇ϶ó.

void g_warning (gchar *format, ...);

À§¿Í °°´Ù, ÇÏÁö¸¸ "** WARNING **: "À» ¾Õ¸Ó¸®¿¡ ºÙÀÌ°í, ¶ÇÇÑ ÇÁ·Î±×·¥À» ³¡³»Áø ¾Ê´Â´Ù.

void g_message (gchar *format, ...);

¿ì¸®°¡ Ãâ·ÂÇÏ·Á´Â ¹®ÀÚ¿­¿¡ "message: "¸¦ ¾Õ¿¡¼­ ºÙ¿© Ãâ·ÂÇØÁØ´Ù.

void g_print   (gchar *format, ...);

printf¸¦ ´ëüÇÑ´Ù.

±×¸®°í ¿ì¸®ÀÇ ¸¶Áö¸· ÇÔ¼ö´Â ÀÌ°ÍÀÌ´Ù.

gchar* g_strsignal (gint signum);

ÀÎÀÚ·Î ÁØ ½Ã±×³Î ¹øÈ£¿¡ ÇØ´çÇÏ´Â À¯´Ð½º ½Ã½ºÅÛÀÇ ½Ã±×³Î À̸§À» Ãâ·ÂÇØÁØ´Ù. ´ë´Ù¼öÀÇ ½Ã±×³Î ´Ù·ç´Â ÇÔ¼öµé¿¡°Ô À¯¿ëÇÏ´Ù.

À§¿¡ ¼Ò°³µÈ ¸ðµç °ÍµéÀº glib.h¿¡¼­ ¸¶±¸ÀâÀÌ·Î ÀοëÇÑ °ÍÀÌ´Ù. ¿©·¯ºÐ Áß ´©±¸¶óµµ ¾î¶² ÇÔ¼ö¿¡ ´ëÇÑ ¹®¼­È­¸¦ ÇÏ°Ú´Ù¸é, ³ª¿¡°Ô emailÀ» º¸³»ÁÖ±æ!

19. GTKÀÇ rc ÆÄÀÏ

GTK´Â rc ÆÄÀÏÀ» ÀÌ¿ëÇؼ­ ¾îÇÃÀÇ µðÆúÆ® ȯ°æÀ» ´Ù·é´Ù. À̵éÀº ¾Õ¼­ ¼³¸íÇÑ ¾î¶² widgetÀÇ »ö±òÀº ¹°·Ð ¹è°æ¿¡ ³ÖÀ» pixmapÀ» ¼³Á¤ÇÒ ¼öµµ ÀÖ´Ù.

19.1 rc ÆÄÀÏÀ» À§ÇÑ ÇÔ¼ö

¾îÇÃÀ» ½ÃÀÛÇÏ´Â ºÎºÐ¿¡¼­ ÀÌ ÇÔ¼ö¸¦ Æ÷ÇÔ½ÃÅ°ÀÚ.

void gtk_rc_parse (char *filename);

ÀÎÀÚ´Â ¿ì¸® rc ÆÄÀÏÀÇ À̸§ÀÌ´Ù. ÀÌ°ÍÀº GTK°¡ ÀÌ ÆÄÀÏÀ» Àо widgetµéÀÇ ½ºÅ¸ÀÏÀ» ±×°÷¿¡ Á¤ÀÇµÈ ´ë·Î ¼¼ÆÃÇϵµ·Ï ÇÑ´Ù.

¸¸¾à widgetµé Áß¿¡ ´Ù¸¥ °Íµé°ú ±¸º°µÇ¾î¾ß ÇÒ Æ¯º°ÇÑ ½ºÅ¸ÀÏÀ» °¡Á®¾ß ÇÒ °ÍÀÌ ÀÖ´Ù¸é, ¶Ç´Â ´Ù¸¥ ¸ñÀûÀ¸·Î widgetµéÀ» ³í¸®ÀûÀ¸·Î ºÐ·ùÇÏ·Á¸é, ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void gtk_widget_set_name (GtkWidget *widget,
                                                gchar *name);

ù¹ø° ÀÎÀÚ·Î »õ·Î ¸¸µç widgetÀ» ÁÖ°í, µÎ¹ø° ÀÎÀÚ´Â ±×°Í¿¡ ºÎ¿©ÇÏ°íÀÚ ÇÏ´Â À̸§ÀÌ´Ù. ÀÌ°ÍÀº ÀÌ widgetÀÇ ¼Ó¼ºÀ» rc ÆÄÀÏ¿¡ ÀÖ´Â À̸§À» ÅëÇÏ¿© ¹Ù²Ü ¼ö ÀÖ°Ô ÇÑ´Ù.

ÀÌ·± ½ÄÀ¸·Î ÇÔ¼ö¸¦ È£ÃâÇß´Ù°í »ý°¢ÇØ º¸ÀÚ.

button = gtk_button_new_with_label ("Special Button");
gtk_widget_set_name (button, "special button");

±×·³ ÀÌ ¹öÆ°Àº "special button"À¸·Î À̸§ºÙ°í rc ÆÄÀÏ¿¡¼­ "special button. GtkButton"À̶ó´Â À̸§À¸·Î µÉ °ÍÀÌ´Ù. (È®ÀÎÇØ º¸ÀÚ!)

¾Æ·¡ÀÇ rc ÆÄÀÏ ¿¹Á¦´Â main À©µµÀÇ ¼Ó¼ºÀ» ¼¼ÆÃÇÏ°í, ±× main À©µµÀÇ child µéÀº "main button"ÀÇ ½ºÅ¸ÀÏÀ» »ó¼Ó¹Þ°Ô µÈ´Ù. ÀÌ ¾îÇÿ¡¼­ ¾²ÀÎ ÄÚµå´Â ÀÌ·¸°Ô µÈ´Ù.

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_name (window, "main window");

±×¸®°í rc ÆÄÀÏ¿¡¼­ Á¤ÀǵǴ ½ºÅ¸ÀÏÀº ÀÌ·¸°Ô µÈ´Ù.

widget "main window.*GtkButton*" style "main_button"

"main window"¿¡ ÀÖ´Â ¸ðµç GtkButton widgetÀ» rc ÆÄÀÏ¿¡¼­ Á¤ÀÇÇÑ "main_buttons"ÀÇ ½ºÅ¸ÀÏ´ë·Î ¼¼ÆÃÇÑ´Ù.

º¸´Ù½ÃÇÇ, ÀÌ°ÍÀº »ó´çÈ÷ °­·ÂÇÏ°í À¯¿¬ÇÑ ½Ã½ºÅÛÀÌ´Ù. ÀÌ°ÍÀ¸·Î ÃÖ°íÀÇ È¿°ú¸¦ ¾ò±â À§ÇØ °¢ÀÚ »ó»ó·ÂÀ» µ¿¿øÇØ º¸±â ¹Ù¶õ´Ù.

19.2 GTK rc ÆÄÀÏÀÇ Æ÷¸Ë

GTK rc ÆÄÀÏÀÇ Æ÷¸ËÀº µÚµû¸£´Â ¿¹Á¦¿¡¼­ º¸¿©Áö°í ÀÖ´Ù. ÀÌ°ÍÀº GTK ¹èÆ÷º»¿¡ ÇÔ²² ÀÖ´Â testgtkrc ÆÄÀÏÀÌ°í, ³»°¡ ¾à°£ÀÇ ÁÖ¼® °°Àº °ÍÀ» ´õÇß´Ù. ´©±¸µçÁö ÀÌ°ÍÀ» ¾îÇÿ¡ Æ÷ÇÔ½ÃÄѼ­ »ç¿ëÀÚµéÀÌ ÀÌ¿ëÇÏ°Ô ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

WidgetÀÇ ¼Ó¼ºÀ» º¯È­½Ãų ¶§ ¸î°¡Áö Á÷°üÀûÀÎ °ÍµéÀÌ ÀÖ´Ù.

  • fg - WidgetÀÇ foreground »ö±ò
  • bg - WidgetÀÇ background »ö±ò
  • bg_pixmap - WidgetÀÇ background¿¡ ¾²ÀÏ ÇȽº¸Ê
  • font - ÁÖ¾îÁø widget¿¡ ¾²ÀÏ ÆùÆ®

À̰͵鿡 µ¡ºÙ¿©, widgetµé¿¡ °¡ÇØÁú ¼ö ÀÖ´Â ¸î°¡Áö state°¡ ÀÖ°í, ¿ì¸®´Â ´Ù¸¥ »ö±ò, ÇȽº¸Ê, ±×¸®°í ÆùÆ®¸¦ °¢ »óÅ¿¡ ¼¼ÆÃÇØ ÁÙ ¼ö ÀÖ´Ù. ÀÌ stateµéÀº ´ÙÀ½°ú °°´Ù.

  • NORMAL - WidgetÀÇ Æò»ó½Ã »óÅÂ. ¸¶¿ì½º°¡ ±× widgetÀÇ À§¿¡ ¿ÀÁö ¾Ê¾Ò°í, ¶Ç ´­·¯ÁöÁöµµ ¾ÊÀº µîÀÇ »óÅ´Ù.
  • PRELIGHT - ¸¶¿ì½º Æ÷ÀÎÅÍ°¡ ¾î¶² widgetÀÇ À§·Î ¿À°Ô µÇ¸é, ÀÌ state¿¡¼­ Á¤ÀÇÇÑ »ö±òµéÀÌ È¿·ÂÀ» °¡Áö°Ô µÈ´Ù.
  • ACTIVE - WidgetÀÌ ´­·¯Áö°Å³ª Ŭ¸¯µÇ¸é activeÀÌ°í, ÀÌ tag¿¡ ÀÇÇؼ­ Á¤ÀÇµÈ ¼Ó¼ºµéÀÌ È¿·ÂÀ» °¡Áø´Ù.
  • INSENSITIVE - ¾î¶² widgetÀÌ insensitive·Î, ±×¸®°í activeµÉ ¼ö ¾øµµ·Ï ¼¼ÆÃµÇ¸é ¿©±â¼­ÀÇ ¼Ó¼ºÀ» µû¸£°Ô µÈ´Ù.
  • SELECTED - Object°¡ selectedµÇ¸é ¿©±â¼­ÀÇ ¼Ó¼ºÀ» µû¸£°Ô µÈ´Ù.

WidgetÀÇ »ö±òÀ» º¯È­½ÃÅ°´Â Å°¿öµåÀÎ "fg"¿Í "bg"¸¦ »ç¿ëÇÒ ¶§ÀÇ Æ÷¸ËÀº ÀÌ·¸´Ù.

fg[<STATE>] = { Red, Green, Blue }

¿©±â¼­ STATE´Â À§ÀÇ Ç¥Çöµé(PRELIGHT, ACTIVE µî) Áß Çϳª°í, Red, Green, Blue´Â 0ºÎÅÍ 1±îÁöÀÇ ºÎµ¿¼Ò¼öÁ¡ ¼ö´Ù. À̵éÀº ¹Ýµå½Ã ºÎµ¿¼Ò¼ö·Î Ç¥ÇöµÇ¾î¾ß Çϸç, ±×·¸Áö ¾ÊÀ¸¸é 0À¸·Î ÀÎ½ÄµÉ °ÍÀÌ´Ù. "1"Àº µ¿ÀÛÇÏÁö ¾Ê´Â´Ù, ²À "1.0" À¸·Î ÇØ¾ß ÇÑ´Ù. ´Ü¼øÈ÷ "0"À̶ó°í ÇÏ´Â °ÍÀº ÀνĵÇÁö ¾Ê´Â °ªÀÌ 0À̹ǷΠ¹«¹æÇÒ °ÍÀÌ´Ù.

bg_pixmapÀº À§ÀÇ °æ¿ì¿Í ¸Å¿ì ºñ½ÁÇÏ´Ù, color°¡ filenameÀ¸·Î ´ëÄ¡µÉ »Ó.

pixmap_path´Â ":"À¸·Î ±¸ºÐµÈ °æ·ÎÀÇ ¸®½ºÆ®´Ù. ÀÌ °æ·Î´Â ¿ì¸®°¡ ¼³Á¤ÇÑ ´ë·Î ¾î¶² ÇȽº¸ÊÀÌ¶óµµ Ã£À» °ÍÀÌ´Ù.

fontµµ Á÷°üÀûÀ¸·Î ÀÌ·¸°Ô¸¸ ÇÏ¸é µÈ´Ù.

font = "<font name>"

µü Çϳª ¾î·Á¿î °Ô ÀÖ´Ù¸é ÆùÆ® À̸§ÀÇ ¹®ÀÚ¿­À» ´Ù·ç´Â °ÍÀÌ´Ù. xfontsel À̳ª À¯»çÇÑ À¯Æ¿¸®Æ¼µéÀÌ µµ¿òÀÌ µÉ °ÍÀÌ´Ù.

"widget_class"´Â widgetµéÀÇ Å¬·¡½º ½ºÅ¸ÀÏÀ» ¼¼ÆÃÇÑ´Ù. ÀÌ Å¬·¡½ºµéÀº widgetÀÇ °³¿ä ºÎºÐ¿¡¼­ º¸ÀΠŬ·¡½º °èÃþ±¸Á¶¿¡ ³ª¿Í ÀÖ´Ù.

"widget"Àº Á÷°üÀûÀ¸·Î, À̸§ ºÙ¿©Áø widgetÀÇ ÁýÇÕÀ» ÁÖ¾îÁø ½ºÅ¸ÀÏ´ë·Î ¼³Á¤Çϸç, ÁÖ¾îÁø widget Ŭ·¡½º¿¡ ´ëÇØ ¾î¶² ½ºÅ¸ÀÏÀÌ¶óµµ ¿À¹ö·ÎµåÇÑ´Ù. ÀÌ·± widgetµéÀº gtk_widget_set_name() ÇÔ¼ö¿¡ ÀÇÇØ ¾îÇà ³»ºÎ¿¡ µî·ÏµÇ¾î ÀÖ´Ù. ÀÌ°ÍÀº widget Ŭ·¡½º ÀüüÀûÀ¸·Î°¡ ¾Æ´Ï¶ó ¾î¶² widgetÀ» basis·Î ÇÏ°í ÀÖ´Â ¾î´À ÇÑ widgetÀÇ Æ¯¼ºÀ» ¼³Á¤ÇØ ÁÙ ¼ö ÀÖµµ·Ï ÇÑ´Ù. »ç¿ëÀÚµéÀÌ ³ª¸§´ë·Î ¼³Á¤ Çؼ­ ÀÌ¿ëÇÒ ÀÖµµ·Ï, ÀÌ·± Ưº°ÇÑ widgetÀ̶ó¸é ¹¹µçÁö ¹®¼­È­ÇØ µÑ °ÍÀ» Àû±Ø ±ÇÇÏ´Â ¹ÙÀÌ´Ù.

Å°¿öµå "parent"°¡ ¼Ó¼º ¼³Á¤¿¡ ¾²À̸é, ±× widgetÀº parentÀÇ ¼Ó¼ºÀ» µû¸£°Ô µÈ´Ù.

½ºÅ¸ÀÏÀ» Á¤ÀÇÇϸ鼭, ÀÌÀü¿¡ Á¤ÀÇµÈ ½ºÅ¸ÀÏÀ» »õ·Î¿î °Í¿¡ ´ëÀÔÇØ ÁÖ´Â °Íµµ °¡´ÉÇÏ´Ù.

style "main_button" = "button"
{
        font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
        bg[PRELIGHT] = { 0.75, 0, 0 }
}

ÀÌ ¿¹Á¦´Â "button"ÀÇ ½ºÅ¸ÀÏÀ» ÃëÇؼ­, ´ÜÁö ÀÌ°Í¿¡¼­ font¿Í prelight background color¸¦ ¹Ù²Ù´Â °ÍÀ¸·Î »õ·Î¿î "main_button" ½ºÅ¸ÀÏÀ» ¸¸µé¾î³½´Ù.

¹°·Ð, ÀÌ·± ¼Ó¼º Áß ¸¹Àº °ÍµéÀº ¸ðµç widget¿¡ ´ëÇØ Àû¿ë°¡´ÉÇÑ °ÍÀÌ ¾Æ´Ï´Ù. ÀÌ°ÍÀº »ó½ÄÀûÀÌ°í °£´ÜÇÑ °ÍÀÌ´Ù. Àû¿ë°¡´ÉÇÑ °ÍÀÌ ÀÖ´Ù¸é Àû¿ëÇÏ¸é µÈ´Ù.

19.3 rc ÆÄÀÏÀÇ ¿¹Á¦

# pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
#
pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
#
# style <name> [= <name>]
# {
#   <option>
# }
#
# widget <widget_set> style <style_name>
# widget_class <widget_class_set> style <style_name>

# ÀÌ°ÍÀº °¡´ÉÇÑ stateµéÀÇ ¸®½ºÆ®´Ù.  À̵é Áß ÀϺδ ƯÁ¤ÇÑ widgetµé¿¡
# ´ëÇؼ­´Â Àû¿ëµÇÁö ¾ÊÀ½À» ÁÖÀÇÇ϶ó.
#
# NORMAL - The normal state of a widget, without the mouse over top of
# it, and not being pressed etc.
#
# PRELIGHT - When the mouse is over top of the widget, colors defined
# using this state will be in effect.
#
# ACTIVE - When the widget is pressed or clicked it will be active, and
# the attributes assigned by this tag will be in effect.
#
# INSENSITIVE - When a widget is set insensitive, and cannot be
# activated, it will take these attributes.
#
# SELECTED - When an object is selected, it takes these attributes.
#
# Given these states, we can set the attributes of the widgets in each of
# these states using the following directives.
#
# fg - Sets the foreground color of a widget.
# fg - Sets the background color of a widget.
# bg_pixmap - Sets the background of a widget to a tiled pixmap.
# font - Sets the font to be used with the given widget.
#

# ¿©±â¼­ "button"À̶ó ºÒ¸®¿ì´Â ½ºÅ¸ÀÏÀ» ¼¼ÆÃÇÑ´Ù.  ÆÄÀÏÀÇ ¸¶Áö¸· ºÎºÐ¿¡¼­
# ½ÇÁ¦ÀÇ widget¿¡ ÁöÁ¤µÇ°í ÀÖÀ¸¹Ç·Î ¿©±â¼­ÀÇ À̸§Àº Áß¿äÇÏÁö ¾Ê´Ù.

style "window"
{
        # ÀÌ°ÍÀº ÁÖ¾îÁø ÇȽº¸ÊÀ¸·Î À©µµÀÇ ÆеùÀ» ¼¼ÆÃÇÑ´Ù.
        #bg_pixmap[<STATE>] = "<pixmap filename>"
        bg_pixmap[NORMAL] = "warning.xpm"
}

style "scale"
{
        # "NORMAL" state¿¡¼­ foreground(font) »ö±òÀ» red·Î ¼¼ÆÃÇÑ´Ù.

        fg[NORMAL] = { 1.0, 0, 0 }

        # ÀÌ widgetÀÇ background pixmapÀ» parentÀÇ ±×°ÍÀ¸·Î ¼¼ÆÃÇÑ´Ù.
        bg_pixmap[NORMAL] = "<parent>"
}

style "button"
{
        # ¿©±â¼­ ¾î¶² ¹öÆ°¿¡ ´ëÇÏ¿© °¡´ÉÇÑ ¸ðµç state¸¦ º¸¿©ÁØ´Ù.  µü Çϳª
        # Àû¿ëµÇÁö ¾Ê´Â °ÍÀº SELECTED state´Ù.

        fg[PRELIGHT] = { 0, 1.0, 1.0 }
        bg[PRELIGHT] = { 0, 0, 1.0 }
        bg[ACTIVE] = { 1.0, 0, 0 }
        fg[ACTIVE] = { 0, 1.0, 0 }
        bg[NORMAL] = { 1.0, 1.0, 0 }
        fg[NORMAL] = { .99, 0, .99 }
        bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
        fg[INSENSITIVE] = { 1.0, 0, 1.0 }
}

# ÀÌ ¿¹Á¦¿¡¼­, ¿ì¸®´Â "button" ½ºÅ¸ÀÏÀÇ ¼Ó¼ºÀ» »ó¼Ó¹Þ´Â´Ù.  ±×¸®°í 
# »õ·Î "main_button" ½ºÅ¸ÀÏÀ» ¸¸µé°Ô µÉ¶§¸é font¿Í background »ö±òÀº
# µû·Î ÁöÁ¤Çؼ­ ¾´´Ù.

style "main_button" = "button"
{
        font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
        bg[PRELIGHT] = { 0.75, 0, 0 }
}

style "toggle_button" = "button"
{
        fg[NORMAL] = { 1.0, 0, 0 }
        fg[ACTIVE] = { 1.0, 0, 0 }

        # toggle_buttonÀÇ background pixmapÀ» ±×°ÍÀÇ parent widget(¾îÇÿ¡¼­
        # Á¤Àǵȴë·Î)ÀÇ ¼Ó¼ºÀ¸·Î ¼¼ÆÃÇÑ´Ù.
        bg_pixmap[NORMAL] = "<parent>"
}

style "text"
{
        bg_pixmap[NORMAL] = "marble.xpm"
        fg[NORMAL] = { 1.0, 1.0, 1.0 }
}

style "ruler"
{
        font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
}

# pixmap_path "~/.pixmaps"

# À̵éÀº widgetÀÇ Å¸ÀÔµéÀ» À§¿¡¼­ Á¤ÀÇµÈ ½ºÅ¸ÀÏ¿¡ µû¸£°Ô ÇÑ´Ù.
# Widget ŸÀÔµéÀº Ŭ·¡½º °èÃþ±¸Á¶¿¡ ¸®½ºÆ®µÇ¾î ÀÖÁö¸¸, ÀÌ ¹®¼­¿¡ ¸®½ºÆ®µÈ
# °Íµéµµ »ç¿ëÀڵ鿡°Ô ÁÁÀº Âü°í°¡ µÉ ¼ö ÀÖ´Ù.

widget_class "GtkWindow" style "window"
widget_class "GtkDialog" style "window"
widget_class "GtkFileSelection" style "window"
widget_class "*Gtk*Scale" style "scale"
widget_class "*GtkCheckButton*" style "toggle_button"
widget_class "*GtkRadioButton*" style "toggle_button"
widget_class "*GtkButton*" style "button"
widget_class "*Ruler" style "ruler"
widget_class "*GtkText" style "text"

# ÀÌ°ÍÀº ¸ðµç ¹öÆ°µé("main window"ÀÇ childrenµé)À» main_buttonÀÇ ½ºÅ¸ÀÏ
# ´ë·Î ¼¼ÆÃÇÑ´Ù.
widget "main window.*GtkButton*" style "main_button"

20. ÀڽŸ¸ÀÇ widget ¸¸µé±â

20.1 °³¿ä

ºñ·Ï GTK ¹èÆ÷ÆÇ¿¡ Æ÷ÇԵǾî ÀÖ´Â ¼ö¸¹Àº widgetµéÀÌ ´ëºÎºÐÀÇ ±âº»ÀûÀÎ ¿ä±¸»çÇ×À» ÃæÁ·½ÃÄÑ ÁÖÁö¸¸, ¾ðÁ¨°¡ ½º½º·Î »õ·Î¿î widgetÀ» ¸¸µé¾î¾ß ÇÒ ¶§°¡ ¿Ã °ÍÀÌ´Ù. GTK°¡ widgetÀÇ »ó¼ÓÀ» ±¤¹üÀ§ÇÏ°Ô ÀÌ¿ëÇÏ°í ¶Ç ÀÌ ¸¸µé¾îÁ® ÀÖ´Â widgetµéÀÌ ¿©·¯ºÐÀÇ ¿ä±¸¿¡ ±ÙÁ¢ÇÑ °ÍµéÀ̱⠶§¹®¿¡, À¯¿ëÇÏ°í »õ·Î¿î widgetÀ» ¸¸µå´Â °Íµµ ´ÜÁö ¸î ÁÙÀÇ ÄÚµå·Î½á °¡´ÉÇÒ ¼öµµ ÀÖ´Ù. ±×·¯³ª »õ·Î¿î widgetÀ» ¸¸µå´Â ÀÛ¾÷À» ½ÃÀÛÇϱâ Àü¿¡, ¸ÕÀú ´©±º°¡ ±×°ÍÀ» ÀÌ¹Ì ¸¸µé¾î ³õÁö ¾Ê¾Ò´ÂÁö üũÇÏÀÚ. ÀÌ·¸°Ô Çؼ­ ³ë·ÂÀÇ Áߺ¹À» ¸·°í ¶Ç GTK widgetÀÇ °¹¼ö¸¦ ÃÖ¼ÒÇÑÀ¸·Î À¯ÁöÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ¼­·Î ´Ù¸¥ ¾îÇÃµé »çÀÌ¿¡¼­ ÄÚµå¿Í ÀÎÅÍÆäÀ̽º ¸ðµÎÀÇ ÅëÀϼºÀ» À¯ÁöÇÏ´Â °ÍÀÌ´Ù. ÀÌ·¸°Ô ÇÏ´Â ÇÑ°¡Áö ¹æ¹ýÀ¸·Î, ¸¸¾à ¿©·¯ºÐÀÌ ÀڽŸ¸ÀÇ widgetÀ» ¿Ï¼ºÇÏ°Ô µÇ¸é, ±×°ÍÀ» ´Ù¸¥ »ç¶÷µé ¸ðµÎ ÀÌ¿ëÇÒ ¼ö ÀÖ°Ô ¼¼°è¿¡ ³Î¸® ¾Ë¸®ÀÚ. ÀÌ·¸°Ô ÇÒ ¼ö ÀÖ´Â °¡Àå ÁÁÀº Àå¼Ò´Â ¾Æ¸¶ gtk-listÀÏ °ÍÀÌ´Ù.

¿¹Á¦µéÀÇ ¿ÏÀüÇÑ ¼Ò½º ÄÚµå´Â ´ç½ÅÀÌ ÀÌ ¹®¼­¸¦ ±¸ÇÑ °÷À̳ª ¶Ç´Â ´ÙÀ½ Àå¼Ò¿¡¼­ ±¸ÇÒ ¼ö ÀÖ´Ù.

http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

20.2 WidgetÀÇ ±¸Á¶

»õ·Î¿î 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½ºÆ®µÉ ¼öµµ ÀÖ´Â °ÍÀÌ´Ù.

20.3 Composite(ÇÕ¼º,È¥¼º) widget ¸¸µé±â

¼Ò°³

¿ì¸®°¡ ¸¸µé°íÀÚ ÇÏ´Â ¾î¶² widgetÀº ´ÜÁö ´Ù¸¥ GTK widgetµéÀÇ ÁýÇÕüÀÏ »ÓÀÏ ¼öµµ ÀÖ´Ù. ÀÌ·± widgetÀº ²À »õ·Î¿î °ÍÀ¸·Î ¸¸µé¾îÁ®¾ß ÇÒ °ÍÀº ¾Æ´ÏÁö¸¸, Àç»ç¿ë¼ºÀ» À§ÇØ »ç¿ëÀÚ ÀÎÅÍÆäÀ̽ºÀûÀÎ ¿ä¼ÒµéÀ» ÆÐŰ¡ÇÏ´Â µ¥ ÀÖ¾î Æí¸®ÇÑ ¹æ½ÄÀ» Á¦°øÇÑ´Ù. Ç¥ÁØ GTK ¹èÆ÷ÆÇ¿¡ ÀÖ´Â FileSelection°ú ColorSelection widgetÀÌ ¿¹°¡ µÉ °ÍÀÌ´Ù.

¿ì¸®°¡ ¿©±â¼­ ¸¸µé·Á´Â ¿¹Á¦´Â Tictactoe widgetÀ¸·Î, Åä±Û¹öÆ°ÀÇ 3x3 ¹è¿­ ¿¡¼­ ¾î´À ÇÑ Çà ¶Ç´Â ¿­ ¶Ç´Â ´ë°¢¼ººÐ ¸ðµÎ°¡ ´­·¯Áö°Ô µÇ¸é ½Ã±×³ÎÀ» ³»º¸³½ ´Ù.

Parent class¸¦ °í¸£±â

ÀüÇüÀûÀ¸·Î 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;
}

20.4 ¹«¿¡¼­(from scratch) widget ¸¸µé±â

¼Ò°³

À̹ø ¼½¼Ç¿¡¼­´Â widgetµéÀÌ ±× ÀڽŵéÀ» ¾î¶»°Ô ½ºÅ©¸°¿¡ º¸ÀÌ°Ô ÇÏ´ÂÁö, ±×¸®°í À̺¥Æ®¿Í »óÈ£ÀÛ¿ë ÇÏ´ÂÁö¸¦ ´õ °øºÎÇÒ °ÍÀÌ´Ù. ÀÌ¿¡ ´ëÇÑ ¿¹Á¦·Î ¿ì¸®´Â Æ÷ÀÎÅÍ°¡ ´Þ·ÁÀÖ´Â ¾Æ³¯·Î±× ´ÙÀ̾ó(analog dial) widgetÀ» ¸¸µé¾î¼­, »ç¿ëÀÚ°¡ ±×°É ²ø¾î¼­ °ªÀ» ¼¼ÆÃÇϵµ·Ï ÇÒ °ÍÀÌ´Ù.

½ºÅ©¸°¿¡ widgetÀ» º¸À̱â

½ºÅ©¸°¿¡ º¸¿©ÁÖ±â À§Çؼ­ ¸î°¡Áö ´Ü°è°¡ ÀÖ´Ù. WidgetÀÌ WIDGETNAME_new() ·Î½á ¸¸µé¾îÁö°í ³ª¼­, ¸î°³ÀÇ ÇÔ¼ö°¡ ´õ ÇÊ¿äÇÏ´Ù.

  • ÇØ´çÇÏ´Â widget¿¡ ´ëÇØ 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() ÇÔ¼ö¸¸À» °®Ãá´Ù.

Dial WidgetÀÇ ±â¿ø

Áö»óÀÇ ¸ðµç µ¿¹°µéÀÌ ÁøÈëÅÁ¿¡¼­ óÀ½À¸·Î ±â¾î³ª¿Â ¾ç¼­·ùÀÇ º¯Á¾µéÀÎ °Íó·³, 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;
                }
}

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;
}

À̺¥Æ® ´Ù·ç±â

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À» ½ÇÁ¦·Î ±¸ÇöÇØ º¸¸é, Æ÷ÀÎÅÍ°¡ µå·¡±×µÇ¸é¼­ ¾à°£ÀÇ ¹ø½°Å¸²ÀÌ ÀÖÀ½À» ¹ß°ßÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ÀÌ°ÍÀº Æ÷ÀÎÅÍ°¡ À̵¿ÇÒ ¶§¸¶´Ù redrawµÇ±â ÀÌÀü¿¡ widget Àüü°¡ Áö¿öÁö±â ¶§¹®ÀÌ´Ù. ÀÌ ¹®Á¦¸¦ ÇØ°áÇÏ´Â °¡Àå ÁÁÀº ¹æ¹ýÀº º¸ÀÌÁö ¾Ê´Â(offscreen) ÇȽº¸Ê¿¡ ±×·ÁÁÖ°í, ±×¸®°í´Â ÃÖÁ¾ °á°ú¹°À» ½ºÅ©¸° À§·Î ´Ü¹ø¿¡ º¹»çÇØ ÁÖ´Â °ÍÀÌ´Ù. (ÁøÇื´ë(progress bar) widgetÀÌ ÀÌ·± ½ÄÀ¸·Î º¸¿©Á³¾ú´Ù.)
  • »ç¿ëÀÚ´Â °ªÀ» º¯È­½ÃÅ°±â À§Çؼ­ up ¹× down È­»ìǥŰ(arrow key)¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ¾î¾ß ÇÒ °ÍÀÌ´Ù.
  • ¿ì¸® widgetÀÌ Å©°Å³ª ÀÛÀº ÆøÀ¸·Î °ªÀ» Áõ°¨½Ãų ¼ö ÀÖ´Â ¹öÆ°À» °¡Áø´Ù¸é ±¦ÂúÀº ±â´ÉÀÌ µÉ °ÍÀÌ´Ù. À̸¦ À§ÇØ ³»ÀåµÈ ¹öÆ° widgetÀ» ÀÌ¿ëÇÏ´Â °Íµµ °¡´ÉÇÏ°ÚÁö¸¸, ¿ì¸®´Â ¶ÇÇÑ ÀÌ ¹öÆ°µéÀÌ °è¼Ó ´­·¯Áø »óÅ¿¡¼­ auto-repeat µÇµµ·Ï ÇÏ°í½Í´Ù, ½ºÅ©·Ñ¹Ù¿¡ ÀÖ´Â È­»ìÇ¥µéó·³. ÀÌ·± ½ÄÀÇ µ¿ÀÛµéÀ» °®Ãß°Ô ÇØÁÖ´Â ´ëºÎºÐÀÇ ÄÚµå´Â GtkRange widget¿¡¼­ ãÀ» ¼ö ÀÖ´Ù.
  • ´ÙÀ̾ó(Dial) widgetÀº ¾Õ¿¡¼­ ¾ð±ÞµÈ ¹öÆ°µéÀÇ ¹Ù´Ú¿¡ À§Ä¡ÇÑ ÇϳªÀÇ child widgetÀ» °¡Áø, ÄÁÅ×ÀÌ³Ê widgetÀ¸·Î ¸¸µé¾îÁú ¼ö ÀÖ´Ù. ±×·¯¸é »ç¿ëÀÚ´Â ´ÙÀ̾óÀÇ ÇöÀç°ªÀ» º¸À̱â À§ÇØ ¿øÇÏ´Â ¶óº§À̳ª ¿£Æ®¸® widgetÀ» ´õÇØÁÙ ¼ö ÀÖ´Ù.

20.5 ´õ ¹è¿öº¸±â

WidgetÀ» ¸¸µé±â À§ÇÑ ¼ö¸¹Àº Ç׸ñµé Áß ±ØÈ÷ ÀϺθ¸ÀÌ À§¿¡¼­ ¼Ò°³µÇ¾ú´Ù. ÀÚ½ÅÀÇ widgetÀ» ¸¸µé·Á´Â ÀÌ¿¡°Ô, °¡Àå ÁÁÀº ¼Ò½º´Â GTK ±× ÀÚüÀÏ °ÍÀÌ´Ù. ¿©·¯ºÐÀÌ ¸¸µé·Á´Â widget¿¡ ´ëÇØ ½º½º·Î ¸î°¡Áö Áú¹®À» Çغ¸ÀÚ. ÀÌ°ÍÀº Container widgetÀΰ¡? ÀÌ°ÍÀº °ü·ÃµÈ À©µµ¸¦ °¡Áö°í Àִ°¡? ÀÌ°ÍÀº ÀÌ¹Ì Á¸ÀçÇÏ´Â widgetÀÇ º¯ÇüÀΰ¡? ±×¸®°í´Â À¯»çÇÑ widgetÀ» ã°í, º¯È­¸¦ Áֱ⠽ÃÀÛÇÏ´Â °ÍÀÌ´Ù. Çà¿îÀ» ºó´Ù!

21. ³«¼­Àå, °£´ÜÇÑ ±×¸®±â ¿¹Á¦

21.1 °³¿ä

¿©±â¼­ ¿ì¸®´Â °£´ÜÇÑ ±×¸®±â ÇÁ·Î±×·¥À» ¸¸µé °ÍÀÌ´Ù. ±× °úÁ¤¿¡¼­ ¿ì¸®´Â ¸¶¿ì½º À̺¥Æ®¸¦ ¾î¶»°Ô ´Ù·ç´ÂÁö ¾Ë¾Æº¼ °ÍÀÌ°í, À©µµ ¾È¿¡ ¾î¶»°Ô ±×¸²À» ±×¸®´ÂÁö, ±×¸®°í ÇȽº¸ÊÀ» ¹è°æÀ¸·Î Çؼ­ ´õ ³ªÀº ±×¸²À» ±×¸®´Â ¹æ¹ýµµ ¹è¿ï °ÍÀÌ´Ù. °£´ÜÇÑ ±×¸®±â ÇÁ·Î±×·¥À» ¸¸µç ÈÄ¿¡, ¿ì¸®´Â ±×°Í¿¡ drawing tablet °°Àº XInput device¸¦ Áö¿øÇÏ´Â µîÀÇ È®ÀåÀ» ½ÃµµÇÒ °ÍÀÌ´Ù. GTK´Â ±×·± device µé·ÎºÎÅÍ pressure¿Í tilt°°Àº, È®ÀåµÈ Á¤º¸¸¦ ¾ò¾î³¾ ¼ö ÀÖ°Ô ÇÏ´Â support routineÀ» Á¦°øÇÑ´Ù.

21.2 À̺¥Æ® ´Ù·ç±â

¿ì¸®°¡ ÀÌ¹Ì »ìÆ캻 GTKÀÇ ½Ã±×³ÎÀº ¸Þ´º ¾ÆÀÌÅÛ ¼±ÅÃó·³ °í¼öÁØÀÇ µ¿ÀÛÀ» À§ÇÑ °ÍµéÀÌ´Ù. ÇÏÁö¸¸, ¸¶¿ì½ºÀÇ ¿òÁ÷ÀÓÀ̶óµçÁö Å°º¸µåÀÇ ´­·¯Áü°°Àº, Àú¼öÁØÀÇ Á¦¾î¸¦ °øºÎÇÏ´Â °Íµµ ¶§¶§·Î À¯¿ëÇÒ °ÍÀÌ´Ù. GTK ½Ã±×³Î Áß¿¡´Â ÀÌ·± Àú¼öÁØÀÇ À̺¥Æ®¸¦ À§ÇÑ °Íµéµµ ÀÖ´Ù. ÀÌ·± À̺¥Æ®¸¦ À§ÇÑ Çڵ鷯´Â ±×·± À̺¥Æ®¿¡ ´ëÇÑ Á¤º¸¸¦ °¡Áö°í ÀÖ´Â ±¸Á¶Ã¼¸¦ °¡¸®Å°°í ÀÖ´Â ¶Ç´Ù¸¥ ÀÎÀÚµéÀ» °¡Áö°Ô µÈ´Ù. ¿¹¸¦µé¾î, motion event Çڵ鷯´Â ¾Æ·¡¿Í °°Àº GdkEventMotion ±¸Á¶Ã¼¸¦ ÇâÇÑ Æ÷ÀÎÅ͸¦ ÀÎÀÚ·Î °¡Áö°í ÀÖ´Ù.

struct _GdkEventMotion
{
        GdkEventType type;
        GdkWindow *window;
        guint32 time;
        gdouble x;
        gdouble y;
        ...
        guint state;
        ...
};

ÀÎÀÚ typeÀº À̺¥Æ®ÀÇ Å¸ÀÔÀÌ µÇ°í, ÀÌ °æ¿ì¿¡´Â GDK_MOTION_NOTIFYÀÌ´Ù. ÀÎÀÚ window´Â ±× À̺¥Æ®°¡ ¹ß»ýÇÑ À©µµ°¡ µÉ °ÍÀÌ´Ù. ÀÎÀÚ x¿Í y´Â ±× À̺¥Æ®ÀÇ ÁÂÇ¥À̸ç, state´Â À̺¥Æ®°¡ ¹ß»ýÇßÀ» ¶§ÀÇ modifier state¸¦ ¼³Á¤ÇÑ´Ù(Áï, ¾î¶² modifier key¿Í modifier buttonÀÌ ´­·¯Á³´ÂÁö ¼³Á¤). ÀÌ°ÍÀº ¾Æ·¡ º¸ÀÌ´Â »ó¼ö°ªµéÀ» ºñÆ® OR½ÃŲ °ÍÀÌ´Ù.

GDK_SHIFT_MASK
GDK_LOCK_MASK
GDK_CONTROL_MASK
GDK_MOD1_MASK
GDK_MOD2_MASK
GDK_MOD3_MASK
GDK_MOD4_MASK
GDK_MOD5_MASK
GDK_BUTTON1_MASK
GDK_BUTTON2_MASK
GDK_BUTTON3_MASK
GDK_BUTTON4_MASK
GDK_BUTTON5_MASK

´Ù¸¥ ½Ã±×³Îµé¿¡ ´ëÇؼ­Ã³·³, À̺¥Æ®°¡ ¹ß»ýÇßÀ» ¶§ ±×°ÍÀÌ ¾î¶² °ÇÁö °áÁ¤ Çϱâ À§ÇØ ¿ì¸®´Â gtk_signal_connect()¸¦ ÀÌ¿ëÇÑ´Ù. ±×·¯³ª ¶ÇÇÑ ¿ì¸®°¡ ¾î¶² À̺¥Æ®°¡ ŽÁöµÇ¾îÁö±æ ¿øÇÏ´ÂÁö GTK°¡ ¾Ë ¼ö ÀÖµµ·Ï ÇؾßÇÑ´Ù. À̸¦ À§Çؼ­´Â ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

void       gtk_widget_set_events          (GtkWidget           *widget,
                                           gint                 events);

µÎ ¹ø° ÀÎÀÚ´Â ¿ì¸®°¡ °ü½ÉÀ» °¡Áø À̺¥Æ®¸¦ ¼³Á¤ÇÑ´Ù. ÀÌ°ÍÀº ¿©·¯ °¡ÁöÀÇ À̺¥Æ®¸¦ À§Çؼ­ ¸î°¡Áö »ó¼ö¸¦ ºñÆ® OR½ÃŲ °ÍÀÌ´Ù. ¾ÕÀ¸·ÎÀÇ ÂüÁ¶¸¦ À§Çؼ­ ÀÌ »ó¼öµé¸¦ ¼Ò°³ÇÑ´Ù.

GDK_EXPOSURE_MASK
GDK_POINTER_MOTION_MASK
GDK_POINTER_MOTION_HINT_MASK
GDK_BUTTON_MOTION_MASK
GDK_BUTTON1_MOTION_MASK
GDK_BUTTON2_MOTION_MASK
GDK_BUTTON3_MOTION_MASK
GDK_BUTTON_PRESS_MASK
GDK_BUTTON_RELEASE_MASK
GDK_KEY_PRESS_MASK
GDK_KEY_RELEASE_MASK
GDK_ENTER_NOTIFY_MASK
GDK_LEAVE_NOTIFY_MASK
GDK_FOCUS_CHANGE_MASK
GDK_STRUCTURE_MASK
GDK_PROPERTY_CHANGE_MASK
GDK_PROXIMITY_IN_MASK
GDK_PROXIMITY_OUT_MASK

gtk_widget_set_events()¸¦ È£ÃâÇÒ ¶§ °üÂûµÇ¾î¾ß ÇÒ ¸î °³ÀÇ ¹Ì¹¦ÇÑ »çÇ×ÀÌ ÀÖ´Ù. ¸ÕÀú, ±×°ÍÀº GTK widgetÀ» À§ÇÑ XÀ©µµ°¡ ¸¸µé¾îÁö±â ÀÌÀü¿¡ È£ÃâµÇ¾î¾ß ÇÑ´Ù. Áï, ÀÌ°ÍÀº widgetÀ» »õ·Î ¸¸µç Á÷ÈÄ¿¡ È£ÃâµÇ¾î¾ß ÇÑ´Ù´Â ¸»ÀÌ´Ù. µÑ° ·Î, ±× widgetÀº °ü·ÃµÈ XÀ©µµ¸¦ ²À °¡Á®¾ß ÇÑ´Ù. È¿À²À» À§Çؼ­ ¸¹Àº widget typeµéÀº ±×µé¸¸ÀÇ À©µµ¸¦ °¡ÁöÁö ¾Ê°í ±×µéÀÇ parent À©µµ ¾È¿¡ ±×·Á³Ö´Â´Ù. ÀÌ·± widgetÀº ´ÙÀ½°ú °°Àº °ÍµéÀÌ´Ù.

GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkImage
GtkItem
GtkLabel
GtkPaned
GtkPixmap
GtkScrolledWindow
GtkSeparator
GtkTable
GtkViewport
GtkAspectFrame
GtkFrame
GtkVPaned
GtkHPaned
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator

ÀÌ·± À̺¥Æ®µéÀ» ŽÁöÇϱâ À§ÇØ ¿ì¸®´Â EventBox widgetÀ» ÇÊ¿ä·Î ÇÑ´Ù. ÀÚ¼¼ ÇÑ °ÍÀº The EventBox WidgetÀ» ÂüÁ¶Ç϶ó.

¿ì¸®ÀÇ ±×¸®±â ÇÁ·Î±×·¥¿¡¼­´Â ¸¶¿ì½º ¹öÆ°ÀÌ ´­·¯Áö´Â °Í°ú ¿òÁ÷ÀÌ´Â °ÍÀ» ŽÁöÇÏ°í ½Í¾îÇϹǷÎ, GDK_POINTER_MOTION_MASK¿Í GDK_BUTTON_PRESS_MASK¸¦ ¼³Á¤ÇÑ´Ù. ¿ì¸®´Â ¶ÇÇÑ À©µµ°¡ ´Ù½Ã ±×·ÁÁ®¾ß ÇÒ ¶§¸¦ ¾Ë¾Æ¾ß ÇϹǷΠGDK_EXPOSURE_MASKµµ ¼³Á¤ÇÑ´Ù. ºñ·Ï ¿ì¸®´Â À©µµÀÇ Å©±â°¡ º¯ÇßÀ» ¶§¸¦ Configure event·Î½á ŽÁöÇØ¾ß ÇÏÁö¸¸, ¿ì¸®´Â À̸¦ À§ÇØ GDK_STRUCTURE_MASK flag¸¦ ¼³Á¤ÇÒ ÇÊ¿ä°¡ ¾ø´Ù. ÀÌ°ÍÀº ¸ðµç À©µµ¿¡ ´ëÇØ ÀÚµ¿ÀûÀ¸·Î ¼³Á¤µÇ±â ¶§¹®ÀÌ´Ù.

±×·±µ¥ GDK_POINTER_MOTION_MASK¸¦ ¼³Á¤ ÇÏ´Â µ¥ ÀÖ¾î ¹®Á¦Á¡ÀÌ ÀÖ´Ù´Â °ÍÀÌ ¹àÇôÁú °ÍÀÌ´Ù. ÀÌ°ÍÀº »ç¿ëÀÚ°¡ ¸¶¿ì½º¸¦ ¿òÁ÷ÀÏ ¶§¸¶´Ù ¼­¹ö°¡ event queue¿¡ motion event¸¦ °è¼Ó ´õÇÒ °ÍÀÌ´Ù. ¾î¶² motion event¸¦ ´Ù·ç±â À§ÇØ 0.1ÃÊ°¡ °É¸°´Ù°í »ý°¢ÇØ º¸ÀÚ. ±×·¯³ª X ¼­¹ö´Â ¸Å 0.05Ãʸ¶´Ù »õ·Î¿î motionÀ» queue¿¡ ÀúÀåÇÑ´Ù. ¿ì¸®´Â °ð »ç¿ëÀÚ°¡ ±×¸®´Â µ¥ ´ëÇÑ ¹æ¹ýÀ» °¡Áö°Ô µÉ °ÍÀÌ´Ù. ¸¸¾à »ç¿ëÀÚ°¡ 5Ãʵ¿¾È ±×¸²À» ±×¸®¸é, ±×µéÀÌ ¸¶¿ì½º ¹öÆ°À» ³õ°í ³­ ÈÄ ¶Ç´Ù¸¥ 5ÃÊ°¡, ±×°ÍÀ» Àâ¾Æ³»±â À§ÇØ ÇÊ¿äÇÏ°Ô µÉ °ÍÀÌ´Ù. ¿ì¸®°¡ ¿øÇÏ´Â °ÍÀº ÁøÇàµÇ´Â °¢°¢ÀÇ À̺¥Æ®¿¡ ´ëÇØ ´Ü ÇϳªÀÇ motion event¸¦ ŽÁöÇÏ´Â °ÍÀÌ´Ù. ÀÌ·¸°Ô Çϱâ À§Çؼ­ ¿ì¸®´Â GDK_POINTER_MOTION_HINT_MASK¸¦ ¼³Á¤ÇÑ´Ù.

¿ì¸®°¡ GDK_POINTER_MOTION_HINT_MASK¸¦ ¼³Á¤Çϸé, ¼­¹ö´Â ¸¶¿ì½º Æ÷ÀÎÅÍ°¡ ¿ì¸®ÀÇ À©µµ¿¡ µé¾î¿À°í ³ª¼­ ¶Ç´Â ¹öÆ°ÀÇ press³ª release À̺¥Æ®°¡ ¹ß»ýÇÏ°í ³ª¼­ óÀ½À¸·Î ¿òÁ÷ÀÏ ¶§ motion event¸¦ º¸³»ÁØ´Ù. µÚµû¸£´Â motion event´Â ¿ì¸®°¡ ¾Æ·¡ÀÇ ÇÔ¼ö·Î½á ºÐ¸íÇÏ°Ô ¸¶¿ì½º Æ÷ÀÎÅÍÀÇ À§Ä¡¸¦ ¹°¾îº¼ ¶§±îÁö ¾ïÁ¦µÉ °ÍÀÌ´Ù.

GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y,
                                          GdkModifierType *mask);

(´õ °£´ÜÇÑ ¾²ÀÓ»õ¸¦ °¡Áø gtk_widget_get_pointer()¶ó´Â ÇÔ¼öµµ ÀÖÁö¸¸, ±×´ÙÁö À¯¿ëÇÏÁö´Â ¾ÊÀ½ÀÌ µå·¯³¯ °ÍÀÌ´Ù. ¿Ö³ÄÇÏ¸é ±×°ÍÀº ¸¶¿ì½º ¹öÆ°ÀÇ »óÅ¿¡ °ü°è ¾øÀÌ Æ÷ÀÎÅÍÀÇ À§Ä¡¸¸À» ¸»ÇØÁֱ⠶§¹®ÀÌ´Ù.)

¿ì¸®ÀÇ À©µµ¿¡ À̺¥Æ®¸¦ ¼¼ÆÃÇÏ´Â ÄÚµå´Â ±×·¯¹Ç·Î ÀÌ·± ½ÄÀ¸·Î µÉ °ÍÀÌ´Ù.

gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
          (GtkSignalFunc) expose_event, NULL);
gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
          (GtkSignalFunc) configure_event, NULL);
gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
          (GtkSignalFunc) motion_notify_event, NULL);
gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
          (GtkSignalFunc) button_press_event, NULL);
gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
                   | GDK_LEAVE_NOTIFY_MASK
                   | GDK_BUTTON_PRESS_MASK
                   | GDK_POINTER_MOTION_MASK
                   | GDK_POINTER_MOTION_HINT_MASK);

"expose_event"¿Í "configure_event"´Â ´ÙÀ½À» À§Çؼ­ ³²°ÜµÐ´Ù. "motion_ notify_event"¿Í "button_press_event"ÀÇ Çڵ鷯´Â ²Ï °£´ÜÇÏ´Ù.

static gint
button_press_event (GtkWidget *widget, GdkEventButton *event)
{
  if (event->button == 1 && pixmap != NULL)
      draw_brush (widget, event->x, event->y);
  return TRUE;
}
static gint
motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
{
  int x, y;
  GdkModifierType state;
  if (event->is_hint)
    gdk_window_get_pointer (event->window, &x, &y, &state);
  else
    {
      x = event->x;
      y = event->y;
      state = event->state;
    }
  if (state & GDK_BUTTON1_MASK && pixmap != NULL)
    draw_brush (widget, x, y);
  return TRUE;
}

21.3 DrawingArea widget, ±×¸®°í ±×¸®±â

ÀÌÁ¦ ½ºÅ©¸°¿¡ ±×¸²À» ±×¸®´Â °úÁ¤¿¡ ´ëÇØ ¾Ë¾Æº¸ÀÚ. À̶§ ÇÊ¿äÇÑ °ÍÀº DrawingArea widgetÀÌ´Ù. ±×¸²À» ±×¸®´Â ¿µ¿ªÀÇ widgetÀ̶õ º»ÁúÀûÀ¸·Î ´Ù¸§ ¾Æ´Ñ XÀ©µµ´Ù. ÀÌ°ÍÀº ¿ì¸®°¡ ¿øÇÏ´Â °ÍÀ» ¹«¾ùÀÌµç ±×·Á³ÖÀ» ¼ö ÀÖ´Â ºó ĵ¹ö½º´Ù. Drawing area´Â ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ ¸¸µé¾îÁø´Ù.

GtkWidget* gtk_drawing_area_new        (void);

ÀÌ widgetÀÇ µðÆúÆ® Å©±â´Â ÀÌ ÇÔ¼ö·Î½á ¼³Á¤ÇÑ´Ù.

void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
                                        gint                 width,
                                        gint                 height);

¸ðµç widget¿¡ ´ëÇØ ¿øÇÑ´Ù¸é ÀÌ µðÆúÆ® Å©±â´Â gtk_widget_set_usize()·Î½á ¿À¹ö·ÎµåµÉ ¼ö ÀÖ´Ù. ±×¸®°í »ç¿ëÀÚ°¡ Á÷Á¢ ±× drawing area¸¦ Æ÷ÇÔÇÑ À©µµÀÇ Å©±â¸¦ º¯°æÇÏ¸é ¿ª½Ã ¿À¹ö·ÎµåµÈ´Ù.

¿ì¸®°¡ DrawingArea widgetÀ» ¸¸µé ¶§, ±×¸± ´ë»óÀÌ ¹«¾ùÀΰ¡¿¡ ÀüÀûÀ¸·Î ÁÖÀǸ¦ ±â¿ï¿©¾ß ÇÑ´Ù. ¸¸¾à ¿ì¸®ÀÇ À©µµ°¡ °¨Ãß¾îÁ³´Ù°¡ ´Ù½Ã µå·¯³µ´Ù¸é, ¿ì¸®´Â exposure ¸¶½ºÅ©¸¦ ¼³Á¤ÇÏ°í ±×¸®°í ¿ø·¡ °¨Ãß¾îÁ³¾ú´ø ³»¿ëÀÌ ¹«¾ùÀ̾ú´ÂÁö ²À ´Ù½Ã ±×·ÁÁà¾ß ÇÑ´Ù. µ¡ºÙ¿©¼­, À©µµÀÇ ÀϺκÐÀÌ Áö¿öÁ³´Ù°¡ ´Ü°èÀûÀ¸·Î ´Ù½Ã ±×·ÁÁö´Â °ÍÀº ½Ã°¢ÀûÀ¸·Î »ê¸¸ÇØÁú ¼ö ÀÖ´Ù. ÀÌ·± ¹®Á¦¿¡ ´ëÇÑ ÇعýÀº offscreen backing pixmapÀ» ÀÌ¿ëÇÏ´Â °ÍÀÌ´Ù. ½ºÅ©¸° À§·Î ¹Ù·Î ±×¸®´Â ´ë½Å, º¸ÀÌÁö ¾Ê´Â ¼­¹ö ¸Þ¸ð¸®¿¡ ÀúÀåµÈ ¾î¶² À̹ÌÁö À§¿¡ ±×·Á³õ°í, À̹ÌÁö°¡ º¯Ç߰ųª ¶Ç´Â À̹ÌÁöÀÇ »õ·Î¿î ¿µ¿ªÀÌ º¸¿©Áö°Ô µÇ¸é ÇØ´çÇÏ´Â ¿µ¿ªÀ» ½ºÅ©¸°¿¡ º¹»çÇØ ÁÖ´Â °ÍÀÌ´Ù.

¾î¶² offscreen pixmapÀ» ¸¸µé±â À§ÇØ, ¿ì¸®´Â ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

GdkPixmap* gdk_pixmap_new (GdkWindow  *window,
                         gint        width,
                         gint        height,
                         gint        depth);

ÀÎÀÚ window´Â ÀÌ ÇȽº¸ÊÀÌ Æ¯¼ºÀ» À̾î¹ÞÀ» GDK À©µµ¸¦ ¼³Á¤ÇÑ´Ù. width¿Í height´Â ÇȽº¸ÊÀÇ Å©±â¸¦ Á¤ÇÑ´Ù. depth´Â color depth·Î¼­, ÀÌ »õ·Î¿î À©µµ¿¡¼­ÀÇ ÇÑ Çȼ¿´ç ºñÆ®ÀÇ ¼ö´Ù. ¸¸¾à depth°¡ -1·Î ¼³Á¤µÇ¸é, ±×°ÍÀº À©µµÀÇ depth¿Í ¶È°°¾ÆÁø´Ù.

¿ì¸®´Â ÇȽº¸ÊÀ» "configure_event" handler ¾È¿¡ ¸¸µç´Ù. ÀÌ À̺¥Æ®´Â À©µµ°¡ óÀ½ »ý¼ºµÉ ¶§¸¦ Æ÷ÇÔÇؼ­, À©µµÀÇ Å©±â°¡ º¯ÇÒ ¶§¸¶´Ù ¹ß»ýÇÑ´Ù.

/* ±×¸± ¿µ¿ª¿¡ ´ëÇÑ backing pixmap */
static GdkPixmap *pixmap = NULL;
/* Àû´çÇÑ Å©±âÀÇ backing pixmapÀ» Çϳª ¸¸µç´Ù. */
static gint
configure_event (GtkWidget *widget, GdkEventConfigure *event)
{
    if (pixmap)
        {
            gdk_pixmap_destroy(pixmap);
        }
    pixmap = gdk_pixmap_new(widget->window,
                            widget->allocation.width,
                            widget->allocation.height,
                            -1);
    gdk_draw_rectangle (pixmap,
                    widget->style->white_gc,
                    TRUE,
                    0, 0,
                    widget->allocation.width,
                    widget->allocation.height);
    return TRUE;
}

gdk_draw_rectangle()À» ºÎ¸£¸ç ÇȽº¸ÊÀ» white·Î ÃʱâÈ­ÇÑ´Ù. ¿©±â¿¡ ´ëÇØ Àá±ñ ´õ ¾ê±âÇÒ °ÍÀÌ´Ù. ±×·¯¸é ¿ì¸®ÀÇ exposure event handler´Â ´Ü¼øÈ÷ ±× ÇȽº¸ÊÀÇ °ü°èµÈ portionÀ» ½ºÅ©¸° À§·Î º¹»çÇÑ´Ù(¿ì¸®´Â exposure eventÀÇ event->area Çʵå·Î½á redrawÇÒ ¿µ¿ªÀ» °áÁ¤ÇÑ´Ù).

/* Backing pixmapÀ¸·ÎºÎÅÍ ½ºÅ©¸°À» º¹±¸ÇÑ´Ù. */
static gint
expose_event (GtkWidget *widget, GdkEventExpose *event)
{
    gdk_draw_pixmap(widget->window,
                    widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                    pixmap,
                    event->area.x, event->area.y,
                    event->area.x, event->area.y,
                    event->area.width, event->area.height);
    return FALSE;
}

¿ì¸®´Â ÀÌÁ¦ ÇȽº¸Ê¿¡ ´ëÇØ ¾î¶»°Ô ½ºÅ©¸°À» º¸Á¸ÇÏ´ÂÁö º¸¾Ò´Ù. ±×·±µ¥ ¿ì¸®ÀÇ ÇȽº¸Ê¿¡ ½ÇÁ¦·Î Àç¹ÌÀÖ´Â °ÍµéÀ» ¾î¶»°Ô ±×·Á³ÖÀ»±î? GTKÀÇ GDK ¶óÀ̺귯¸®¿¡´Â drawablesµéÀ» ±×¸®´Â µ¥ ÇÊ¿äÇÑ ¸¹Àº ¼öÀÇ ÇÔ¼öµéÀÌ ÀÖ´Ù. DrawableÀ̶õ °£´ÜÈ÷ ¾îµò°¡¿¡ ±×·ÁÁú ¼ö ÀÖ´Â ±× ¹«¾ùÀÌ´Ù. ¿©±â¼­ ¾îµð¶õ ÇϳªÀÇ window, pixmap, ¶Ç´Â bitmap(Èæ¹éÀÇ À̹ÌÁö)ÀÌ µÉ ¼ö ÀÖ´Ù. ¿ì¸®´Â ÀÌ¹Ì ÀÌ·± ÇÔ¼ö µÎ°¡Áö¸¦ º¸¾Ò´Ù. gdk_draw_rectangle()°ú gdk_draw_pixmap()ÀÌ ±×°ÍÀÌ´Ù. ÀÌ ÇÔ¼öµéÀÇ ¿ÏÀüÇÑ ¸®½ºÆ®´Â ÀÌ·¸´Ù.

gdk_draw_line ()
gdk_draw_rectangle ()
gdk_draw_arc ()
gdk_draw_polygon ()
gdk_draw_string ()
gdk_draw_text ()
gdk_draw_pixmap ()
gdk_draw_bitmap ()
gdk_draw_image ()
gdk_draw_points ()
gdk_draw_segments ()

ÀÌ ÇÔ¼öµé¿¡ ´ëÇØ ´õ ÀÚ¼¼È÷ ¾Ë·Á¸é Âü°í ¹®¼­¸¦ º¸°Å³ª <gdk/gdk.h> ÆÄÀÏÀ» º¸¶ó. ÀÌ ÇÔ¼öµéÀº óÀ½ µÎ °³ÀÇ ÀÎÀÚ¸¦ °øÅëÀûÀ¸·Î °¡Áø´Ù. ù ¹ø°´Â ±×·Á ³ÖÀ» drawable, ±×¸®°í µÎ¹ø°´Â graphics context(GC)ÀÌ´Ù.

C´Â foreground/background color³ª line width°°Àº, ±×·ÁÁú °Í¿¡ ´ëÇÑ Á¤º¸µéÀ» ĸ½¶È­ÇÑ °ÍÀÌ´Ù. GDK´Â GC¸¦ »õ·Î ¸¸µé°í º¯ÇüÇϴµ¥ ÇÊ¿äÇÑ ¸ðµç ÇÔ¼öµéÀ» °¡Áö°í ÀÖÁö¸¸, ¹¹µçÁö °£´ÜÈ÷ À¯ÁöÇϱâ À§Çؼ­(Keep things simple) ¿ì¸®´Â ÀÌ¹Ì Á¤ÀǵǾî ÀÖ´Â GC¸¸À» ¾µ °ÍÀÌ´Ù. °¢ widgetÀº ¿¬°üµÈ ½ºÅ¸ÀÏÀÌ ÀÖ´Ù(À̵éÀº rc ÆÄÀÏÀ» ÆíÁýÇÔÀ¸·Î½á º¯Çü°¡´ÉÇÏ´Ù. GTKÀÇ rc ÆÄÀÏ¿¡ ´ëÇÑ ºÎºÐÀ» ÂüÁ¶). ÀÌ°ÍÀº ´Ù¸¥ °Íµé »çÀÌ¿¡¼­ GCÀÇ °³¼ö¸¦ ÀúÀåÇÑ´Ù. ÀÌ·± GC¿¡ Á¢±ÙÇÏ´Â ¸î°¡Áö ¿¹¸¦ º¸ÀÌ°Ú´Ù.

widget->style->white_gc
widget->style->black_gc
widget->style->fg_gc[GTK_STATE_NORMAL]
widget->style->bg_gc[GTK_WIDGET_STATE(widget)]

Çʵå fg_gc, bg_gc, dark_gc, light_gc µîÀº ¾Æ·¡ °ªµéÀ» °¡Áú ¼ö ÀÖ´Â GtkStateTypeÀ̶ó´Â ÀÎÀÚ·Î ³ªÅ¸³»¾îÁø´Ù.

GTK_STATE_NORMAL,
GTK_STATE_ACTIVE,
GTK_STATE_PRELIGHT,
GTK_STATE_SELECTED,
GTK_STATE_INSENSITIVE

¿¹¸¦µé¾î, GTK_STATE_SELECTED¿¡ ´ëÇØ µðÆúÆ® foreground »ö±òÀº whiteÀÌ°í background »ö±òÀº dark blueÀÌ´Ù. ½ÇÁ¦·Î ½ºÅ©¸° À§·Î ±×¸®´Â ÇÔ¼öÀÎ draw_brush()´Â ±×·¯¹Ç·Î ÀÌ·¸°Ô µÈ´Ù.

/* ½ºÅ©¸°¿¡ »ç°¢ÇüÀ» Çϳª ±×¸°´Ù. */
static void
draw_brush (GtkWidget *widget, gdouble x, gdouble y)
{
    GdkRectangle update_rect;
    update_rect.x = x - 5;
    update_rect.y = y - 5;
    update_rect.width = 10;
    update_rect.height = 10;
    gdk_draw_rectangle (pixmap,
                        widget->style->black_gc,
                        TRUE,
                        update_rect.x, update_rect.y,
                        update_rect.width, update_rect.height);
    gtk_widget_draw (widget, &update_rect);
}

¿ì¸®°¡ ÇȽº¸Ê À§·Î ºê·¯½¬¸¦ Ç¥½ÃÇÏ´Â »ç°¢ÇüÀ» ±×¸®°í ³ª¼­, ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù.

void       gtk_widget_draw              (GtkWidget           *widget,
                                         GdkRectangle        *area);

ÀÌ°ÍÀº area¶ó´Â ÀÎÀÚ·Î ÁÖ¾îÁø ¿µ¿ªÀÌ ¾÷µ¥ÀÌÆ®µÇ¾î¾ß ÇÔÀ» X¿¡°Ô ¾Ë·ÁÁØ´Ù. °á±¹ X´Â expose À̺¥Æ®¸¦ ¹ß»ýÇÏ°í, ÀÌ°ÍÀº ¿ì¸®ÀÇ expose À̺¥Æ® Çڵ鷯°¡ °ü°èµÈ ¿µ¿ªÀ» ½ºÅ©¸° À§·Î º¹»çÇÏ°Ô²û ÇÒ °ÍÀÌ´Ù.

ÀÌÁ¦ ¿ì¸®´Â main À©µµ¸¦ ¸¸µå´Â °Í °°ÀÌ ÀϺΠÈçÇÑ Ç׸ñµéÀ» Á¦¿ÜÇÏ°í ÀÌ ±×¸®±â ÇÁ·Î±×·¥À» ¸ðµÎ »ìÆ캸¾Ò´Ù. ¿ÏÀüÇÑ ¼Ò½ºÄÚµå´Â ÀÌ ¹®¼­¸¦ ±¸ÇÑ °÷À̳ª ´ÙÀ½ À§Ä¡¿¡¼­ ±¸ÇÒ ¼ö ÀÖ´Ù.

http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

21.4 Input support¸¦ ´õÇϱâ

ÀÌÁ¦ drawing tablet °°ÀÌ, ±×´ÙÁö ºñ½ÎÁö ¾ÊÀ¸¸é¼­ ¸¶¿ì½ºº¸´Ù ÈξÀ ¿¹¼úÀûÀΠǥÇöÀ» ÆíÇÏ°Ô ±×¸± ¼ö ÀÖ°Ô ÇØÁÖ´Â ÀÔ·ÂÀåÄ¡(input device)¸¦ ±¸ÀÔÇÏ´Â °ÍÀÌ °¡´ÉÇÑ ½Ã´ë´Ù. ÀÌ·± ÀåÄ¡¸¦ ÀÌ¿ëÇÏ´Â °¡Àå °£´ÜÇÑ ¹æ¹ýÀÌ¾ß °£´ÜÈ÷ ¸¶¿ì½º¸¦ ´ëÄ¡ÇØ ¹ö¸®´Â °ÍÀÌ°ÚÁö¸¸, ÀÌ·² °æ¿ì ±×·± ÀÔ·ÂÀåÄ¡ÀÇ ´ÙÀ½°ú °°Àº ¸¹Àº ÀåÁ¡À» ÀÒ°Ô µÉ ¼öµµ ÀÖ´Ù.

  • Pressure sensitivity
  • Tilt reporting
  • Sub-pixel positioning
  • Multiple inputs (for example, a stylus with a point and eraser)

XInput extension¿¡ ´ëÇÑ Á¤º¸¸¦ ¾òÀ¸·Á¸é XInput-HOWTO ¸¦ º¸¶ó. ¿¹¸¦µé¾î GdkEventMotion ±¸Á¶Ã¼ÀÇ Àüü Á¤ÀÇ°°Àº °É ºÁµµ, extended device¸¦ Áö¿øÇϱâ À§ÇÑ Çʵ带 °¡Áö°í ÀÖÀ½À» ¾Ë °ÍÀÌ´Ù.

struct _GdkEventMotion
{
        GdkEventType type;
        GdkWindow *window;
        guint32 time;
        gdouble x;
        gdouble y;
        gdouble pressure;
        gdouble xtilt;
        gdouble ytilt;
        guint state;
        gint16 is_hint;
        GdkInputSource source;
        guint32 deviceid;
};

pressure ÀÎÀÚ´Â 0°ú 1 »çÀÌÀÇ ºÎµ¿¼Ò¼öÁ¡¼ö·Î µÈ pressure¸¦ ÁØ´Ù. xtilt¿Í ytile´Â °¢ ¹æÇâÀ¸·ÎÀÇ tilt °¢µµ¿¡ ÇØ´çÇÏ´Â -1ºÎÅÍ 1 »çÀÌÀÇ °ªÀ» °¡Áú ¼ö ÀÖ´Ù. source¿Í deviceid ÀÎÀÚ´Â µÎ°¡Áö ´Ù¸¥ ¹æ½ÄÀ¸·Î ¹ß»ýÇÑ À̺¥Æ®¿¡ ´ëÇØ ÀåÄ¡(device)¸¦ ¼³Á¤ÇÑ´Ù. source´Â ÀåÄ¡ÀÇ Å¸ÀÔ¿¡ ´ëÇÑ °£´ÜÇÑ Á¤º¸¸¦ ÁØ´Ù. ÀÌ°ÍÀº ´ÙÀ½ÀÇ enumeration °ªµéÀ» °¡Áú ¼ö ÀÖ´Ù.

GDK_SOURCE_MOUSE
GDK_SOURCE_PEN
GDK_SOURCE_ERASER
GDK_SOURCE_CURSOR

deviceid´Â °¢ ÀåÄ¡¿¡ ´ëÇØ °íÀ¯ÀÇ ¼ýÀÚ ID¸¦ ¼³Á¤ÇÑ´Ù. ÀÌ°ÍÀº gdk_input_list_devices() ÇÔ¼ö·Î(µÚ¿¡ ³ª¿È) ±× ÀåÄ¡¿¡ ´ëÇÑ ´õ ¸¹Àº Á¤º¸¸¦ Á¶»çÇÏ°íÀÚ ÇÒ ¶§ ¾²ÀÏ ¼ö ÀÖ´Ù. Core pointer device(º¸Åë ¸¶¿ì½º)¿¡ ´ëÇØ Æ¯º°È÷ GDK_CORE_POINTER¶ó´Â »ó¼ö°ªÀÌ ¾²ÀδÙ.

Extended device Á¤º¸¸¦ »ç¿ë°¡´ÉÇÏ°Ô Çϱâ

GTK¿¡°Ô ¿ì¸®°¡ °ü½ÉÀ» °¡Áø extended deviceÀÇ Á¤º¸°¡ ¹«¾ùÀÎÁö ¾Ë·Á ÁÖ·Á¸é, ¿ì¸® ÇÁ·Î±×·¥¿¡ ´Ü ÇÑ ÁÙ¸¸ ´õÇØÁÖ¸é µÈ´Ù.

gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);

GDK_EXTENSION_EVENTS_CURSOR¶ó´Â °ªÀ» ÁÜÀ¸·Î½á ¿ì¸®´Â È®ÀåµÈ À̺¥Æ®µé¿¡ °ü½ÉÀÌ ÀÖÀ½À» ¾Ë¸°´Ù. ´Ü, À̶§ ¿ì¸®´Â »õ·Î Ä¿¼­¸¦ ±×·Á¼­´Â ¾ÈµÈ´Ù. Ä¿¼­¸¦ ±×¸®´Â ¹®Á¦¿¡ ´ëÇؼ­´Â µÚ¿¡ ³ª¿Ã º¹ÀâÇÑ ÀÌ¿ë ºÎºÐÀ» ÂüÁ¶Ç϶ó. ¿ì¸®°¡ ¿ì¸®¸¸ÀÇ Ä¿¼­¸¦ ±×¸®·Á ÇÑ´Ù¸é GDK_EXTENSION_EVENTS_ALLÀ» ¾²¸é µÇ°í, µðÆúÆ® ·Î µ¹¾Æ°¡·Á¸é GDK_EXTENSION_EVENTS_NONEÀ» ¾´´Ù.

À̾߱â´Â ÀÌ°ÍÀ¸·Î ³¡³ªÁö ¾Ê´Â´Ù. µðÆúÆ®·Î, extension device´Â disable µÇ¾î ÀÖ´Ù. ¿ì¸®´Â »ç¿ëÀÚ·Î ÇÏ¿©±Ý ±×µéÀÇ extension deviceµéÀ» enable½ÃÅ°°í ¼³Á¤ÇÒ ¼ö ÀÖ°Ô ÇØÁÖ´Â ¸ÅÄ¿´ÏÁòÀÌ ÇÊ¿äÇÏ´Ù. GTK´Â ÀÌ °úÁ¤À» ÀÚµ¿ÀûÀ¸·Î ÇØ ÁÖ´Â InputDialog widgetÀ» Á¦°øÇÑ´Ù. ´ÙÀ½°ú °°Àº °úÁ¤´ë·Î InputDialog widgetÀ» °ü¸®ÇÑ´Ù. ÀÌ°ÍÀº device°¡ Á¸ÀçÇÏÁö ¾ÊÀ¸¸é dialog·Î ¾Ë·ÁÁÖ°í, ³ª¸ÓÁö °æ¿ì¿£ topÀ¸·Î ¿Ã·Áº¸³½´Ù.

void
input_dialog_destroy (GtkWidget *w, gpointer data)
{
    *((GtkWidget **)data) = NULL;
}

void
create_input_dialog ()
{
    static GtkWidget *inputd = NULL;
    if (!inputd)
        {
            inputd = gtk_input_dialog_new();
            gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
                               (GtkSignalFunc)input_dialog_destroy, &inputd);
            gtk_signal_connect_object 
            (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
                     "clicked",
                     (GtkSignalFunc)gtk_widget_hide,
                     GTK_OBJECT(inputd));
            gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
            gtk_widget_show (inputd);
        }
    else
        {
            if (!GTK_WIDGET_MAPPED(inputd))
                gtk_widget_show(inputd);
            else
                gdk_window_raise(inputd->window);
        }
}
(¿ì¸®°¡ ÀÌ dialog¸¦ ´Ù·ç´Â ¹æ¹ý¿¡ ÁÖÀǸ¦ ±â¿ï¿©¾ß ÇÒ °ÍÀÌ´Ù. "destroy" ½Ã±×³Î¿¡ ¿¬°á½ÃÄÑ µÎ´Â °ÍÀ¸·Î, ¿ì¸®´Â dialog°¡ Æı«µÈ ÀÌÈÄ Æ÷ÀÎÅ͸¦ dialog ¿¡ ³²°ÜµÎ´Â ½Ç¼ö - ÀÌ°ÍÀº Segfault(!)¸¦ ºÎ¸¥´Ù - ¸¦ ÇÇÇÒ ¼ö ÀÖ´Ù.)

InputDialog´Â "Close" ±×¸®°í "Save"¶ó´Â µÎ ¹öÆ°À» °¡Áö°í ÀÖÀ¸¸ç, µðÆúÆ® ·Î´Â ¾Æ¹«·± µ¿ÀÛÀÌ ¿¬°áµÇ¾î ÀÖÁö ¾Ê´Ù. À§¿¡¼­´Â "Close" ¹öÆ°À» dialog¸¦ °¨Ãߴµ¥ ½è°í, "Save" ¹öÆ°Àº °¨Ãß¾î ¹ö·È´Ù. ÀÌ ÇÁ·Î±×·¥¿¡¼­ XInputÀ» ÀúÀå ÇÏ´Â ¿É¼ÇÀ» °®ÃßÁö ¾Ê¾Ò±â ¶§¹®ÀÌ´Ù.

Extended device Á¤º¸¸¦ ÀÌ¿ëÇϱâ

ÀÏ´Ü ÀåÄ¡(device)¸¦ enable½ÃÄ×À¸¸é, ¿ì¸®´Â À̺¥Æ® ±¸Á¶Ã¼ÀÇ ³ª¸ÓÁö Çʵ忡 ÀÖ´Â extended deviceÀÇ Á¤º¸¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. »ç½Ç, ÀÌ Á¤º¸¸¦ ÀÌ¿ëÇÏ´Â °Ç ¾ðÁ¦³ª ¾ÈÀüÇÏ´Ù. Extended event°¡ disableµÇ¾î ÀÖ´õ¶óµµ À̵éÀº ÀûÀýÇÑ µðÆúÆ®°ªÀ» °¡Áö°í Àֱ⠶§¹®ÀÌ´Ù.

ÇÑ °¡Áö ÁÖÀÇÇÒ °ÍÀº gdk_window_get_pointer() ´ë½Å¿¡ gdk_input_window_get_pointer()¸¦ È£ÃâÇÑ´Ù´Â °ÍÀÌ´Ù. ÀÌ°ÍÀº gdk_window_get_pointer°¡ extended device Á¤º¸¸¦ ¸®ÅÏÇÏÁö ¸øÇϱ⠶§¹®ÀÌ´Ù.

void gdk_input_window_get_pointer     (GdkWindow       *window,
                                     guint32         deviceid,
                                     gdouble         *x,
                                     gdouble         *y,
                                     gdouble         *pressure,
                                     gdouble         *xtilt,
                                     gdouble         *ytilt,
                                     GdkModifierType *mask);

ÀÌ ÇÔ¼ö¸¦ ºÎ¸¦ ¶§, À©µµÀÇ °æ¿ì¿Í ¸¶Âù°¡Áö·Î deviceÀÇ ID¸¦ ¸í½ÃÇØ Áà¾ß ÇÑ´Ù. º¸Åë, ¿ì¸®´Â device ID¸¦ event ±¸Á¶Ã¼ÀÇ deviceid Çʵå·ÎºÎÅÍ ÃëÇÒ °ÍÀÌ´Ù. ´Ù½Ã Çѹø, ÀÌ ÇÔ¼ö´Â extension event°¡ disableµÈ »óÅ¿¡¼­µµ ÇÕ´çÇÑ °ªÀ» ¸®ÅÏÇÔÀ» ±â¾ïÇÏÀÚ. (ÀÌ °æ¿ì¿£, event->deviceid´Â GDK_CORE_POINTER¶ó´Â °ªÀ» °¡Áú °ÍÀÌ´Ù.)

±×·¡¼­ ¿ì¸®ÀÇ button-press ¿Í motion À̺¥Æ® Çڵ鷯ÀÇ ±âº»ÀûÀÎ ±¸Á¶´Â ±×¸® º¯ÇÏÁö ¾Ê´Â´Ù - ¿ì¸° ´ÜÁö extended¿¡ ÇØ´çÇÏ´Â Á¤º¸¸¦ ´Ù·ê Äڵ带 Ãß°¡Çϱ⸸ ÇÏ¸é µÈ´Ù.

static gint
button_press_event (GtkWidget *widget, GdkEventButton *event)
{
    print_button_press (event->deviceid);
    if (event->button == 1 && pixmap != NULL)
        draw_brush (widget, event->source, event->x, event->y, event->pressure);
    return TRUE;
}

static gint
motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
{
    gdouble x, y;
    gdouble pressure;
    GdkModifierType state;
    if (event->is_hint)
        gdk_input_window_get_pointer (event->window, event->deviceid,
                            &x, &y, &pressure, NULL, NULL, &state);
    else
        {
            x = event->x;
            y = event->y;
            pressure = event->pressure;
            state = event->state;
        }
    if (state & GDK_BUTTON1_MASK && pixmap != NULL)
        draw_brush (widget, event->source, x, y, pressure);
    return TRUE;
}

¿ì¸° ¶ÇÇÑ »õ·Î¿î Á¤º¸¸¦ ÀÌ¿ëÇÏ´Â ÀÏÀ» ¹º°¡ ÇØ¾ß ÇÑ´Ù. ¿ì¸®ÀÇ draw_brush() ÇÔ¼ö´Â °¢ event->source¸¶´Ù ´Ù¸¥ »ö±ò·Î ±×¸± ¼ö ÀÖ°Ô ÇÏ°í, ±×¸®°í pressure¿¡ µû¶ó brushÀÇ Å©±â¸¦ º¯ÇÏ°Ô ÇÑ´Ù.

/* ½ºÅ©¸°¿¡ »ç°¢ÇüÀ» ±×¸°´Ù.  Å©±â´Â pressure¿¡ ÀÇÁ¸ÇÏ°í,
 * ±×¸®°í »ö±òÀº deviceÀÇ Å¸ÀÔ¿¡ ÀÇÁ¸ÇÑ´Ù. */
static void
draw_brush (GtkWidget *widget, GdkInputSource source,
            gdouble x, gdouble y, gdouble pressure)
{
    GdkGC *gc;
    GdkRectangle update_rect;
    switch (source)
        {
        case GDK_SOURCE_MOUSE:
            gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
            break;
        case GDK_SOURCE_PEN:
            gc = widget->style->black_gc;
            break;
        case GDK_SOURCE_ERASER:
            gc = widget->style->white_gc;
            break;
        default:
            gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
        }
    update_rect.x = x - 10 * pressure;
    update_rect.y = y - 10 * pressure;
    update_rect.width = 20 * pressure;
    update_rect.height = 20 * pressure;
    gdk_draw_rectangle (pixmap, gc, TRUE,
                        update_rect.x, update_rect.y,
                        update_rect.width, update_rect.height);
    gtk_widget_draw (widget, &update_rect);
}

Device¿¡ ´ëÇØ ´õ ¸¹Àº °É ¾Ë¾Æ³»±â

Device¿¡ ´ëÇÑ Á¤º¸¸¦ ¾î¶»°Ô ´õ ¾Ë¾Æ³»´ÂÁö º¸¿©ÁÖ´Â ¿¹Á¦·Î¼­, ¿ì¸® ÇÁ·Î ±×·¥Àº °¢ ¹öÆ°À» ´©¸£¸é deviceÀÇ À̸§À» ÇÁ¸°Æ®ÇÒ °ÍÀÌ´Ù. DeviceÀÇ À̸§À» ¾Ë¾Æ³»±â À§ÇÏ¿© ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

GList *gdk_input_list_devices               (void);

ÀÌ°ÍÀº GdkDeviceInfo ±¸Á¶Ã¼ÀÇ GList(glib ¶óÀ̺귯¸®¿¡¼­ ¿Â ¿¬°á¸®½ºÆ® ŸÀÔ)¸¦ ¸®ÅÏÇÑ´Ù. GdkDeviceInfo ±¸Á¶Ã¼´Â ÀÌ·¸°Ô Á¤ÀǵǾî ÀÖ´Ù.

struct _GdkDeviceInfo
{
        guint32 deviceid;
        gchar *name;
        GdkInputSource source;
        GdkInputMode mode;
        gint has_cursor;
        gint num_axes;
        GdkAxisUse *axes;
        gint num_keys;
        GdkDeviceKey *keys;
};

¿©±âÀÖ´Â ´ëºÎºÐÀÇ Çʵå´Â ¿©·¯ºÐÀÌ XInput ¼³Á¤À» ÀúÀåÇÏ´Â ±â´ÉÀ» Ãß°¡ÇÏÁö ¾Ê¾Ò´Ù¸é ¹«½ÃÇصµ ±¦ÂúÀº ¼³Á¤ Á¤º¸µéÀÌ´Ù. Áö±Ý ¿ì¸®°¡ °ü½ÉÀ» °¡Áø °ÍÀº ´Ü¼øÈ÷ X°¡ device¿¡ ºÎ¿©ÇÑ À̸§(name)ÀÌ´Ù. ¼³Á¤(configuration)Çʵ忡 ÇØ´çÇÏÁö ¾Ê´Â °ÍÀº has_cursorÀÌ´Ù. ±×·±µ¥ ¿ì¸®´Â GDK_EXTENSION_EVENTS_CURSOR¸¦ ¼³Á¤ÇßÀ¸¹Ç·Î, ÀÌ Çʵ忡 ´ëÇؼ­´Â °ÆÁ¤ÇÏÁö ¸»ÀÚ.

print_button_press() ÇÔ¼ö´Â ¸ÅÄ¡µÇ´Â ¸®½ºÆ®¸¦ ¸®ÅÏÇÒ ¶§±îÁö ´Ü¼øÈ÷ ¹Ýº¹µÉ °ÍÀ̸ç, deviceÀÇ À̸§À» ÇÁ¸°Æ®ÇØ ÁÙ °ÍÀÌ´Ù.

static void
print_button_press (guint32 deviceid)
{
        GList *tmp_list;
        /* gdk_input_list_devices´Â ³»ºÎÀûÀÎ ¸®½ºÆ®¸¦ ¸®ÅÏÇϸç,
         * µû¶ó¼­ ¿ì¸®´Â ÈÄ¿¡ ÀÌ°ÍÀ» ÇØÁ¦ÇØ ÁÖÁö ¾ÊÀ» °ÍÀÌ´Ù. */
        tmp_list = gdk_input_list_devices();
        while (tmp_list)
                {
                        GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
                        if (info->deviceid == deviceid)
                                {
                                        printf("Button press on device '%s'\n", info->name);
                                        return;
                                }
                        tmp_list = tmp_list->next;
                }
}

ÀÌ°ÍÀ¸·Î ¿ì¸®ÀÇ ``XInputize'' ÇÁ·Î±×·¥À» ¿ÏÀüÈ÷ º¯°æÇß´Ù. ù ¹öÁ¯°ú ¸¶Âù°¡Áö·Î ÀÌ°ÍÀÇ ¿ÏÀüÇÑ ¼Ò½º ÄÚµå´Â ÀÌ ¹®¼­¸¦ ±¸ÇÑ °÷À̳ª ´ÙÀ½ À§Ä¡¿¡¼­ ±¸ÇÒ ¼ö ÀÖ´Ù.

http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

´õ º¹ÀâÇÑ ÀÌ¿ë

ºñ·Ï ¿ì¸® ÇÁ·Î±×·¥ÀÌ ÀÌÁ¦ XInputÀ» ²Ï Àß Áö¿øÇÔ¿¡µµ ºÒ±¸ÇÏ°í, ¾îÇà ÀüüÀû À¸·Î ºÁ¼­ ¹º°¡ ºÎÁ·ÇØ º¸ÀÌ´Â ¸éµµ ÀÖ´Ù. ¸ÕÀú, »ç¿ëÀÚ´Â ÇÁ·Î±×·¥À» ½ÇÇàÇÒ ¶§¸¶´Ù ±×µéÀÇ ÀåÄ¡µéÀ» ¼³Á¤ÇÏ·Á°í ÇÏÁø ¾ÊÀ» °ÍÀ̹ǷÎ, ¿ì¸®´Â ±× ÀåÄ¡µéÀÇ ¼³Á¤À» ÀúÀåÇÒ ¼ö ÀÖµµ·Ï ÇØÁà¾ß ÇÑ´Ù. ÀÌ°ÍÀº gdk_input_list_devices()ÀÇ ¸®ÅÏÀ» µÇÇ®ÀÌÇÏ°í, ¼³Á¤À» ÆÄÀÏ¿¡ ±â·Ï(write)ÇÏ´Â °ÍÀ¸·Î ÀÌ·ç¾îÁø´Ù.

ÇÁ·Î±×·¥ÀÌ ´ÙÀ½ ¹ø ½ÇÇàµÉ ¶§ ÇöÀçÀÇ state¸¦ º¹±¸ÇØ ÁÖ±â À§Çؼ­, GDK´Â device ¼³Á¤¿¡ ´ëÇÑ ´ÙÀ½ ÇÔ¼öµéÀ» Á¦°øÇÑ´Ù.

gdk_input_set_extension_events()
gdk_input_set_source()
gdk_input_set_mode()
gdk_input_set_axes()
gdk_input_set_key()

(gdk_input_list_devices()°¡ ¸®ÅÏÇÑ ¸®½ºÆ®´Â Á¤È®È÷ º¯°æµÇÁö ¾ÊÀ» ¼ö ÀÖ´Ù.) ÀÌ°Í¿¡ ´ëÇÑ ¿¹Á¦´Â ±×¸®±â ÇÁ·Î±×·¥ÀÎ Gsumi( http://www.msc.cornell.edu/~otaylor/gsumi/¿¡ ÀÖ´Ù.)°¡ µÉ °ÍÀÌ´Ù. °á±¹, ¸ðµç ¾îÇõ鿡 ´ëÇØ ÀÌ ¸ñÀûÀ¸·Î Ç¥ÁØÀûÀÎ ¹æ½ÄÀ» °¡Áú ¼ö ÀÖ´Ù¸é ¸ÚÁø ÀÏÀÌ µÉ °ÍÀÌ´Ù. ÀÌ°ÍÀº ¾Æ¸¶ GNOME ¶óÀ̺귯¸®°¡ GTKº¸´Ù ¾à°£ ³ôÀº ·¹º§¿¡ ¼ÓÇÒ °ÍÀÌ´Ù.

¿ì¸®°¡ ¾Õ¿¡¼­ ´Ù·é °Í¿¡¼­ ºüÁø ¶ÇÇϳª Áß¿äÇÑ °ÍÀº cursor¿¡ ´ëÇÑ °ÍÀÌ´Ù. XFree86°ú ´Ù¸¥ Ç÷§ÆûµéÀº ÇöÀç·Î¼­´Â µ¿½Ã¿¡ µÑÀ» - Core pointer, ±×¸®°í ¾îÇÿ¡ ÀÇÇÑ Á÷Á¢ÀûÀÎ Á¶ÀÛ - »ç¿ëÇÏ¿© ÀåÄ¡¸¦ ´Ù·ê ¼ö ¾ø´Ù. ÀÌ°Í¿¡ ´ëÇØ ´õ ÀÚ¼¼ÇÑ Á¤º¸´Â XInput-HOWTO¸¦ º¸¶ó. ÀÌ°ÍÀº ÃÖ´ëÇÑÀÇ ÀÌ¿ëÀÚ¸¦ È®º¸ÇÏ·Á´Â ¾îÇÃÀ̶ó¸é ÀڽŸ¸ÀÇ Ä¿¼­¸¦ ±×·ÁÁÖ´Â °Ô ÇÊ¿äÇÔÀ» ÀǹÌÇÑ´Ù.

ÀڽŸ¸ÀÇ Ä¿¼­¸¦ ±×¸®´Â ¾îÇÃÀº ´ÙÀ½ÀÇ µÎ ÀÏÀ» ÇØ¾ß ÇÑ´Ù. ù°·Î ÇöÀçÀÇ ÀåÄ¡°¡ ±×·ÁÁø Ä¿¼­¸¦ ÇÊ¿ä·Î ÇÏ´ÂÁöÀÇ ¿©ºÎ¸¦ °áÁ¤ÇÏ°í, µÑ°·Î ÇöÀçÀÇ ÀåÄ¡°¡ Á¢±Ù(proximity)µÇ¾î ÀÖ´ÂÁöÀÇ ¿©ºÎ¸¦ °áÁ¤ÇÑ´Ù. (ÇöÀçÀÇ ÀåÄ¡°¡ drawing tabletÀÏ °æ¿ì, stylus°¡ tablet¿¡¼­ ¶³¾îÁ³À» ¶§ Ä¿¼­°¡ º¸ÀÌÁö ¾Ê°Ô ÇÏ´Â °ÍÀÌ ÁÁÀ» °ÍÀÌ´Ù. ÀåÄ¡°¡ stylus¿Í ºÙ¾î ÀÖÀ» ¶§, À̸¦ Á¢±ÙµÇ¾ú´Ù(in proximity)°í Ç¥ÇöÇÑ´Ù.) ù¹ø° ÀÛ¾÷Àº ¿ì¸®°¡ deviceÀÇ À̸§À» ¾Ë¾Æ³»±â À§ÇØ ÇßµíÀÌ, deviceÀÇ ¸®½ºÆ®¸¦ Á¶»ç ÇÔÀ¸·Î½á ÇØ°áµÈ´Ù. µÎ¹ø° ÀÛ¾÷Àº "proximity_out" À̺¥Æ®¸¦ ¼³Á¤ÇÔÀ¸·Î½á ÇØ°áÇÑ´Ù. °¢ÀÚÀÇ Ä¿¼­¸¦ ±×¸®´Â ¿¹Á¦´Â GTK ¹èÆ÷ÆÇ¿¡ ÀÖ´Â 'testinput' ÇÁ·Î ±×·¥¿¡¼­ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.

22. GTK ¾îÇÃÀ» °³¹ßÇÏ´Â ÆÁ

ÀÌ ºÎºÐÀº ´ÜÁö ÁÁÀº GTK ¾îÇÃÀ» °³¹ßÇÒ ¼ö ÀÖµµ·Ï ÀϹÝÀûÀÎ ½ºÅ¸ÀÏÀÇ Á¶¾ð°ú ÈùÆ® µîÀ» ´Ù·ç°í ÀÖ´Ù. ÀÌ°ÍÀº Áö±ÝÀ¸·Î¼± Á¦¸ñ¸¸ ±×·¸´Ù´Â °ÍÀÌ°í, µû¶ó¼­ ÀüÇô ÇÊ¿ä¾øÀ» °ÍÀÌ´Ù. :)

GNU autoconf¿Í automake¸¦ ÀÌ¿ëÇ϶ó! ±×µéÀº ¿ì¸® Ä£±¸´Ù. :) ³ª´Â À̵鿡 ´ëÇÑ °£´ÜÇÑ ¼Ò°³¸¦ ÇØÁÙ °èȹÀÌ ÀÖ´Ù.

23. Contributing

ÀÌ ¹®¼­´Â, ´Ù¸¥ ¼ö¸¹Àº ¼ÒÇÁÆ®¿þ¾îµé°ú ¸¶Âù°¡Áö·Î, ÀÚÀ¯·Î¿î ÀÌ¿ëÀ» À§Çؼ­ ÀÚ¹ßÀûÀ¸·Î ¸¸µé¾îÁø °ÍÀÌ´Ù. ¸¸¾à ¿©·¯ºÐÀÌ ¾ÆÁ÷ ¹®¼­È­µÇÁö ¾ÊÀº GTKÀÇ ¾î¶² ±â´É¿¡ ´ëÇØ È®½ÇÈ÷ Áö½ÄÀ» °¡Áö°Ô µÈ´Ù¸é, ¿©·¯ºÐ Àڽŵµ ÀÌ ¹®¼­¿¡ ±â¿©ÇØ º¼ °ÍÀ» °í·ÁÇØ º¸ÀÚ.

¸¸¾à ±â¿©ÇÏ°Ú´Ù°í ¸¶À½¸Ô¾ú´Ù¸é, ¿©·¯ºÐÀÇ ±ÛÀ» Tony Gale gale@gtk.org¿¡°Ô º¸³»Áֱ⠹ٶõ´Ù. ¶ÇÇÑ, ÀÌ ¹®¼­´Â ¿ÏÀüÈ÷ ÀÚÀ¯·Î¿î °ÍÀÌ¸ç ¿©·¯ºÐ¿¡ ÀÇÇÑ ¾î¶² Ãß°¡»çÇ× ¿ª½Ã ÀÚÀ¯´Ù. Áï »ç¶÷µéÀº ±×µéÀÇ ÇÁ·Î±×·¥À» À§ÇØ ¿©·¯ºÐÀÇ ±ÛÀÇ ¾î¶² ºÎºÐÀÌ¶óµµ ÀÌ¿ëÇÒ °ÍÀÌ°í, ¶Ç ¹®¼­ÀÇ º¹Á¦Ç°Àº ¿øÇÏ´Â ´ë·Î ¹èÆ÷µÉ °ÍÀÌ´Ù.

Thank you.

24. Credits

ÀÌ ¹®¼­¿¡ °øÇåÇÑ ´ÙÀ½ »ç¶÷µé¿¡°Ô °¨»çÇÑ´Ù.

  • Bawer Dagdeviren, chamele0n@geocities.com for the menus tutorial.
  • Raph Levien, raph@acm.org for hello world ala GTK, widget packing, and general all around wisdom. He's also generously donated a home for this tutorial.
  • Peter Mattis, petm@xcf.berkeley.edu for the simplest GTK program.. and the ability to make it :)
  • Werner Koch werner.koch@guug.de for converting the original plain text to SGML, and the widget class hierarchy.
  • Mark Crichton crichton@expert.cc.purdue.edu for the menu factory code, and the table packing tutorial.
  • Owen Taylor owt1@cornell.edu for the EventBox widget section (and the patch to the distro). He's also responsible for the selections code and tutorial, as well as the sections on writing your own GTK widgets, and the example application. Thanks a lot Owen for all you help!
  • Mark VanderBoom mvboom42@calvin.edu for his wonderful work on the Notebook, Progress Bar, Dialogs, and File selection widgets. Thanks a lot Mark! You've been a great help.
  • Tim Janik timj@psynet.net for his great job on the Lists Widget. Thanks Tim :)
  • Rajat Datta rajat@ix.netcom.com for the excellent job on the Pixmap tutorial.
  • Michael K. Johnson johnsonm@redhat.com for info and code for popup menus.

±×¸®°í µµ¿òÀ» ÁÖ°í ´õ ¼¼·ÃµÈ ¹®¼­°¡ µÇµµ·Ï ÇØÁØ ¸ðµç À̵鿡°Ôµµ °¨»çÇÑ´Ù.

Thanks.

25. Tutorial Copyright and Permissions Notice

The GTK Tutorial is Copyright (C) 1997 Ian Main.

Copyright (C) 1998 Tony Gale.

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this document under the conditions for verbatim copying, provided that this copyright notice is included exactly as in the original, and that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this document into another language, under the above conditions for modified versions.

If you are intending to incorporate this document into a published work, please contact the maintainer, and we will make an effort to ensure that you have the most up to date information available.

There is no guarentee that this document lives up to its intended purpose. This is simply provided as a free resource. As such, the authors and maintainers of the information provided within can not make any guarentee that the information is even accurate.


ID
Password
Join
He is truly wise who gains wisdom from another's mishap.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2011-03-10 22:19:35
Processing time 0.0042 sec