1/* $Id: xml.ccg,v 1.14 2006/01/20 14:55:53 murrayc Exp $ */ 2 3/* Copyright (C) 2002 The libglademm Development Team 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public 16 * License along with this library; if not, write to the Free 17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20#include <glade/glade-xml.h> 21#include <gtkmm/button.h> 22#include <gtkmm/menuitem.h> 23#include <gtkmm/toolbutton.h> 24 25namespace Gnome 26{ 27 28namespace Glade 29{ 30 31XmlError::XmlError(const Glib::ustring& message) 32: 33 message_ (message) 34{} 35 36XmlError::~XmlError() throw() 37{} 38 39XmlError::XmlError(const XmlError& other) 40: 41 Glib::Exception (other), 42 message_ (other.message_) 43{} 44 45XmlError& XmlError::operator=(const XmlError& other) 46{ 47 message_ = other.message_; 48 return *this; 49} 50 51Glib::ustring XmlError::what() const 52{ 53 return message_; 54} 55 56 57#ifdef GLIBMM_EXCEPTIONS_ENABLED 58Xml::Xml(const std::string& filename, const Glib::ustring& root, const Glib::ustring& domain) 59#else 60Xml::Xml(const std::string& filename, const Glib::ustring& root, const Glib::ustring& domain, std::auto_ptr<XmlError>& error) 61#endif 62: 63 _CONSTRUCT() 64{ 65 if(!glade_xml_construct(gobj(), filename.c_str(), root.empty() ? 0 : root.c_str(), 66 domain.empty() ? 0 : domain.c_str())) 67 { 68#ifdef GLIBMM_EXCEPTIONS_ENABLED 69 throw XmlError("Failed to load glade file `" + Glib::filename_to_utf8(filename) + '\''); 70#else 71 std::auto_ptr<Glib::Error> dummy_error; 72 error.reset(new XmlError("Failed to load glade file `" + Glib::filename_to_utf8(filename, dummy_error) + '\'')); 73#endif // GLIBMM_EXCEPTIONS_ENABLED 74 } 75} 76 77#ifdef GLIBMM_EXCEPTIONS_ENABLED 78Xml::Xml(const char* buffer, int size, const Glib::ustring& root, const Glib::ustring& domain) 79#else 80Xml::Xml(const char* buffer, int size, const Glib::ustring& root, const Glib::ustring& domain, std::auto_ptr<XmlError>& error) 81#endif 82: 83 Glib::ObjectBase(0), //Mark this class as gtkmmproc-generated, rather than a custom class, to allow vfunc optimisations. 84 Glib::Object(Glib::ConstructParams(xml_class_.init(), (char*) 0)) 85{ 86 if(!glade_xml_construct_from_buffer(gobj(), buffer, size, root.empty() ? 0 87: root.c_str(), domain.empty() ? 0 : domain.c_str())) 88 { 89#ifdef GLIBMM_EXCEPTIONS_ENABLED 90 throw XmlError("Failed to read glade input buffer"); 91#else 92 error.reset(new XmlError("Failed to read glade input buffer")); 93#endif 94 } 95} 96 97// static 98#ifdef GLIBMM_EXCEPTIONS_ENABLED 99Glib::RefPtr<Xml> Xml::create(const std::string& filename, 100 const Glib::ustring& root, const Glib::ustring& domain) 101#else 102Glib::RefPtr<Xml> Xml::create(const std::string& filename, 103 const Glib::ustring& root, const Glib::ustring& domain, 104 std::auto_ptr<XmlError>& error) 105#endif 106{ 107#ifdef GLIBMM_EXCEPTIONS_ENABLED 108 return Glib::RefPtr<Xml>(new Xml(filename, root, domain)); 109#else 110 // Return an empty pointer if an error occurred, the resulting Xml object 111 // would not be of use anyway becasue the underlaying gobject_ is NULL. 112 Glib::RefPtr<Xml> xml(new Xml(filename, root, domain, error)); 113 if(error.get()) return Glib::RefPtr<Xml>(); 114 return xml; 115#endif 116} 117 118// static 119#ifdef GLIBMM_EXCEPTIONS_ENABLED 120Glib::RefPtr<Xml> Xml::create_from_buffer(const char* buffer, int size, 121 const Glib::ustring& root, const Glib::ustring& domain) 122#else 123Glib::RefPtr<Xml> Xml::create_from_buffer(const char* buffer, int size, 124 const Glib::ustring& root, const Glib::ustring& domain, 125 std::auto_ptr<XmlError>& error) 126#endif 127{ 128#ifdef GLIBMM_EXCEPTIONS_ENABLED 129 return Glib::RefPtr<Xml>(new Xml(buffer, size, root, domain)); 130#else 131 // Return an empty pointer if an error occurred, the resulting Xml object 132 // would not be of use anyway becasue the underlaying gobject_ is NULL. 133 Glib::RefPtr<Xml> xml(new Xml(buffer, size, root, domain, error)); 134 if(error.get()) return Glib::RefPtr<Xml>(); 135 return xml; 136#endif 137} 138 139void Xml::reparent_widget(const Glib::ustring& name, Gtk::Container& container) 140{ 141 Gtk::Widget* pWidget = 0; 142 get_widget(name, pWidget); 143 144 g_return_if_fail(pWidget != 0); 145 146 pWidget->reparent(container); 147} 148 149Gtk::Widget* Xml::get_widget_checked(const Glib::ustring& name, GType type) 150{ 151 // Get the widget from the glade file. 152 Gtk::Widget *const pWidget = get_widget(name); 153 154 if(!pWidget) 155 { 156 g_critical("widget `%s' not found in glade file `%s'", name.c_str(), gobj()->filename); 157 return 0; 158 } 159 160 // Check if it has the correct type. 161 if(!g_type_is_a(G_OBJECT_TYPE(pWidget->gobj()), type)) 162 { 163 g_critical("widget `%s' (in glade file `%s') is of type `%s' but `%s' was expected", 164 name.c_str(), gobj()->filename, G_OBJECT_TYPE_NAME(pWidget->gobj()), g_type_name(type)); 165 return 0; 166 } 167 168 return pWidget; 169} 170 171GtkWidget* Xml::get_cwidget(const Glib::ustring& name) 172{ 173 GtkWidget* pCWidget = glade_xml_get_widget(gobj(), name.c_str()); 174 if(!pCWidget) 175 { 176 g_critical("Glade::Xml::get_cwidget(): glade_xml_get_widget() failed for widget name=%s", name.c_str()); 177 } 178 179 return pCWidget; 180} 181 182#ifdef GLIBMM_VFUNCS_ENABLED 183// Custom coded so that we can custom-code the vfunc in the Xml class. 184// This is marginally better than modifying gtkmmproc to allow this. 185// 186GType Xml_Class::lookup_type_vfunc_callback(GladeXML* self, const char* classname) 187{ 188 CppObjectType *const obj = dynamic_cast<CppObjectType*>( 189 Glib::ObjectBase::_get_current_wrapper((GObject*) self)); 190 191 if(obj) 192 { 193 #ifdef GLIBMM_EXCEPTIONS_ENABLED 194 try 195 { 196 #endif //GLIBMM_EXCEPTIONS_ENABLED 197 return obj->lookup_type_vfunc(Glib::convert_const_gchar_ptr_to_ustring(classname)); 198 #ifdef GLIBMM_EXCEPTIONS_ENABLED 199 } 200 catch(...) 201 { 202 Glib::exception_handlers_invoke(); 203 } 204 #endif //GLIBMM_EXCEPTIONS_ENABLED 205 } 206 else 207 { 208 BaseClassType *const base = static_cast<BaseClassType*>( 209 g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class. 210 ); 211 212 if(base && base->lookup_type) 213 return (*base->lookup_type)(self, classname); 214 } 215 216 return 0; 217} 218#endif // GLIBMM_VFUNCS_ENABLED 219 220GType Xml::lookup_type_vfunc(const Glib::ustring& classname) 221{ 222 // See if there is a gtkmm version of the gclass: 223 Glib::ustring classname_prefixed ("gtkmm__"); // gtkmm uses a prefix 224 classname_prefixed += classname; 225 226 GType gtype = g_type_from_name(classname_prefixed.c_str()); 227 228 if(gtype == G_TYPE_INVALID) // if it's not a registered typename 229 { 230 // There's no gtkmm derived type, so just use the normal one. 231 gtype = g_type_from_name(classname.c_str()); 232 } 233 234 return gtype; 235} 236 237void Xml::connect_clicked(const Glib::ustring& widget_name, const sigc::slot<void>& slot_ ) 238{ 239 Gtk::Widget* pWidget = 0; 240 get_widget(widget_name, pWidget); 241 242 Gtk::Button* pButton = dynamic_cast<Gtk::Button*>(pWidget); 243 Gtk::MenuItem* pMenuItem = dynamic_cast<Gtk::MenuItem*>(pWidget); 244 Gtk::ToolButton* pToolButton = dynamic_cast<Gtk::ToolButton*>(pWidget); 245 246 if(pButton) 247 pButton->signal_clicked().connect( slot_); 248 249 if(pMenuItem) 250 pMenuItem->signal_activate().connect( slot_ ); 251 252 if(pToolButton) 253 pToolButton->signal_clicked().connect( slot_ ); 254} 255 256} // namespace Glade 257} // namespace Gnome 258 259