Gtk3でコンボボックス(ドロップダウン) Widgetを作る

Gtk3で、ComboBox(DropDown)を作るサンプルコードです。

これまでGtk3では公式ドキュメントを反面教師として、単体動作するコードをサンプルとして提示してきたつもりなのですが、今回は諦めました。すいません。なんというか、実用を目指すプロジェクトからコードを一部だけ、動く状態に抜き出すって無理ですね。



====
        // self->combo_linejoin = gtk_combo_box_new();
    //    GtkListStore *liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
        GtkListStore *liststore = gtk_list_store_new(1, G_TYPE_STRING);
        int num = get_num_stroke_linejoin_infos();
        for(int i = 0; i < num; i++){
            const PvStrokeLinejoinInfo *info = get_stroke_linejoin_info_from_id(i);
            gtk_list_store_insert_with_values(liststore, NULL, -1,
                            0, info->name,
    //                        1, info->linejoin,
                            -1);
        }
        self->combo_linejoin = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
        g_object_unref(liststore);
        GtkCellRenderer *column = gtk_cell_renderer_text_new();
        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(self->combo_linejoin), column, TRUE);
        gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(self->combo_linejoin), column,
                    "text", 0, NULL);
        gtk_combo_box_set_active(GTK_COMBO_BOX(self->combo_linejoin), 0);
        gtk_box_pack_start(GTK_BOX(self->box_linejoin), self->combo_linejoin, false, true, 3);
    }


====

ついでに使っている独自型などは以下。

====
 /*! @brief StrokeLinejoin */
typedef enum{
    PvStrokeLinejoin_Miter,
    PvStrokeLinejoin_Round,
    PvStrokeLinejoin_Bevel,
}PvStrokeLinejoin;

typedef struct{
    PvStrokeLinejoin linejoin;
    const char *name;
    int cairo_value;
}PvStrokeLinejoinInfo;

int get_num_stroke_linejoin_infos();
const PvStrokeLinejoinInfo *get_stroke_linejoin_info_from_id(PvStrokeLinejoin linejoin);


====

ドロップダウンリストの内容をGtkListStoreで作ります。それをGTK_TREE_MODEL形式でcombo_box_new_*()関数に流しこめば完了です。
一番重要なのはGtkListStoreがGtkTreeModelに変換できること、そしてそれがComboBoxに流し込めることです。

Python版コードなどを見てみると、GTK_TREE_MODELのところはタプルとか作ってそのまま流し込んでいて、確かに動的言語なら辞書配列が簡単に作れるし、それがコンボボックスの材料になるのも納得ですが、C言語だとこのなんだかしっくり来ない謎型変換をするコードになっています。

参考にしたのはこちら。
http://stackoverflow.com/questions/16630528/trying-to-populate-a-gtkcombobox-with-model-in-c
参考コードのほうが綺麗で完結していて読みやすいですね。
参考コードはコンボボックスの選択肢に色を付けるという愉快なサンプルコードになっていますが、これもしかしてここからオブジェクト取り出して選択した要素を一意に特定してコールバック処理の際に処理を分岐するとかの用途を想定しているんじゃないかな、私はコールバックの中でアクティブな選択肢の昇順を取ってきて、キャストなどもせず乱暴に元データのIndexに置き換えています。いずれはgpointer *data に選択肢のポインタそのまま投げ込んで判定するつもりだけれど、といった感じです。

====
g_signal_connect(self->combo_linecap, "changed",
            G_CALLBACK(_cb_changed_linecap_with_combo), NULL);


static void _cb_changed_linecap_with_combo(GtkComboBox *widget, gpointer user_data)
{
    EtStrokePanel *self = stroke_panel;
    assert(self);

    self->stroke.linecap = gtk_combo_box_get_active(GTK_COMBO_BOX(self->combo_linecap));

    _update_focus_elements_from_local();
}

====

以上です。

TIGORA(ティゴラ)のトレッキング シューズ

 TIGORA(ティゴラ)の トレッキング シューズを買いました。 メインの靴がアシックスウォーキングで街歩き用なのですが、これまではこれで高尾山などの軽い山も登っていました。 今回、靴底があまりに摩耗したこともあってアシックスウォーキングを買い替えたのですが、ついでに消耗が激...