summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2020-10-22 11:02:57 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2020-10-22 11:02:57 +0200
commit3dc782adc709644a5fe4b94f427c24757989023b (patch)
tree6d73a2d9d5af4ddfc93056944c8027aa22e0d152
parent70c40bfec82cc104f129e738f2729d8117808d31 (diff)
downloadvala-3dc782adc709644a5fe4b94f427c24757989023b.tar.gz
gtkmodule: Support "binding" to bind GtkCallback to class of given property
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1093
-rw-r--r--codegen/valagtkmodule.vala46
-rw-r--r--tests/gtktemplate/gtktemplate.ui11
-rw-r--r--tests/gtktemplate/gtktemplate.vala7
3 files changed, 62 insertions, 2 deletions
diff --git a/codegen/valagtkmodule.vala b/codegen/valagtkmodule.vala
index 2f3431653..f78b39203 100644
--- a/codegen/valagtkmodule.vala
+++ b/codegen/valagtkmodule.vala
@@ -30,6 +30,8 @@ public class Vala.GtkModule : GSignalModule {
/* GResource name to real file name mapping */
private HashMap<string, string> gresource_to_file_map = null;
/* GtkBuilder xml handler to Vala signal mapping */
+ private HashMap<string, Property> current_handler_to_property_map = new HashMap<string, Property>(str_hash, str_equal);
+ /* GtkBuilder xml handler to Vala signal mapping */
private HashMap<string, Signal> current_handler_to_signal_map = new HashMap<string, Signal>(str_hash, str_equal);
/* GtkBuilder xml child to Vala class mapping */
private HashMap<string, Class> current_child_to_class_map = new HashMap<string, Class>(str_hash, str_equal);
@@ -145,6 +147,7 @@ public class Vala.GtkModule : GSignalModule {
MarkupReader reader = new MarkupReader (ui_file);
Class current_class = null;
+ Property? current_property = null;
bool template_tag_found = false;
MarkupTokenType current_token = reader.read_token (null, null);
@@ -199,6 +202,35 @@ public class Vala.GtkModule : GSignalModule {
current_handler_to_signal_map.set (handler_name, sig);
}
}
+ } else if (current_class != null && current_token == MarkupTokenType.START_ELEMENT && current_name == "binding") {
+ var property_name = reader.get_attribute ("name");
+ if (property_name == null) {
+ Report.error (node.source_reference, "Invalid binding in ui file `%s'".printf (ui_file));
+ current_token = reader.read_token (null, null);
+ continue;
+ }
+
+ property_name = property_name.replace ("-", "_");
+ current_property = SemanticAnalyzer.symbol_lookup_inherited (current_class, property_name) as Property;
+ if (current_property == null) {
+ Report.error (node.source_reference, "Unknown property `%s:%s' for binding in ui file `%s'".printf (current_class.get_full_name (), property_name, ui_file));
+ current_token = reader.read_token (null, null);
+ continue;
+ }
+ } else if (current_class != null && current_token == MarkupTokenType.START_ELEMENT && current_name == "closure") {
+ var handler_name = reader.get_attribute ("function");
+
+ if (current_property != null) {
+ if (handler_name == null) {
+ Report.error (node.source_reference, "Invalid closure in ui file `%s'".printf (ui_file));
+ current_token = reader.read_token (null, null);
+ continue;
+ }
+
+ //TODO Retrieve signature declaration? c-type to vala-type?
+ current_handler_to_property_map.set (handler_name, current_property);
+ current_property = null;
+ }
}
current_token = reader.read_token (null, null);
}
@@ -337,8 +369,9 @@ public class Vala.GtkModule : GSignalModule {
/* Handler name as defined in the gtkbuilder xml */
var handler_name = m.get_attribute_string ("GtkCallback", "name", m.name);
var sig = current_handler_to_signal_map.get (handler_name);
- if (sig == null) {
- Report.error (m.source_reference, "could not find signal for handler `%s'".printf (handler_name));
+ var prop = current_handler_to_property_map.get (handler_name);
+ if (sig == null && prop == null) {
+ Report.error (m.source_reference, "could not find signal or property for handler `%s'".printf (handler_name));
return;
}
@@ -361,6 +394,15 @@ public class Vala.GtkModule : GSignalModule {
ccode.add_expression (call);
}
}
+ if (prop != null) {
+ prop.check (context);
+ //TODO Perform signature check
+ var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_class_bind_template_callback_full"));
+ call.add_argument (new CCodeIdentifier ("GTK_WIDGET_CLASS (klass)"));
+ call.add_argument (new CCodeConstant ("\"%s\"".printf (handler_name)));
+ call.add_argument (new CCodeIdentifier ("G_CALLBACK(%s)".printf (get_ccode_name (m))));
+ ccode.add_expression (call);
+ }
pop_context ();
}
diff --git a/tests/gtktemplate/gtktemplate.ui b/tests/gtktemplate/gtktemplate.ui
index 1546d9472..df9ca019d 100644
--- a/tests/gtktemplate/gtktemplate.ui
+++ b/tests/gtktemplate/gtktemplate.ui
@@ -42,6 +42,17 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="label0">
+ <binding name="label">
+ <closure type="gchararray" function="on_enabled_cb">
+ <constant type="gchararray">some string</constant>
+ <constant type="gint">42</constant>
+ <lookup name="boolean0">GtkTemplateTest</lookup>
+ </closure>
+ </binding>
+ </object>
+ </child>
</object>
</child>
</template>
diff --git a/tests/gtktemplate/gtktemplate.vala b/tests/gtktemplate/gtktemplate.vala
index fa6317ff0..5f66ccc21 100644
--- a/tests/gtktemplate/gtktemplate.vala
+++ b/tests/gtktemplate/gtktemplate.vala
@@ -6,6 +6,8 @@ public class GtkTemplate : Gtk.ApplicationWindow {
[GtkChild (internal = true)]
public Gtk.Button button1;
+ public bool boolean0 { get; set; }
+
[GtkCallback]
void on_clicked_cb (Gtk.Button button) {
}
@@ -13,4 +15,9 @@ public class GtkTemplate : Gtk.ApplicationWindow {
[GtkCallback (name = "on_activate_cb")]
void on_something_cb (Gtk.Button button) {
}
+
+ [GtkCallback]
+ string on_enabled_cb (string s, int i, bool val) {
+ return "%s:%i".printf (s, i);
+ }
}