From 531a88aaf0f1b50870df3009becb2b1ee0e9596b Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Thu, 10 Oct 2024 15:30:09 +0200 Subject: [PATCH 1/2] Port "List View with Sections" to JavaScript --- src/List View with Sections/main.blp | 22 ++++++------- src/List View with Sections/main.js | 47 ++++++++++++++++++++++++++++ src/List View with Sections/main.py | 12 +++---- 3 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 src/List View with Sections/main.js diff --git a/src/List View with Sections/main.blp b/src/List View with Sections/main.blp index 779e25dd..38d7a6c0 100644 --- a/src/List View with Sections/main.blp +++ b/src/List View with Sections/main.blp @@ -13,6 +13,17 @@ Adw.StatusPage { orientation: vertical; spacing: 18; + ScrolledWindow { + height-request: 330; + has-frame: true; + + child: ListView list_view { + factory: SignalListItemFactory item_factory {}; + + header-factory: SignalListItemFactory header_factory {}; + }; + } + Box { halign: center; @@ -26,17 +37,6 @@ Adw.StatusPage { uri: "https://docs.gtk.org/gtk4/section-list-widget.html#sections"; } } - - ScrolledWindow { - height-request: 330; - has-frame: true; - - child: ListView list_view { - factory: SignalListItemFactory item_factory {}; - - header-factory: SignalListItemFactory header_factory {}; - }; - } } } } diff --git a/src/List View with Sections/main.js b/src/List View with Sections/main.js new file mode 100644 index 00000000..577b6475 --- /dev/null +++ b/src/List View with Sections/main.js @@ -0,0 +1,47 @@ +import Gtk from "gi://Gtk"; +import GObject from "gi://GObject"; + +const list_view = workbench.builder.get_object("list_view"); +const item_factory = workbench.builder.get_object("item_factory"); +const header_factory = workbench.builder.get_object("header_factory"); + +const CustomModel = GObject.registerClass( + { + Implements: [Gtk.SectionModel], + }, + class CustomModel extends Gtk.StringList { + vfunc_get_section(position) { + const start = position; + const end = start + 5; + return [start, end]; + } + }, +); + +item_factory.connect("setup", (_self, list_item) => { + list_item.set_child( + new Gtk.Label({ margin_start: 12, halign: Gtk.Align.START }), + ); +}); + +item_factory.connect("bind", (_self, list_item) => { + const item = list_item.get_item(); + const label = list_item.get_child(); + + label.set_label(item.get_string()); +}); + +header_factory.connect("setup", (_self, list_item) => { + list_item.set_child( + new Gtk.Label({ label: "Header", halign: Gtk.Align.START }), + ); +}); + +const custom_model = new CustomModel(); + +for (let i = 1; i <= 200; i++) { + custom_model.append(`Item ${i}`); +} + +const selection_model = new Gtk.NoSelection({ model: custom_model }); +list_view.set_model(selection_model); diff --git a/src/List View with Sections/main.py b/src/List View with Sections/main.py index a990ae18..758646aa 100644 --- a/src/List View with Sections/main.py +++ b/src/List View with Sections/main.py @@ -1,7 +1,6 @@ import gi gi.require_version("Gtk", "4.0") -gi.require_version("Adw", "1") from gi.repository import Gtk import workbench @@ -11,17 +10,14 @@ class CustomModel(Gtk.StringList, Gtk.SectionModel): - def __init__(self): - super().__init__() - def do_get_section(self, position): - start = (position // 5) * 5 + start = position end = start + 5 return (start, end) def on_setup_item(_, list_item): - list_item.set_child(Gtk.Label(margin_start=12, xalign=0)) + list_item.set_child(Gtk.Label(margin_start=12, halign=Gtk.Align.START)) def on_bind_item(_, list_item): @@ -32,12 +28,12 @@ def on_bind_item(_, list_item): def on_setup_header(_, list_item): - list_item.set_child(Gtk.Label(label="Header", xalign=0)) + list_item.set_child(Gtk.Label(label="Header", halign=Gtk.Align.START)) custom_model = CustomModel() -for i in range(0, 200): +for i in range(1, 201): custom_model.append(f"Item {i}") item_factory.connect("setup", on_setup_item) From b2cd70441975ad98812555a8070847a6ae45dc6d Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Thu, 10 Oct 2024 15:30:53 +0200 Subject: [PATCH 2/2] Port "List View with a Tree" to JavaScript --- src/List View with a Tree/main.js | 84 +++++++++++++++++++++++++++++++ src/List View with a Tree/main.py | 3 +- 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/List View with a Tree/main.js diff --git a/src/List View with a Tree/main.js b/src/List View with a Tree/main.js new file mode 100644 index 00000000..679b6428 --- /dev/null +++ b/src/List View with a Tree/main.js @@ -0,0 +1,84 @@ +import Gtk from "gi://Gtk"; +import GObject from "gi://GObject"; +import Gio from "gi://Gio"; + +const list_view = workbench.builder.get_object("list_view"); +const factory = workbench.builder.get_object("factory"); + +const TreeNode = GObject.registerClass( + class TreeNode extends GObject.Object { + constructor(title, children) { + super(); + this.title = title; + this.children = children; + } + }, +); + +const TreeWidget = GObject.registerClass( + class TreeWidget extends Gtk.Box { + constructor(...args) { + super(...args); + this.spacing = 6; + this.margin_start = 6; + this.margin_end = 12; + this.margin_top = 6; + this.margin_bottom = 6; + + this.expander = new Gtk.TreeExpander(); + this.label = new Gtk.Label({ halign: Gtk.Align.START }); + + this.append(this.expander); + this.append(this.label); + } + }, +); + +function create_model_func(item) { + if (item.children.length < 1) return null; + const child_model = new Gio.ListStore(TreeNode); + for (const child of item.children) { + child_model.append(child); + } + return child_model; +} + +factory.connect("setup", (_self, list_item) => { + list_item.set_child(new TreeWidget()); +}); + +factory.connect("bind", (_self, list_item) => { + const list_row = list_item.get_item(); + const widget = list_item.get_child(); + const item = list_row.get_item(); + + widget.expander.set_list_row(list_row); + widget.label.set_label(item.title); +}); + +const root_model = new TreeNode("Root", [ + new TreeNode("Child 1", [ + new TreeNode("Child 1.1", []), + new TreeNode("Child 1.2", []), + ]), + new TreeNode("Child 2", [ + new TreeNode("Child 2.1", []), + new TreeNode("Child 2.2", []), + new TreeNode("Child 2.3", [new TreeNode("Child 3.1", [])]), + ]), +]); + +const tree_model = new Gio.ListStore(TreeNode); +tree_model.append(root_model); + +const tree_list_model = Gtk.TreeListModel.new( + tree_model, + false, + true, + create_model_func, +); +tree_list_model.set_autoexpand(false); + +const selection_model = new Gtk.NoSelection({ model: tree_list_model }); + +list_view.set_model(selection_model); diff --git a/src/List View with a Tree/main.py b/src/List View with a Tree/main.py index a3cec7ad..53b2f545 100644 --- a/src/List View with a Tree/main.py +++ b/src/List View with a Tree/main.py @@ -1,7 +1,6 @@ import gi gi.require_version("Gtk", "4.0") -gi.require_version("Adw", "1") from gi.repository import Gtk, GObject, Gio import workbench @@ -24,7 +23,7 @@ def __init__(self): self.expander = Gtk.TreeExpander.new() - self.label = Gtk.Label(xalign=0, ellipsize=3) + self.label = Gtk.Label(halign=Gtk.Align.START) self.append(self.expander) self.append(self.label)