1 // $Id: widget.cc,v 1.66 2004/06/22 15:25:23 christof Exp $
2 /*  glade--: C++ frontend for glade (Gtk+ User Interface Builder)
3  *  Copyright (C) 1999-2000  Adolf Petig GmbH & Co. KG, written by Christof Petig
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 #include "widget.hh"
21 
TypeName(const Widget & w) const22 const std::string Gtk_Widget::TypeName(const Widget &w) const
23 {  return GtkPrefix()+"Widget";
24 }
25 
IncludeName(const Widget & w) const26 const std::string Gtk_Widget::IncludeName(const Widget &w) const
27 {  return Configuration.GtkmmIncludePath()+"widget.h";
28 }
29 
SignalHandlerArgs(const Widget & w,const std::string & signal,std::string & rettype,std::string & scope) const30 const std::string Gtk_Widget::SignalHandlerArgs(const Widget &w,const std::string &signal,std::string &rettype,std::string &scope) const
31 {  std::string bool_sig_ret="gint";
32    if (GTKMM2) bool_sig_ret="bool";
33    scope=Gtk_Widget::TypeName(w);
34    if (signal=="draw") return "GdkRectangle *rect";
35    if (signal=="size_request") return "GtkRequisition *req";
36    if (signal=="size_allocate") return "GtkAllocation *all";
37    if (signal=="state_changed") return "unsigned int state";
38    if (signal=="event") { rettype=bool_sig_ret; return "GdkEvent *ev"; }
39    if (signal=="button_press_event" || signal=="button_release_event")
40    { rettype=bool_sig_ret; return "GdkEventButton *ev"; }
41    if (signal=="motion_notify_event") { rettype=bool_sig_ret; return "GdkEventMotion *ev"; }
42    if (signal=="delete_event" || signal=="map_event" || signal=="unmap_event")
43    { rettype=bool_sig_ret; return "GdkEventAny *ev"; }
44    if (signal=="expose_event") { rettype=bool_sig_ret; return "GdkEventExpose *ev"; }
45    if (signal=="key_press_event" || signal=="key_release_event")
46    { rettype=bool_sig_ret; return "GdkEventKey *ev"; }
47    if (signal=="enter_notify_event" || signal=="leave_notify_event")
48    { rettype=bool_sig_ret; return "GdkEventCrossing *ev"; }
49    if (signal=="configure_event") { rettype=bool_sig_ret; return "GdkEventConfigure *ev"; }
50    if (signal=="focus_in_event" || signal=="focus_out_event")
51    { rettype=bool_sig_ret; return "GdkEventFocus *ev"; }
52    if (signal=="property_notify_event") { rettype=bool_sig_ret; return "GdkEventProperty *ev"; }
53    if (signal=="selection_clear_event" || signal=="selection_request_event" || signal=="selection_notify_event")
54    { rettype=bool_sig_ret; return "GdkEventSelection *ev"; }
55    if (signal=="proximity_in_event" || signal=="proximity_out_event")
56    { rettype=bool_sig_ret; return "GdkEventProximity *ev"; }
57    if (signal=="drag_begin_event") { rettype=bool_sig_ret; return "GdkEventDragBegin *ev"; }
58    if (signal=="drag_request_event") { rettype=bool_sig_ret; return "GdkEventDragRequest *ev"; }
59    const std::string drag_context= GTKMM2
60         ? "const Glib::RefPtr<Gdk::DragContext>& context"
61    	: "GdkDragContext *context";
62    const std::string selection_data = GTKMM24
63         ? "Gtk::SelectionData &selection_data"
64         : "GtkSelectionData *selection_data";
65    if (signal=="drag_begin" || signal=="drag_end" || signal=="drag_data_delete")
66    	return drag_context;
67    if (signal=="drag_data_get") return drag_context+","+selection_data+",guint info,guint time";
68    if (signal=="drag_leave") return drag_context+",guint time";
69    if (signal=="drag_motion" || signal=="drag_drop")
70    	return drag_context+",gint x,gint y,guint time";
71    if (signal=="drag_data_received")
72    	return drag_context+",gint x,gint y,"+selection_data+",guint info,guint time";
73    if (signal=="drop_enter_event") { rettype=bool_sig_ret; return "GdkEventDropEnter *ev"; }
74    if (signal=="drop_leave_event") { rettype=bool_sig_ret; return "GdkEventDropLeave *ev"; }
75    if (signal=="drop_data_available_event") { rettype=bool_sig_ret; return "GdkEventDropDataAvailable *ev"; }
76    if (signal=="other_event") { rettype=bool_sig_ret; return "GdkEventOther *ev"; }
77    if (signal=="selection_received") return selection_data+",guint time";
78    if (signal=="selection_get") return selection_data+",guint info,guint time";
79    if (signal=="client_event") { rettype=bool_sig_ret; return "GdkEventClient *ev"; }
80    if (signal=="no_expose_event") { rettype=bool_sig_ret; return "GdkEventAny *ev"; }
81    if (signal=="show" || signal=="grab_focus" || signal=="hide"
82    	|| signal=="destroy" || signal=="map" || signal=="unmap"
83    	|| signal=="realize" || signal=="unrealize") return "";
84    if (signal=="popup_menu") { rettype="bool"; return ""; }
85    if (signal=="visibility_notify_event") { rettype=bool_sig_ret; return "GdkEventVisibility *ev"; }
86    scope="";
87    return "";
88 }
89 
90 // define this to allow widgets of this type
91 //static Gtk_Widget Gtk_Widget;
92 
Configure(const Widget & w,CxxFile & f,const std::string & instance) const93 void Gtk_Widget::Configure(const Widget &w, CxxFile &f,const std::string &instance) const
94 {
95   /* Note: Below code causes trouble for menu items, as objects are created
96           _after_ this method is called. Also, most of it doesn't apply anyway;
97 	  the bits that do have been copied to appropriate locations. */
98   if(TypeName(w).find("MenuItem")!=std::string::npos)
99     return;
100 
101   // glade 0.x / 1.1.0
102   WriteIntIntProperty(w,f,instance, "width", "height",
103   	GTKMM2?"size_request":"usize");
104   // glade 1.1.2+
105   WriteIntIntProperty(w,f,instance, "width_request", "height_request",
106   	GTKMM2?"size_request":"usize");
107 
108   WriteEnumPropertyNS(w,f,instance, "events");
109 
110    // uposition
111    // style
112 
113    std::string name=w.Name();
114    if (!name.empty() && Configuration.widget_names)
115    {  f.Statement() << instance << "set_name(" << Configuration.CString_WithQuotes(name) << ')';
116    }
117 
118    WriteBoolProperty(w,f,instance, "sensitive");
119 
120    if (GTKMM1) WriteBoolProp_2Fun(w,f,instance, "can_focus",
121    		"unset_flags(GTK_CAN_FOCUS)", "set_flags(GTK_CAN_FOCUS)");
122    else
123    {  WriteBoolProp_2Fun(w,f,instance, "can_focus",
124    		"unset_flags(Gtk::CAN_FOCUS)", "set_flags(Gtk::CAN_FOCUS)");
125       WriteBoolProp_2Fun(w,f,instance, "can_default",
126    		"unset_flags(Gtk::CAN_DEFAULT)", "set_flags(Gtk::CAN_DEFAULT)");
127    }
128 
129    if (w.getBoolProperty("has_focus",false))
130    {  f.Statement() << instance << "grab_focus()";
131    }
132 
133    if (w.hasProperty("tooltip") && (!w.isSeperateClass() || instance.empty()))
134    {  std::string tooltip(w.getProperty("tooltip"));
135       f.Statement() << "_tooltips.set_tip(" << Reference(instance)
136             << ", " << Configuration.Translatable(tooltip) << ", \"\")";
137    }
138 // this will fail for internal widgets !! will it ? CP
139    if (Configuration.has_accelerators)
140    { for (Widget::const_iterator i=w.get_Accels();i!=w.end();++i)
141       {  std::string modifiers=i->getGladeAttr("modifiers");
142 	 std::string key=i->getGladeAttr("key");
143 	 const std::string signal=i->getGladeAttr("signal");
144 
145          if (modifiers.empty() || key.empty() || signal.empty())
146             std::cerr << w.Name() << ": accel is missing param ("
147             	<< modifiers << ',' << key << ',' << signal << ")\n";
148 	 else
149 	 { if (key.substr(0,4)!="GDK_") key="GDK_"+key;
150 	   f.Statement() << instance
151 			 << "add_accelerator("
152 			 << Configuration.CString_WithQuotes(signal)
153 			 << ", " << (GTKMM2 ? "" : "*")
154 			 << "gmm_data->getAccelGroup(), " << key << ", ";
155 	   if (GTKMM1)
156 	      f << "(GdkModifierType )" << modifiers << ", GTK_ACCEL_VISIBLE)";
157 	   else // gtkmm2
158 	   {  replace_all(modifiers,"GDK_","Gdk::");
159 	      if (modifiers=="0") f << "Gdk::ModifierType(0)";
160 	      else f << modifiers;
161 	      f << ", Gtk::ACCEL_VISIBLE)";
162 	   }
163  	 }
164       }
165    }
166 }
167 
Configure_show(const Widget & w,CxxFile & f,const std::string & instance) const168 void Gtk_Widget::Configure_show(const Widget &w, CxxFile &f,const std::string &instance) const
169 {  if (w.getBoolProperty("visible",!Configuration.glade2))
170    {  f.Statement() << instance << "show()";
171    }
172 }
173 
ApplyPreferences(Tag & t) const174 void Gtk_Widget::ApplyPreferences(Tag &t) const
175 {  if (!Configuration.has_accelerators && t.hasTag("accelerator"))
176 	Configuration.has_accelerators=true;
177    Parent::ApplyPreferences(t);
178 }
179 
isInternalMethod(const Widget & w,std::string & method,const std::string & args,std::string & scope,bool & is_signal) const180 bool Gtk_Widget::isInternalMethod(const Widget &w,std::string &method,const std::string &args,std::string &scope,bool &is_signal) const
181 {  const char prefix[]="gtk_widget_";
182    const int plen(sizeof(prefix)-1);
183    if (method.substr(0,plen)==prefix) method=method.substr(plen);
184    if ((method=="set_usize" && matches("gint\\ \\_,gint\\ \\_",args))
185 	|| ((method=="set_flags" || method=="unset_flags")
186 		&& (matches("gint\\ \\_",args)||matches("int\\ \\_",args))))
187    {  scope=Gtk_Widget::TypeName(w);
188       is_signal=false;
189       return true;
190    }
191    if ((method=="grab_focus" && args.empty() && GTKMM2)
192 	|| (method=="grab_default" && args.empty())
193 	|| (method=="set_usize" && matches("gint\\ \\_,gint\\ \\_",args))
194 	|| ((method=="set_flags" || method=="unset_flags")
195 		&& (matches("gint\\ \\_",args)||matches("int\\ \\_",args))))
196    {  scope=Gtk_Widget::TypeName(w);
197       is_signal=false;
198       return true;
199    }
200    return Parent::isInternalMethod(w,method,args,scope,is_signal);
201 }
202 
isProxySignal(const Widget & w,std::string & method,bool after) const203 bool Gtk_Widget::isProxySignal(const Widget &w,std::string &method,bool after)const
204 {  if (after && method.size()>6 && method.substr(method.size()-6)=="_event")
205    {  std::string rettype,scope;
206       SignalHandlerArgs(w,method,rettype,scope);
207       if (scope==Gtk_Widget::TypeName(w))
208          std::cerr << "You really should connect with '!after' to " << w.Name()
209       		<< "'s " << method << '\n';
210    }
211    return Parent::isProxySignal(w,method,after);
212 }
213