Created
April 27, 2021 15:47
-
-
Save bwindels/36c0e3b17c5556972d84cbe06caa41b2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #!/usr/bin/gjs | |
| /* | |
| https://developer.gnome.org/platform-overview/unstable/tour-gjs.html.en | |
| https://gitlab.gnome.org/GNOME/gjs/wikis/Home | |
| examples at https://github.com/optimisme/gjs-examples | |
| docs at https://devdocs.baznga.org/gtk30~3.22.12/ | |
| */ | |
| imports.gi.versions.Gtk = '3.0'; | |
| const Gtk = imports.gi.Gtk; | |
| const Mainloop = imports.mainloop; | |
| const GObject = imports.gi.GObject; | |
| class HelloWorld { | |
| constructor() { | |
| this.app = new Gtk.Application(); | |
| this.app.connect('activate', this._onActivate.bind(this)); | |
| this.app.connect('startup', this._onStartup.bind(this)); | |
| } | |
| _onActivate() { | |
| this._window.show_all(); | |
| } | |
| async _onStartup() { | |
| try { | |
| const builder = new Gtk.Builder(); | |
| builder.add_from_file('ui.glade'); | |
| this._window = builder.get_object('mainwindow'); | |
| this.app.add_window(this._window); | |
| builder.get_object('header').set_title('haha!'); | |
| const list = builder.get_object('list'); | |
| list.set_model(this._createModel()); | |
| const column = new Gtk.TreeViewColumn({title: "Title"}); | |
| const cell = new Gtk.CellRendererText(); | |
| column.pack_start(cell, true); | |
| column.add_attribute(cell, "text", 0); | |
| list.append_column(column); | |
| await new Promise(resolve => Mainloop.timeout_add(2000, resolve)); | |
| builder.get_object('header').set_subtitle('t macheert gewoon!'); | |
| } catch (err) { | |
| log(err); | |
| } | |
| } | |
| _createModel() { | |
| const store = new Gtk.ListStore(); | |
| store.set_column_types([GObject.TYPE_STRING]); | |
| store.set_value(store.append(), 0, "hello"); | |
| store.set_value(store.append(), 0, "world"); | |
| store.set_value(store.append(), 0, "foo bar"); | |
| return store; | |
| } | |
| } | |
| new HelloWorld().app.run(ARGV); | |
| /** | |
| * looks like for a nice updatable list we will need to use ListBox (as fractal does). | |
| * It can take a Gio.ListModel, which can only emit an event for adding and removing items, | |
| * not for changing items. For this, it relies on the items being GObject's, | |
| * which have an notify (https://gjs-docs.gnome.org/gobject20~2.66p/gobject.object#signal-notify) signal for when it changes. | |
| * | |
| * So to convert a ObservableList to a ListModel, | |
| * we'd have to wrap all the items in a GObject wrapper, | |
| * declaring each property so we can bind to it? | |
| */ | |
| /** | |
| * In the GObject wrapper, | |
| * we might have to cache the values of all (or at least the ones used on an object) | |
| * the properties (like we do for the html binding) to know if the property has actually changed. | |
| * | |
| * E.g. in the ObservableListModel we would receive an onUpdate(index, value, params) and we would get the wrapper | |
| * for that index, and call checkChanged() or something, where it goes over all its properties and compares the | |
| * ones in the cache vs the ones returned by the original view model, and calls set_property (which emits the notify signal) for each changed? | |
| * | |
| * Alternatively, we start taking the arguments to emitChange([]) seriously... should we? hmmm | |
| * | |
| * We could then have the GObject be a stateless passthrough for our model... we declare the props with functions/closures? that just get it from the view model. | |
| * https://ptomato.wordpress.com/2017/07/14/inventing-gobject-es6-classes/ | |
| * http://videos.guadec.org/2017/turing20-philip_chimento-modern_javascript.webm | |
| * | |
| * Hmmm, or perhaps we can manually update the bindings for a collection and not use the gtk bindings. | |
| * | |
| * E.g. the widget returned from GtkListBoxCreateWidgetFunc can have an updateBindings() method that we call somehow | |
| * when an onUpdate is received, by getting the widget at the index (gtk_list_box_get_row_at_index), and calling updateBindings. | |
| * | |
| * Hmm, but that doesn't change the fact that Gio.ListModel needs to return a GObject ... | |
| * so we might as well go with the wrapper if we need a GObject anyway. | |
| * Probably best to go with the standard binding initially anyway | |
| */ | |
| // const RoomTileWrapper = createWrapper({ | |
| // hidden: GObject.TYPE_BOOL, | |
| // url: GObject.TYPE_STRING, | |
| // isOpen: GObject.TYPE_BOOL, | |
| // isUnread: GObject.TYPE_BOOL, | |
| // name: GObject.TYPE_STRING, | |
| // avatarUrl: GObject.TYPE_STRING, | |
| // }); | |
| // all properties would be readonly, as we only support one-way binding. | |
| // how can we call methods on the viewmodel? | |
| // wrapper.original.method() ? | |
| // const listModel = new ObservableListModel(list, RoomTileWrapper); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment