1// -*- c++ -*- 2/* $Id: entrycompletion.ccg,v 1.13 2006/07/19 16:58:50 murrayc Exp $ */ 3 4/* Copyright 2003 The gtkmm Development Team 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free 18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include <gtkmm/treeiter.h> 22#include <gtkmm/entry.h> 23#include <gtk/gtk.h> 24 25 26static gboolean SignalProxy_Match_gtk_callback(GtkEntryCompletion* completion, const gchar* key, GtkTreeIter* iter, gpointer user_data) 27{ 28 Gtk::EntryCompletion::SlotMatch* the_slot = static_cast<Gtk::EntryCompletion::SlotMatch*>(user_data); 29 30 try 31 { 32 GtkTreeModel* tree_model = gtk_entry_completion_get_model(completion); 33 return (*the_slot)(Glib::convert_const_gchar_ptr_to_ustring(key), 34 Gtk::TreeModel::const_iterator(tree_model, iter) 35 ); 36 } 37 catch(...) 38 { 39 Glib::exception_handlers_invoke(); 40 } 41 42 return false; //An arbitary default, just to avoid the compiler warning. 43} 44 45static void SignalProxy_Match_gtk_callback_destroy(void* data) 46{ 47 delete static_cast<Gtk::EntryCompletion::SlotMatch*>(data); 48} 49 50 51namespace Gtk 52{ 53 54void EntryCompletion::unset_model() 55{ 56 gtk_entry_completion_set_model(gobj(), 0); 57} 58 59void EntryCompletion::set_match_func(const SlotMatch& slot) 60{ 61 // Create a copy of the slot. A pointer to this will be passed 62 // through the callback's data parameter. It will be deleted 63 // when SignalProxy_Match_gtk_callback_destroy() is called. 64 SlotMatch* slot_copy = new SlotMatch(slot); 65 66 gtk_entry_completion_set_match_func(gobj(), 67 &SignalProxy_Match_gtk_callback, slot_copy, 68 &SignalProxy_Match_gtk_callback_destroy); 69} 70 71void EntryCompletion::insert_action_text(const Glib::ustring& text, int index) 72{ 73 gtk_entry_completion_insert_action_text(gobj(), index, text.c_str()); 74} 75 76void EntryCompletion::insert_action_markup(const Glib::ustring& markup, int index) 77{ 78 gtk_entry_completion_insert_action_markup(gobj(), index, markup.c_str()); 79} 80 81void EntryCompletion::prepend_action_text(const Glib::ustring& text) 82{ 83 //We know that gtk_entry_completion_insert_action_text() uses gtk_list_store_insert(), 84 //and we know that gtk_list_store_insert() prepends if the position is 0, though 85 //this is not actually documented. 86 gtk_entry_completion_insert_action_text(gobj(), 0, text.c_str()); 87} 88 89void EntryCompletion::prepend_action_markup(const Glib::ustring& markup) 90{ 91 //We know that gtk_entry_completion_insert_action_markup() uses gtk_list_store_insert(), 92 //and we know that gtk_list_store_insert() prepends if the position is 0, though 93 //this is not actually documented. 94 gtk_entry_completion_insert_action_markup(gobj(), 0 /* See C docs */, markup.c_str()); 95} 96 97} //namespace Gtk 98 99 100namespace //anonymous 101{ 102 103static gboolean Widget_signal_match_selected_callback(GtkEntryCompletion* self, GtkTreeModel* c_model, GtkTreeIter* c_iter, void* data) 104{ 105 using namespace Gtk; 106 typedef sigc::slot< bool, const TreeModel::iterator& > SlotType; 107 108 // Do not try to call a signal on a disassociated wrapper. 109 if(Glib::ObjectBase::_get_current_wrapper((GObject*) self)) 110 { 111 try 112 { 113 if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) 114 { 115 //This conversion is the custom-written part: 116 Gtk::TreeModel::iterator cppIter(c_model, c_iter); 117 118 return static_cast<int>( (*static_cast<SlotType*>(slot))(cppIter) ); 119 } 120 } 121 catch(...) 122 { 123 Glib::exception_handlers_invoke(); 124 } 125 } 126 127 typedef gboolean RType; 128 return RType(); 129} 130 131static gboolean Widget_signal_match_selected_notify_callback(GtkEntryCompletion* self, GtkTreeModel* c_model, GtkTreeIter* c_iter, void* data) 132{ 133 using namespace Gtk; 134 typedef sigc::slot< void, const TreeModel::iterator& > SlotType; 135 136 // Do not try to call a signal on a disassociated wrapper. 137 if(Glib::ObjectBase::_get_current_wrapper((GObject*) self)) 138 { 139 try 140 { 141 if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) 142 { 143 //This conversion is the custom-written part: 144 Gtk::TreeModel::iterator cppIter(c_model, c_iter); 145 146 (*static_cast<SlotType*>(slot))(cppIter); 147 } 148 } 149 catch(...) 150 { 151 Glib::exception_handlers_invoke(); 152 } 153 } 154 155 typedef gboolean RType; 156 return RType(); 157} 158 159const Glib::SignalProxyInfo EntryCompletion_signal_match_selected_info = 160{ 161 "match_selected", 162 (GCallback) &Widget_signal_match_selected_callback, 163 (GCallback) &Widget_signal_match_selected_notify_callback 164}; 165 166 167static gboolean Widget_signal_cursor_on_match_callback(GtkEntryCompletion* self, GtkTreeModel* c_model, GtkTreeIter* c_iter, void* data) 168{ 169 using namespace Gtk; 170 typedef sigc::slot< bool, const TreeModel::iterator& > SlotType; 171 172 // Do not try to call a signal on a disassociated wrapper. 173 if(Glib::ObjectBase::_get_current_wrapper((GObject*) self)) 174 { 175 try 176 { 177 if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) 178 { 179 //This conversion is the custom-written part: 180 Gtk::TreeModel::iterator cppIter(c_model, c_iter); 181 182 return static_cast<int>( (*static_cast<SlotType*>(slot))(cppIter) ); 183 } 184 } 185 catch(...) 186 { 187 Glib::exception_handlers_invoke(); 188 } 189 } 190 191 typedef gboolean RType; 192 return RType(); 193} 194 195static gboolean Widget_signal_cursor_on_match_notify_callback(GtkEntryCompletion* self, GtkTreeModel* c_model, GtkTreeIter* c_iter, void* data) 196{ 197 using namespace Gtk; 198 typedef sigc::slot< void, const TreeModel::iterator& > SlotType; 199 200 // Do not try to call a signal on a disassociated wrapper. 201 if(Glib::ObjectBase::_get_current_wrapper((GObject*) self)) 202 { 203 try 204 { 205 if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) 206 { 207 //This conversion is the custom-written part: 208 Gtk::TreeModel::iterator cppIter(c_model, c_iter); 209 210 (*static_cast<SlotType*>(slot))(cppIter); 211 } 212 } 213 catch(...) 214 { 215 Glib::exception_handlers_invoke(); 216 } 217 } 218 219 typedef gboolean RType; 220 return RType(); 221} 222 223 224const Glib::SignalProxyInfo EntryCompletion_signal_cursor_on_match_info = 225{ 226 "match_selected", 227 (GCallback) &Widget_signal_cursor_on_match_callback, 228 (GCallback) &Widget_signal_cursor_on_match_notify_callback 229}; 230 231} //anonymous namespace 232 233 234namespace Gtk 235{ 236 237//Hand-coded signal wrapping: 238 239bool Gtk::EntryCompletion::on_match_selected(const TreeModel::iterator& iter) 240{ 241 BaseClassType *const base = static_cast<BaseClassType*>( 242 g_type_class_peek_parent(G_OBJECT_GET_CLASS(gobject_)) // Get the parent class of the object class (The original underlying C class). 243 ); 244 245 if(base && base->match_selected) 246 return (*base->match_selected)(gobj(), iter.get_model_gobject(), const_cast<GtkTreeIter*>(iter.gobj())); 247 else 248 { 249 typedef bool RType; 250 return RType(); //There should always be an implementation in the C object, so this will never happen. 251 } 252} 253 254gboolean EntryCompletion_Class::match_selected_callback_custom(GtkEntryCompletion* self, GtkTreeModel* c_model, GtkTreeIter* c_iter) 255{ 256 CppObjectType *const obj = dynamic_cast<CppObjectType*>( 257 Glib::ObjectBase::_get_current_wrapper((GObject*)self)); 258 259 // Non-gtkmmproc-generated custom classes implicitly call the default 260 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc- 261 // generated classes can use this optimisation, which avoids the unnecessary 262 // parameter conversions if there is no possibility of the virtual function 263 // being overridden: 264 if(obj && obj->is_derived_()) 265 { 266 try // Trap C++ exceptions which would normally be lost because this is a C callback. 267 { 268 // Call the virtual member method, which derived classes might override. 269 270 //This conversion is the custom-written part: 271 Gtk::TreeModel::iterator cppIter(c_model, c_iter); 272 return obj->on_match_selected(cppIter); 273 } 274 catch(...) 275 { 276 Glib::exception_handlers_invoke(); 277 } 278 } 279 else 280 { 281 BaseClassType *const base = static_cast<BaseClassType*>( 282 g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class). 283 ); 284 285 // Call the original underlying C function: 286 if(base && base->match_selected) 287 return (*base->match_selected)(self, c_model, c_iter); 288 } 289 290 typedef gboolean RType; 291 return RType(); 292} 293 294Glib::SignalProxy1< bool, const TreeModel::iterator& > EntryCompletion::signal_match_selected() 295{ 296 return Glib::SignalProxy1< bool, const TreeModel::iterator& >(this, &EntryCompletion_signal_match_selected_info); 297} 298 299Glib::SignalProxy1< bool, const TreeModel::iterator& > EntryCompletion::signal_cursor_on_match() 300{ 301 return Glib::SignalProxy1< bool, const TreeModel::iterator& >(this, &EntryCompletion_signal_cursor_on_match_info); 302} 303 304 305 306} // namespace Gtk 307 308