Created
September 19, 2014 08:44
-
-
Save ptomato/c4245c77d375022a43c5 to your computer and use it in GitHub Desktop.
Clone a GObject
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Gtk = imports.gi.Gtk; | |
const GObject = imports.gi.GObject; | |
const Gir = imports.gi.GIRepository; | |
// G_PARAM_READWRITE is not yet properly introspected | |
const READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE; | |
const dontCloneTheseProperties = [ | |
['Gtk', 'Widget', 'parent'], // would try to add the new widget to the same parent | |
['Gtk', 'Widget', 'margin'], // sets all margin properties at once | |
['Gtk', 'Widget', 'expand'], // sets all expand properties at once | |
]; | |
function ignoreInfoEqual(arg1, arg2) { | |
return arg1[0] === arg2[0] && arg1[1] === arg2[1] && arg1[2] === arg2[2]; | |
} | |
function getWritablePropertyNamesForObjectInfo(info) { | |
let propertyNames = []; | |
let nProperties = Gir.object_info_get_n_properties(info); | |
for(let ix = 0; ix < nProperties; ix++) { | |
let propertyInfo = Gir.object_info_get_property(info, ix); | |
let flags = Gir.property_info_get_flags(propertyInfo); | |
if ((flags & READWRITE) == READWRITE) { | |
let name = propertyInfo.get_name(); | |
let ignoreInfo = [info.get_namespace(), info.get_name(), name]; | |
if (!dontCloneTheseProperties.some(ignoreInfoEqual.bind(null, ignoreInfo))) | |
propertyNames.push(name); | |
} | |
} | |
return propertyNames; | |
} | |
function clone(obj) { | |
// This seems like it ought to work, but segfaults: | |
// let typeClass = GObject.TypeClass.ref(obj.constructor.$gtype); | |
// let props = GObject.ObjectClass.prototype.list_properties.call(typeClass); | |
// let obj2 = new obj.constructor(props); | |
// return obj2; | |
let repository = Gir.Repository.get_default(); | |
let baseInfo = repository.find_by_gtype(obj.constructor.$gtype); | |
let propertyNames = []; | |
for (let info = baseInfo; info !== null; info = Gir.object_info_get_parent(info)) { | |
propertyNames = propertyNames.concat(getWritablePropertyNamesForObjectInfo(info)); | |
} | |
let constructProps = {}; | |
propertyNames.forEach(function (name) { | |
constructProps[name] = obj[name]; | |
}); | |
return new obj.constructor(constructProps); | |
} | |
Gtk.init(null); | |
let win = new Gtk.Window(); | |
let grid = new Gtk.Grid(); | |
let button1 = new Gtk.Button({ | |
label: 'I am a button!', | |
margin_left: 20, | |
tooltip_text: 'I am a tooltip!', | |
vexpand: true, | |
}); | |
let button2 = clone(button1); | |
grid.add(button1); | |
grid.add(button2); | |
win.add(grid); | |
win.connect('destroy', Gtk.main_quit); | |
win.show_all(); | |
Gtk.main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment