gtk_source.h

Go to the documentation of this file.
00001 /*
00002  * File Name: gtk_source.h
00003  */
00004 
00005 /*
00006  * This file is part of liberscribble.
00007  *
00008  * liberscribble is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * liberscribble is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
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     /// @brief Enable caller to handle GTK events without inheriting from any class.
00039     /// One-one connection. It's better to use template based technology. 
00040     /// By GtkEventSource caller is able to handle multiple widgets' events.
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         /// Disconnect all connected signal handlers.
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         /// @brief Connect the event handler(slot) with the gtk event(signal)
00084         void connect_event_handlers(GtkWidget * widget)
00085         {
00086             // events 
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             // install event handlers.
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         /// @brief Set event handler of File Descriptor
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         /// @brief Set event handler of gtk event (from event loop)
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 }; //namespace gtk
00209 
00210 #endif
00211 
Generated by  doxygen 1.6.2-20100208