{"action":"created","issue":{"url":"https://api.github.com/repos/rust-gnome/gtk/issues/59","labels_url":"https://api.github.com/repos/rust-gnome/gtk/issues/59/labels{/name}","comments_url":"https://api.github.com/repos/rust-gnome/gtk/issues/59/comments","events_url":"https://api.github.com/repos/rust-gnome/gtk/issues/59/events","html_url":"https://github.com/rust-gnome/gtk/pull/59","id":73462531,"number":59,"title":"[RFC] GObject wrappers refactoring","user":{"login":"gkoz","id":4260361,"avatar_url":"https://avatars.githubusercontent.com/u/4260361?v=3","gravatar_id":"","url":"https://api.github.com/users/gkoz","html_url":"https://github.com/gkoz","followers_url":"https://api.github.com/users/gkoz/followers","following_url":"https://api.github.com/users/gkoz/following{/other_user}","gists_url":"https://api.github.com/users/gkoz/gists{/gist_id}","starred_url":"https://api.github.com/users/gkoz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gkoz/subscriptions","organizations_url":"https://api.github.com/users/gkoz/orgs","repos_url":"https://api.github.com/users/gkoz/repos","events_url":"https://api.github.com/users/gkoz/events{/privacy}","received_events_url":"https://api.github.com/users/gkoz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-05-05T23:30:08Z","updated_at":"2015-05-06T07:40:47Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/rust-gnome/gtk/pulls/59","html_url":"https://github.com/rust-gnome/gtk/pull/59","diff_url":"https://github.com/rust-gnome/gtk/pull/59.diff","patch_url":"https://github.com/rust-gnome/gtk/pull/59.patch"},"body":"_Do not merge!_\r\n\r\nHere's my latest and likely final (modulo small improvements) version of the `GObject` wrapper framework first proposed at https://github.com/jeremyletang/rgtk/pull/197 that's supposed to replace the current approach of using macros and a C glue module.\r\n\r\nObjectives:\r\n* reduce code duplication by encapsulating reference counting and containers management;\r\n* reduce boilerplate by factoring out most common conversions and checks;\r\n* reduce reliance on macros in favor of generic programming that allows better type checking;\r\n* improve support for implementing multiple interfaces (e.g. `GtkTreeModel` is an interface implemented by `GtkTreeStore`, it shouldn't be represented as a separate widget);\r\n* support implementing some widgets in separate crates (e.g. `libvte`);\r\n* remove the need for `gtk_glue.c` and build complications it brings;\r\n* move toward automatic code generation from GIR by unifying the translations to/from the FFI types.\r\n\r\nThe `glib::translate` module shows all its power now: you can have a string, a widget, a nullable widget or a `GList` of widgets, doesn't matter, it just works, all applicable asserts included:\r\n```Rust\r\n    pub fn new() -> Button {\r\n        unsafe { Widget::borrow_from_glib(ffi::gtk_button_new()).downcast_unchecked() }\r\n    }\r\n\r\n    fn get_name(&self) -> Option<String> {\r\n        unsafe {\r\n            Option::borrow_from_glib(ffi::gtk_widget_get_name(self.upcast().lend_to_glib().0))\r\n        }\r\n    }\r\n\r\n    fn set_name(&self, name: &str) {\r\n        unsafe {\r\n            ffi::gtk_widget_set_name(self.upcast().lend_to_glib().0, name.lend_to_glib().0)\r\n        }\r\n    }\r\n\r\n    fn get_ancestor(&self, widget_type: Type) -> Option<Widget> {\r\n        unsafe {\r\n            Option::borrow_from_glib(\r\n                ffi::gtk_widget_get_ancestor(self.upcast().lend_to_glib().0, widget_type.to_glib()))\r\n        }\r\n    }\r\n\r\n    fn get_children(&self) -> Vec<Widget> {\r\n        unsafe {\r\n            Vec::take_outer_from_glib(\r\n                ffi::gtk_container_get_children(self.upcast().lend_to_glib().0))\r\n        }\r\n    }\r\n```\r\n\r\nThe `basic` example (not present in this PR) demonstrates the use of the only two widgets supported in this proof of concept - `Window` and `Button` each implementing its own trait as well as `WidgetTrait` and `ContainerTrait`, and downcasting from `Widget` to `Button`.\r\n\r\nThe changes touch almost all crates, you can find the principal changes here: [glib](https://github.com/gkoz/rust-gnome-glib/tree/refactor_objects), [gtk](https://github.com/gkoz/rust-gnome-gtk/tree/refactor_objects), [examples](https://github.com/gkoz/rust-gnome-examples/tree/refactor_objects) but for the example to build other crates need patching too.\r\n\r\nIf you want to run the code I suggest using the [__git-repo__](https://code.google.com/p/git-repo/) tool:\r\n* [Install __repo__](http://source.android.com/source/downloading.html#installing-repo).\r\n* Set up the working copy:\r\n```shell\r\n> cd some_empty_dir\r\n> repo init -u https://github.com/gkoz/rust-gnome-manifest -b refactor_objects\r\n> repo sync\r\n```\r\n* Run:\r\n```shell\r\n> cd examples\r\n> cargo run\r\n```"},"comment":{"url":"https://api.github.com/repos/rust-gnome/gtk/issues/comments/99356321","html_url":"https://github.com/rust-gnome/gtk/pull/59#issuecomment-99356321","issue_url":"https://api.github.com/repos/rust-gnome/gtk/issues/59","id":99356321,"user":{"login":"GuillaumeGomez","id":3050060,"avatar_url":"https://avatars.githubusercontent.com/u/3050060?v=3","gravatar_id":"","url":"https://api.github.com/users/GuillaumeGomez","html_url":"https://github.com/GuillaumeGomez","followers_url":"https://api.github.com/users/GuillaumeGomez/followers","following_url":"https://api.github.com/users/GuillaumeGomez/following{/other_user}","gists_url":"https://api.github.com/users/GuillaumeGomez/gists{/gist_id}","starred_url":"https://api.github.com/users/GuillaumeGomez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GuillaumeGomez/subscriptions","organizations_url":"https://api.github.com/users/GuillaumeGomez/orgs","repos_url":"https://api.github.com/users/GuillaumeGomez/repos","events_url":"https://api.github.com/users/GuillaumeGomez/events{/privacy}","received_events_url":"https://api.github.com/users/GuillaumeGomez/received_events","type":"User","site_admin":false},"created_at":"2015-05-06T07:40:47Z","updated_at":"2015-05-06T07:40:47Z","body":"The biggest current problem is the fact we can't convert an object into another one. For example, converting a `GtkListStore` into a `GtkTreeModel`. I wanted to add two functions for this:\r\n\r\n```Rust\r\ntrait GObject {\r\n    pub fn cast_to<T: GObject>(&self) -> T;\r\n    pub fn cast_from<T: GObject>(object: &T) -> Self;\r\n}\r\n```\r\n\r\nYour solution seems to allow such a thing in a better way. I'll test your example by the end of the week but I think I'll appreciate it. Very nice job !"}}