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