´ÙÀ½ ÀÌÀü Â÷·Ê

11. ¸Þ´º widget

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

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

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

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

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

¸Þ´º ¾ÆÀÌÅÛ 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);

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

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

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 *~

Áö±Ý ´çÀåÀº ÀÌ ¿¹Á¦»ÓÀÌ´Ù. ÀÚ¼¼ÇÑ ¼³¸í°ú ÄÚ¸àÆ®µéÀº ³ªÁß¿¡ Ãß°¡µÉ °ÍÀÌ´Ù.


´ÙÀ½ ÀÌÀü Â÷·Ê