ClutterBoxLayout

ClutterStage が現在 Wayland で使えないのはあきらめて。
当面は GtkClutter を使ったサンプルコードを書いていこう。

今回は ClutterActor のレイアウトマネージャ。

GTK+ と全然違い property の layout-manager で指定するようだ。
デフォルトは ClutterFixedLayout になっている。
書くまでもなく絶対値配置なので子 Actor は重なって表示される。

GtkBox のように並べて配置するには ClutterBoxLayout を指定。
clutter_actor_add_child するだけで普通に並んでいく。

#!/usr/bin/gjs

const Clutter = imports.gi.Clutter;
const GtkClutter = imports.gi.GtkClutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;

const ListTest = new Lang.Class({
    Name: 'ListTest',
    Extends: Gtk.Window,

    _init: function() {
        this.parent({
            title: "add_actor"
        });
        // BoxLayout
        let layout = new Clutter.BoxLayout({
            orientation: Clutter.Orientation.VERTICAL,
            spacing: 1
        });
        // Actor
        this.actor = new Clutter.Actor({
            layout_manager: layout
        });
        // add
        let girls = ["椎名心実です", "あかね!", "くおえうえーーーうえうぅぅぅ"];
        for (let i=0; i<girls.length; i++) {
            let item = new Clutter.Text({
                x_align: Clutter.ActorAlign.START,
                x_expand: true,
                text: girls[i]
            });
            this.actor.add_child(item);
        }
        // Embed
        let embed = new GtkClutter.Embed();
        let stage = embed.get_stage();
        stage.add_child(this.actor);
        this.add(embed);
        // this
        this.connect("hide", Gtk.main_quit);
        this.show_all();
    }
});

GtkClutter.init(null);
new ListTest();
Gtk.main();

GListModel を使ってバインドもできる。
頻繁に入れ替えを行う場合はこちらのほうが便利かもしれない。

#!/usr/bin/gjs

const Clutter = imports.gi.Clutter;
const GtkClutter = imports.gi.GtkClutter;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang;

const ListTest = new Lang.Class({
    Name: 'ListTest',
    Extends: Gtk.Window,

    _init: function() {
        this.parent({
            title: "GListStore"
        });
        // GListStore  
        this.model = new Gio.ListStore({
            item_type: Clutter.Text
        });
        // layout
        let layout = new Clutter.BoxLayout({
            orientation: Clutter.Orientation.VERTICAL,
            //pack_start: true,
            spacing: 1
        });
        // Actor
        this.actor = new Clutter.Actor({
            background_color: Clutter.Color.from_string("#aaa")[1],
            layout_manager: layout
        });
        this.actor.bind_model(this.model, Lang.bind(this, function(item) {
            return item;
        }));
        // append
        let girls = ["椎名心実です", "あかね!", "くおえうえーーーうえうぅぅぅ"];
        for (let i=0; i<girls.length; i++) {
            let item = new Clutter.Text({
                x_align: Clutter.ActorAlign.START,
                x_expand: true,
                text: girls[i]
            });
            this.model.append(item);
        }
        // remove
        this.model.remove(1);
        // Embed
        let embed = new GtkClutter.Embed();
        let stage = embed.get_stage();
        stage.add_child(this.actor);
        this.add(embed);
        // this
        this.connect("hide", Gtk.main_quit);
        this.resize(this.actor.width, this.actor.height);
        this.show_all();
    }
});

GtkClutter.init(null);
new ListTest();
Gtk.main();

GTK+ 同様に子 Actor のサイズによって親のサイズが拡大されるようだ。
ただし GTK+ 部品にまでは適用されないのでそこらは自力で。