Hi Philip,
  I must admit I'm way more excited about GJS and Gtk than familiar with
it, so I'm not even sure why you would create properties that needs to go
"up and down" the bindings instead of simply keeping it in the JS side when
it makes sense.

However, since like I've said I don't have enough background, I've read
again your example and tried to think about a possible solution.

Right now, ES6 classes syntax is not suitable for things like `Properties`
at class definition.
There are three options here, and I don't know which one would be better:

   1. define properties like it was a generic instance one (properties
   proposal), it looks close to what you have now but it's based on ES6 syntax
   (I'll show you later an example)
   2. using class decorators, probably the best approach since those are
   the way to enrich or extend ( `@nativeProperties({list, of, props}) class
   Label extends Gtk.Label {}` ). This doesn't look so familiar though ...
   3. using an intermediate layer at class definition such `class Label
   extends Gtk.Label.withProperties({count, etc}) {}` where `withProperties`
   comes from `Function.prototype` or `__noSuchMethod__` ... although this one
   feels obtrusive and less future proof


To give you an idea about the first method, here an example with some API
improvement (or let's say an easier to write list of properties)

```js
const Gtk = require('Gtk');

class TimerLabel extends Gtk.Label {
  properties = {
    interval: {
      type: 'uint',
      value: 1000,
      flags: ['rw', 'co'] // constructor_only
    },                    // will set it on creation
    count: {              // as mark it as non writable
      type: 'uint',
      flags: 'r'  // as read only, creates a _count
    }             // with default uint value
  }               // readable through count getter
  constructor(props) {
    super(props);
    this.label = 'Hello World!';
    setInterval(() => {
      this._count++;
      this.notify('count');
    }, this.interval);
  }
}

Gtk.init(null);

let win = new Gtk.Window();
win.add(
  new TimerLabel()
    .on('notify::count', (obj) => {
      if (obj.count === 2 && obj.interval === 1000)
        Gtk.mainQuit();   //  ^ just as example
    })
);
win
  .on('show', Gtk.main)
  .on('destroy', Gtk.mainQuit)
  .showAll()
;
```

Above code uses properties as if it's instance property and in my case it
works well if I add more transformers but, at the same time, it requires
logical hacks (properties has nothing to do with the instance shape) and
technical hacks (parsing at runtime transformed code with stuff that should
happen at definition time).

Ideally, decorators will make the extension both look nicer and hopefully
easier to implement:

```js
@GObjectProperties({
  interval: {
    type: 'uint',
    value: 1000,
    flags: ['rw', 'co']
  },
  count: {type: 'uint', flags: 'r'}
});
class TimerLabel extends Gtk.Label {
  constructor(props) {
    super(props);
    this.label = 'Hello World!';
    setInterval(() => {
      this._count++;
      this.notify('count');
    }, this.interval);
  }
}
```

I find above variant more elegant.


To answer your other questions:

   1. `emit` and `on` in `jsgtk` uses native signals, where possible, or
   custom one. This is right now independent
   2. `jsgtk` is backward compatible, you can always switch to
   `this.notify()` instead of `emit` and `this.connect()` instead of
   `this.on()` or `this.once()`. Although in latter cases you need to store
   the returned `connect` reference/id since `on` and `once` works through
   handlers, not returned ids (the returned value is the object for
   chainability sake)

Last but not least, the idea behind simplified flags is that it takes long
time to remember the amount of arguments and their position in those
ParamSpec methods, plus it's nice to play with both prototype and instances
using flags so that

   - read only are getters in the proto with automatic _key = value created
   at initialization time ... no need to duplicate each time the JS coutnerpart
   - write only works like read only with this._key = value as setter
   counterpart
   - readwrite, which should probably be the default, simply create an own
   property at initialization time, like it is for the `interval` one I've
   used before ... this makes you write code that is reachable from "both
   worlds" using the same property, and even a `this.count++` would work (I'll
   write and push code later today)
   - it private is specified, and it's a readwrite, the definition will be
   as example `interval` but the JS side will have only a non enumerable
   `_interval`, as opposite of generically enumerable `interval` defined at
   construction time
   - if the flag is construction_only, the instance will have its own
   property value defined once during initialization but non writable

These are just few ideas on top of my head to make writing code easier than
it's now.

Best Regards
_______________________________________________
javascript-list mailing list
javascript-list@gnome.org
https://mail.gnome.org/mailman/listinfo/javascript-list

Reply via email to