普段はxmlを手で打っているのでgladeを使わないのですが、暇なので試してみました。
とりあえず、まずはCで。
カスタムウィジェットのソース
#include <gtk/gtk.h>
#include <cairo.h>
#define HOGE_TYPE_DRAWABLE hoge_drawable_get_type()
G_DECLARE_FINAL_TYPE(HogeDrawable, hoge_drawable, HOGE, DRAWABLE, GtkDrawingArea)
HogeDrawable * hoge_drawable_new();
/* ---------------------------------------------------------------------- */
struct _HogeDrawable {
GtkDrawingArea parent;
};
struct _HogeDrawableClass {
GtkDrawingArea parent_class;
};
HogeDrawable * hoge_drawable_new()
{
return HOGE_DRAWABLE(g_object_new(HOGE_TYPE_DRAWABLE, NULL));
}
static void hoge_drawable_init(HogeDrawable *self)
{
g_print("%s(%d): trace.\n", __FILE__, __LINE__);
}
static gboolean hoge_drawable_draw(GtkWidget *widget, cairo_t *cr)
{
int width, height;
width = gtk_widget_get_allocated_width(widget);
height = gtk_widget_get_allocated_height(widget);
cairo_set_source_rgb(cr, 0, 1, 0);
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
return FALSE;
}
static void hoge_drawable_class_init(HogeDrawableClass *klass)
{
GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass);
g_print("%s(%d): trace.\n", __FILE__, __LINE__);
widget_klass->draw = hoge_drawable_draw;
}
G_DEFINE_TYPE(HogeDrawable, hoge_drawable, GTK_TYPE_DRAWING_AREA)
/* ---------------------------------------------------------------------- */
void hoge_glade_init()
{
g_print("%s(%d): trace.\n", __FILE__, __LINE__);
hoge_drawable_get_type();
}
/* ---------------------------------------------------------------------- */
#if 0
/* 一応、ソースコード単体で動くかどうかテストしておく。 */
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *drawable;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
drawable = hoge_drawable_new();
gtk_container_add(GTK_CONTAINER(window), drawable);
gtk_widget_show(drawable);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show(window);
gtk_main();
return 0;
}
#endif
モジュール
基本的に、カスタムウィジェットのコードは ダイナミックリンクライブラリ(soファイル)にしてgladeから読み込めるようにしなければなりません。(gladeでは、これを「モジュール」と呼んでいるよう)
また、gladeの初期化時に、カスタムウィジェットのタイプの登録をするために、g_type_register_static
などの関数を呼ぶ必要があります。
C言語の場合、上記のソースコードのようにGTK+のマクロを使っていれば、<なんちゃら>_get_type
を呼べばOKです。
というわけで、上記のソースコードを元に、ダイナミックリンクライブラリを作ります。
gcc -shared -fPIC -o libhoge.so hoge_drawable.c `pkg-config --cflags gtk+-3.0`
作ったライブラリは、
-
pkg-config --variable=moduledir gladeui-2.0
を実行して出力されるディレクトリ
-
GLADE_MODULE_SEARCH_PATH
環境変数で設定されたディレクトリ
- (おそらく)システムで普通に読めるディレクトリ(
/usr/lib
とか)
のいずれかに置きます。
カタログ
カタログファイルは、以下のとおりです。
<?xml version="1.0" encoding="utf-8"?>
<glade-catalog name="hoge_drawable"
library="libhoge.so"
depends="gtk+"
>
<init-function>hoge_glade_init</init-function>
<glade-widget-classes>
<glade-widget-class
name="HogeDrawable"
generic-name="drawable1"
title="Hoge Drawable"
/>
</glade-widget-classes>
<glade-widget-group name="hoge"
title="Hoge"
>
<glade-widget-class-ref name="HogeDrawable" />
</glade-widget-group>
</glade-catalog>
「init-function
」に、先ほど説明したモジュール内の初期化関数を指定します。
「library
」に、先ほど作成したダイナミックリンクライブラリの名前を指定します。(これも、ぐぐると色々とあるようだけど、とりあえずフルのファイル名を指定しました。)
このカタログファイルを、
-
pkg-config --variable=catalogdir gladeui-2.0
を実行して出力されるディレクトリ
-
GLADE_CATALOG_SEARCH_PATH
環境変数で設定されたディレクトリ
- gladeの設定で指定したディレクトリ
のいずれかに置きます。
これで、gladeでカスタムウィジェットが選べるようになりました。
C++の場合
(おそらく、gtkmmのことだと思うけど)自分はgtkmmは使ったことがないのでコメントできませんが、少なくともその下で動いているのはCのGTK+なので、gtkmmがどのようにg_type_register_static
などの関数を呼び出しているか調べてみると道が見えるかもしれません。
あと、既に見つけているかもしれませんが、以下のStackoverflowの質問もありました。
https://stackoverflow.com/questions/10826435/how-do-i-add-a-custom-gtkmm-widget-to-glade
お呼びじゃないけど、Pythonの場合
まぁ、自分が主に使うのはPythonなのでw
参考にされているサイトの内容が古いので当てにならないかな、と思いましたが、そのままやってみたらあっさりと動きました。
カスタムウィジェットのソースコード。
# coding: utf-8
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
class PiyoDrawable(Gtk.DrawingArea):
__gtype_name__ = 'PiyoDrawable'
def __init__(self, **kwargs):
super().__init__(**kwargs)
def do_draw(self, cr):
width = self.get_allocated_width()
height = self.get_allocated_height()
cr.set_source_rgb(0, 0, 1)
cr.rectangle(0, 0, width, height)
cr.fill()
を、モジュールパスに置き、PYTYHONPATH
環境変数もその場所を指定しておく。
で、カタログファイルを
<?xml version="1.0" encoding="utf-8"?>
<glade-catalog
name="piyo"
library="gladepython"
depends="gtk+"
>
<init-function>glade_python_init</init-function>
<glade-widget-classes
>
<glade-widget-class
title="Piyo Drawable"
name="PiyoDrawable"
generic-name="piyo_drawable"
/>
</glade-widget-classes>
<glade-widget-group
name="python"
title="Python"
>
<glade-widget-class-ref name="PiyoDrawable" />
</glade-widget-group>
</glade-catalog>
というように書いてカタログパスに置けばOKでした。