00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef GTK_SOURCE_H_
00028 #define GTK_SOURCE_H_
00029
00030 #include <vector>
00031 #include <gtk/gtk.h>
00032 #include <string.h>
00033
00034
00035 namespace gtk
00036 {
00037
00038
00039
00040
00041 template <class T>
00042 class GtkEventSource
00043 {
00044 public:
00045 enum EventType
00046 {
00047 EVENT_EXPOSE = 0,
00048 EVENT_CONFIG,
00049 EVENT_BUTTON_PRESS,
00050 EVENT_BUTTON_RELEASE,
00051 EVENT_MOTION_NOTIFY,
00052 EVENT_KEY_PRESS,
00053 EVENT_KEY_RELEASE,
00054 EVENT_DELETE,
00055 EVENT_FD_INPUT,
00056 EVENT_UNDEFINED,
00057 };
00058
00059 public:
00060 GtkEventSource(T * r)
00061 : receiver(r)
00062 {
00063 memset(&callbacks[0], 0, sizeof(callbacks));
00064 }
00065
00066 ~GtkEventSource()
00067 {
00068 }
00069
00070
00071 void clear(GtkWidget * widget)
00072 {
00073 for(size_t i = 0; i < handler_ids.size(); ++i)
00074 {
00075 gtk_signal_disconnect(GTK_OBJECT (widget), handler_ids[i]);
00076 }
00077
00078 handler_ids.clear();
00079 receiver = 0;
00080 memset(&callbacks[0], 0, sizeof(callbacks));
00081 }
00082
00083
00084 void connect_event_handlers(GtkWidget * widget)
00085 {
00086
00087 gtk_widget_set_events (widget,
00088 GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK |
00089 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
00090 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
00091
00092
00093 handler_ids.push_back(
00094 gtk_signal_connect (GTK_OBJECT (widget), "expose_event",
00095 GTK_SIGNAL_FUNC (widget_event_handler), this));
00096
00097 handler_ids.push_back(
00098 gtk_signal_connect (GTK_OBJECT (widget), "configure_event",
00099 GTK_SIGNAL_FUNC (widget_event_handler), this));
00100
00101 handler_ids.push_back(
00102 gtk_signal_connect (GTK_OBJECT (widget), "button_press_event",
00103 GTK_SIGNAL_FUNC (widget_event_handler), this));
00104
00105 handler_ids.push_back(
00106 gtk_signal_connect (GTK_OBJECT (widget), "button_release_event",
00107 GTK_SIGNAL_FUNC (widget_event_handler), this));
00108
00109 handler_ids.push_back(
00110 gtk_signal_connect (GTK_OBJECT (widget), "motion_notify_event",
00111 GTK_SIGNAL_FUNC (widget_event_handler), this));
00112
00113 handler_ids.push_back(
00114 gtk_signal_connect (GTK_OBJECT (widget), "key_press_event",
00115 GTK_SIGNAL_FUNC (widget_event_handler), this));
00116
00117 handler_ids.push_back(
00118 gtk_signal_connect (GTK_OBJECT (widget), "key_release_event",
00119 GTK_SIGNAL_FUNC (widget_event_handler), this));
00120
00121 handler_ids.push_back(
00122 gtk_signal_connect (GTK_OBJECT (widget), "delete_event",
00123 GTK_SIGNAL_FUNC (widget_event_handler), this));
00124 }
00125
00126
00127 void set_fd_event_watcher(int fd, gboolean
00128 (T::*func)(GtkWidget *widget,
00129 GdkEvent * event))
00130 {
00131 gdk_input_add(fd, GDK_INPUT_READ,
00132 (GdkInputFunction)fd_event_handler,
00133 (gpointer)this);
00134
00135 callbacks[EVENT_FD_INPUT] = func;
00136 }
00137
00138
00139 inline void set_event_handler(EventType type,
00140 gboolean (T::*func)(GtkWidget * widget,
00141 GdkEvent * event))
00142 {
00143 callbacks[type] = func;
00144 }
00145
00146 private:
00147 static gboolean widget_event_handler(GtkWidget * widget,
00148 GdkEvent * event,
00149 gpointer user_data)
00150 {
00151 GtkEventSource* pThis = (GtkEventSource *)user_data;
00152 if (event == 0)
00153 {
00154 return FALSE;
00155 }
00156
00157 switch (event->type)
00158 {
00159 case GDK_EXPOSE:
00160 return pThis->invoke_callback(EVENT_EXPOSE, widget, event);
00161 case GDK_CONFIGURE:
00162 return pThis->invoke_callback(EVENT_CONFIG, widget, event);
00163 case GDK_BUTTON_PRESS:
00164 return pThis->invoke_callback(EVENT_BUTTON_PRESS, widget, event);
00165 case GDK_BUTTON_RELEASE:
00166 return pThis->invoke_callback(EVENT_BUTTON_RELEASE, widget, event);
00167 case GDK_MOTION_NOTIFY:
00168 return pThis->invoke_callback(EVENT_MOTION_NOTIFY, widget, event);
00169 case GDK_KEY_PRESS:
00170 return pThis->invoke_callback(EVENT_KEY_PRESS, widget, event);
00171 case GDK_KEY_RELEASE:
00172 return pThis->invoke_callback(EVENT_KEY_RELEASE, widget, event);
00173 case GDK_DELETE:
00174 return pThis->invoke_callback(EVENT_DELETE, widget, event);
00175 default:
00176 break;
00177 }
00178
00179 return FALSE;
00180 }
00181
00182 static void fd_event_handler(gpointer user_data, gint *fd,
00183 GdkInputCondition id)
00184 {
00185 GtkEventSource *pThis = (GtkEventSource *)user_data;
00186 pThis->invoke_callback(EVENT_FD_INPUT, 0, 0);
00187 }
00188
00189 gboolean invoke_callback(EventType type,
00190 GtkWidget *widget,
00191 GdkEvent *event)
00192 {
00193 if (callbacks[type] && receiver)
00194 {
00195 return (receiver->*callbacks[type])(widget, event);
00196 }
00197 return FALSE;
00198 }
00199
00200 private:
00201 T * receiver;
00202 gboolean (T::*callbacks[EVENT_UNDEFINED])(GtkWidget *widget,
00203 GdkEvent *event);
00204 std::vector<gulong> handler_ids;
00205
00206 };
00207
00208 };
00209
00210 #endif
00211