@gjsify/example-gtk-adwaita-storybook 0.53.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-main.js +8093 -3042
- package/dist/gjs.js +15 -10
- package/dist/gjs.node.mjs +10 -5
- package/package.json +5 -5
- package/src/browser/buttons/color-dialog-button.web.ts +42 -0
- package/src/browser/buttons/font-dialog-button.web.ts +42 -0
- package/src/browser/buttons/link-button.web.ts +37 -0
- package/src/browser/buttons/scale-button.web.ts +36 -0
- package/src/browser/buttons/toggle-button.web.ts +35 -0
- package/src/browser/controls/check-button.web.ts +38 -0
- package/src/browser/controls/gtk-spinner.web.ts +39 -0
- package/src/browser/controls/level-bar.web.ts +43 -0
- package/src/browser/controls/password-entry.web.ts +36 -0
- package/src/browser/controls/progress-bar.web.ts +39 -0
- package/src/browser/controls/scale.web.ts +44 -0
- package/src/browser/controls/search-entry.web.ts +49 -0
- package/src/browser/controls/spin-button.web.ts +40 -0
- package/src/browser/controls/switch.web.ts +38 -0
- package/src/browser/drawing/drag-icon.web.ts +112 -0
- package/src/browser/drawing/drawing-area.web.ts +66 -0
- package/src/browser/drawing/gl-area.web.ts +162 -0
- package/src/browser/drawing/graphics-offload.web.ts +74 -0
- package/src/browser/feedback/dialog.web.ts +76 -0
- package/src/browser/feedback/emoji-chooser.web.ts +93 -0
- package/src/browser/feedback/gtk-about-dialog.web.ts +105 -0
- package/src/browser/feedback/page-setup-unix-dialog.web.ts +93 -0
- package/src/browser/feedback/print-unix-dialog.web.ts +111 -0
- package/src/browser/feedback/shortcuts-dialog.web.ts +90 -0
- package/src/browser/layout/application-window.web.ts +94 -0
- package/src/browser/layout/aspect-frame.web.ts +49 -0
- package/src/browser/layout/bin.web.ts +41 -0
- package/src/browser/layout/breakpoint-bin.web.ts +61 -0
- package/src/browser/layout/center-box.web.ts +45 -0
- package/src/browser/layout/clamp-scrollable.web.ts +47 -0
- package/src/browser/layout/expander.web.ts +52 -0
- package/src/browser/layout/fixed.web.ts +51 -0
- package/src/browser/layout/frame.web.ts +40 -0
- package/src/browser/layout/grid.web.ts +46 -0
- package/src/browser/layout/layout-slot.web.ts +60 -0
- package/src/browser/layout/multi-layout-view.web.ts +94 -0
- package/src/browser/layout/overlay.web.ts +57 -0
- package/src/browser/layout/paned.web.ts +69 -0
- package/src/browser/layout/popover-bin.web.ts +54 -0
- package/src/browser/layout/popover-menu.web.ts +48 -0
- package/src/browser/layout/popover.web.ts +61 -0
- package/src/browser/layout/revealer.web.ts +53 -0
- package/src/browser/layout/scrollbar.web.ts +54 -0
- package/src/browser/layout/scrolled-window.web.ts +52 -0
- package/src/browser/layout/separator.web.ts +47 -0
- package/src/browser/layout/viewport.web.ts +51 -0
- package/src/browser/layout/window.web.ts +60 -0
- package/src/browser/media/image.web.ts +39 -0
- package/src/browser/media/inscription.web.ts +52 -0
- package/src/browser/media/media-controls.web.ts +65 -0
- package/src/browser/media/picture.web.ts +56 -0
- package/src/browser/media/video.web.ts +56 -0
- package/src/browser/navigation/popover-menu-bar.web.ts +40 -0
- package/src/browser/presentation/calendar.web.ts +49 -0
- package/src/browser/presentation/column-view.web.ts +45 -0
- package/src/browser/presentation/flow-box.web.ts +52 -0
- package/src/browser/presentation/grid-view.web.ts +37 -0
- package/src/browser/presentation/list-box.web.ts +48 -0
- package/src/browser/presentation/list-view.web.ts +36 -0
- package/src/browser/presentation/tree-expander.web.ts +68 -0
- package/src/browser/presentation/window-handle.web.ts +42 -0
- package/src/browser/rows/preferences-row.web.ts +43 -0
- package/src/browser/stories.ts +158 -0
- package/src/browser/text/editable-label.web.ts +45 -0
- package/src/browser/text/search-bar.web.ts +45 -0
- package/src/browser/text/text-view.web.ts +54 -0
- package/src/browser/text/text.web.ts +48 -0
- package/src/browser/view-switching/notebook.web.ts +67 -0
- package/src/browser/view-switching/stack-sidebar.web.ts +68 -0
- package/src/browser/view-switching/stack-switcher.web.ts +70 -0
- package/src/browser/view-switching/stack.web.ts +72 -0
- package/src/browser/view-switching/tab-bar.web.ts +105 -0
- package/src/browser/view-switching/tab-button.web.ts +52 -0
- package/src/browser/view-switching/tab-overview.web.ts +87 -0
- package/src/browser/view-switching/view-switcher-sidebar.web.ts +77 -0
- package/src/browser/windows/action-bar.web.ts +66 -0
- package/src/browser/windows/gtk-application-window.web.ts +67 -0
- package/src/browser/windows/gtk-header-bar.web.ts +61 -0
- package/src/browser/windows/gtk-window.web.ts +58 -0
- package/src/browser/windows/window-controls.web.ts +54 -0
- package/src/buttons/color-dialog-button.meta.ts +16 -0
- package/src/buttons/color-dialog-button.story.ts +49 -0
- package/src/buttons/font-dialog-button.meta.ts +29 -0
- package/src/buttons/font-dialog-button.story.ts +52 -0
- package/src/buttons/link-button.meta.ts +18 -0
- package/src/buttons/link-button.story.ts +48 -0
- package/src/buttons/scale-button.meta.ts +34 -0
- package/src/buttons/scale-button.story.ts +50 -0
- package/src/buttons/toggle-button.meta.ts +17 -0
- package/src/buttons/toggle-button.story.ts +46 -0
- package/src/controls/check-button.meta.ts +19 -0
- package/src/controls/check-button.story.ts +56 -0
- package/src/controls/gtk-spinner.meta.ts +24 -0
- package/src/controls/gtk-spinner.story.ts +53 -0
- package/src/controls/level-bar.meta.ts +39 -0
- package/src/controls/level-bar.story.ts +58 -0
- package/src/controls/password-entry.meta.ts +18 -0
- package/src/controls/password-entry.story.ts +54 -0
- package/src/controls/progress-bar.meta.ts +20 -0
- package/src/controls/progress-bar.story.ts +53 -0
- package/src/controls/scale.meta.ts +47 -0
- package/src/controls/scale.story.ts +66 -0
- package/src/controls/search-entry.meta.ts +18 -0
- package/src/controls/search-entry.story.ts +57 -0
- package/src/controls/spin-button.meta.ts +40 -0
- package/src/controls/spin-button.story.ts +55 -0
- package/src/controls/switch.meta.ts +18 -0
- package/src/controls/switch.story.ts +50 -0
- package/src/drawing/drag-icon.meta.ts +39 -0
- package/src/drawing/drag-icon.story.ts +117 -0
- package/src/drawing/drawing-area.meta.ts +45 -0
- package/src/drawing/drawing-area.story.ts +78 -0
- package/src/drawing/gl-area.meta.ts +30 -0
- package/src/drawing/gl-area.story.ts +113 -0
- package/src/drawing/graphics-offload.meta.ts +39 -0
- package/src/drawing/graphics-offload.story.ts +73 -0
- package/src/feedback/dialog.meta.ts +25 -0
- package/src/feedback/dialog.story.ts +78 -0
- package/src/feedback/emoji-chooser.meta.ts +10 -0
- package/src/feedback/emoji-chooser.story.ts +98 -0
- package/src/feedback/gtk-about-dialog.meta.ts +29 -0
- package/src/feedback/gtk-about-dialog.story.ts +90 -0
- package/src/feedback/page-setup-unix-dialog.meta.ts +37 -0
- package/src/feedback/page-setup-unix-dialog.story.ts +70 -0
- package/src/feedback/print-unix-dialog.meta.ts +30 -0
- package/src/feedback/print-unix-dialog.story.ts +93 -0
- package/src/feedback/shortcuts-dialog.meta.ts +12 -0
- package/src/feedback/shortcuts-dialog.story.ts +79 -0
- package/src/layout/application-window.meta.ts +16 -0
- package/src/layout/application-window.story.ts +97 -0
- package/src/layout/aspect-frame.meta.ts +19 -0
- package/src/layout/aspect-frame.story.ts +62 -0
- package/src/layout/bin.meta.ts +15 -0
- package/src/layout/bin.story.ts +56 -0
- package/src/layout/breakpoint-bin.meta.ts +38 -0
- package/src/layout/breakpoint-bin.story.ts +62 -0
- package/src/layout/center-box.meta.ts +26 -0
- package/src/layout/center-box.story.ts +54 -0
- package/src/layout/clamp-scrollable.meta.ts +30 -0
- package/src/layout/clamp-scrollable.story.ts +51 -0
- package/src/layout/expander.meta.ts +30 -0
- package/src/layout/expander.story.ts +62 -0
- package/src/layout/fixed.meta.ts +16 -0
- package/src/layout/fixed.story.ts +54 -0
- package/src/layout/frame.meta.ts +24 -0
- package/src/layout/frame.story.ts +51 -0
- package/src/layout/grid.meta.ts +45 -0
- package/src/layout/grid.story.ts +80 -0
- package/src/layout/layout-slot.meta.ts +22 -0
- package/src/layout/layout-slot.story.ts +68 -0
- package/src/layout/multi-layout-view.meta.ts +31 -0
- package/src/layout/multi-layout-view.story.ts +101 -0
- package/src/layout/overlay.meta.ts +42 -0
- package/src/layout/overlay.story.ts +72 -0
- package/src/layout/paned.meta.ts +45 -0
- package/src/layout/paned.story.ts +70 -0
- package/src/layout/popover-bin.meta.ts +29 -0
- package/src/layout/popover-bin.story.ts +66 -0
- package/src/layout/popover-menu.meta.ts +54 -0
- package/src/layout/popover-menu.story.ts +119 -0
- package/src/layout/popover.meta.ts +38 -0
- package/src/layout/popover.story.ts +66 -0
- package/src/layout/revealer.meta.ts +44 -0
- package/src/layout/revealer.story.ts +79 -0
- package/src/layout/scrollbar.meta.ts +33 -0
- package/src/layout/scrollbar.story.ts +61 -0
- package/src/layout/scrolled-window.meta.ts +57 -0
- package/src/layout/scrolled-window.story.ts +74 -0
- package/src/layout/separator.meta.ts +25 -0
- package/src/layout/separator.story.ts +53 -0
- package/src/layout/viewport.meta.ts +19 -0
- package/src/layout/viewport.story.ts +53 -0
- package/src/layout/window.meta.ts +13 -0
- package/src/layout/window.story.ts +66 -0
- package/src/media/image.meta.ts +24 -0
- package/src/media/image.story.ts +48 -0
- package/src/media/inscription.meta.ts +45 -0
- package/src/media/inscription.story.ts +64 -0
- package/src/media/media-controls.meta.ts +30 -0
- package/src/media/media-controls.story.ts +58 -0
- package/src/media/picture.meta.ts +42 -0
- package/src/media/picture.story.ts +81 -0
- package/src/media/video.meta.ts +32 -0
- package/src/media/video.story.ts +57 -0
- package/src/metas.ts +79 -0
- package/src/navigation/popover-menu-bar.meta.ts +51 -0
- package/src/navigation/popover-menu-bar.story.ts +72 -0
- package/src/presentation/calendar.meta.ts +28 -0
- package/src/presentation/calendar.story.ts +64 -0
- package/src/presentation/column-view.meta.ts +30 -0
- package/src/presentation/column-view.story.ts +73 -0
- package/src/presentation/flow-box.meta.ts +51 -0
- package/src/presentation/flow-box.story.ts +72 -0
- package/src/presentation/grid-view.meta.ts +28 -0
- package/src/presentation/grid-view.story.ts +64 -0
- package/src/presentation/list-box.meta.ts +55 -0
- package/src/presentation/list-box.story.ts +68 -0
- package/src/presentation/list-view.meta.ts +38 -0
- package/src/presentation/list-view.story.ts +73 -0
- package/src/presentation/tree-expander.meta.ts +24 -0
- package/src/presentation/tree-expander.story.ts +105 -0
- package/src/presentation/window-handle.meta.ts +27 -0
- package/src/presentation/window-handle.story.ts +53 -0
- package/src/rows/preferences-row.meta.ts +15 -0
- package/src/rows/preferences-row.story.ts +50 -0
- package/src/text/editable-label.meta.ts +17 -0
- package/src/text/editable-label.story.ts +47 -0
- package/src/text/search-bar.meta.ts +17 -0
- package/src/text/search-bar.story.ts +48 -0
- package/src/text/text-view.meta.ts +49 -0
- package/src/text/text-view.story.ts +69 -0
- package/src/text/text.meta.ts +21 -0
- package/src/text/text.story.ts +50 -0
- package/src/view-switching/notebook.meta.ts +44 -0
- package/src/view-switching/notebook.story.ts +77 -0
- package/src/view-switching/stack-sidebar.meta.ts +50 -0
- package/src/view-switching/stack-sidebar.story.ts +85 -0
- package/src/view-switching/stack-switcher.meta.ts +53 -0
- package/src/view-switching/stack-switcher.story.ts +95 -0
- package/src/view-switching/stack.meta.ts +53 -0
- package/src/view-switching/stack.story.ts +95 -0
- package/src/view-switching/tab-bar.meta.ts +22 -0
- package/src/view-switching/tab-bar.story.ts +85 -0
- package/src/view-switching/tab-button.meta.ts +14 -0
- package/src/view-switching/tab-button.story.ts +52 -0
- package/src/view-switching/tab-overview.meta.ts +21 -0
- package/src/view-switching/tab-overview.story.ts +86 -0
- package/src/view-switching/view-switcher-sidebar.meta.ts +42 -0
- package/src/view-switching/view-switcher-sidebar.story.ts +73 -0
- package/src/windows/action-bar.meta.ts +27 -0
- package/src/windows/action-bar.story.ts +65 -0
- package/src/windows/gtk-application-window.meta.ts +27 -0
- package/src/windows/gtk-application-window.story.ts +89 -0
- package/src/windows/gtk-header-bar.meta.ts +39 -0
- package/src/windows/gtk-header-bar.story.ts +76 -0
- package/src/windows/gtk-window.meta.ts +30 -0
- package/src/windows/gtk-window.story.ts +64 -0
- package/src/windows/window-controls.meta.ts +42 -0
- package/src/windows/window-controls.story.ts +61 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Shared, renderer-agnostic metadata for the Popover Menu story. Imported by the GTK
|
|
2
|
+
// renderer (popover-menu.story.ts) and the browser renderer
|
|
3
|
+
// (browser/layout/popover-menu.web.ts), so both expose identical controls.
|
|
4
|
+
|
|
5
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The menu both renderings build: a section with a heading, a plain item and a submenu, so
|
|
9
|
+
* the page stack and the decoration are both on show. Written as the PORTABLE model
|
|
10
|
+
* (ADR 0042) — the JSON `<gtk-popover-menu menu-model>` takes and `Gio.Menu` is built from
|
|
11
|
+
* on the GTK side.
|
|
12
|
+
*/
|
|
13
|
+
export const POPOVER_MENU_ITEMS = [
|
|
14
|
+
{ label: 'New Window', accel: '<Control>N' },
|
|
15
|
+
{ section: [{ label: 'Cut' }, { label: 'Copy' }, { label: 'Paste' }], label: 'Edit' },
|
|
16
|
+
{
|
|
17
|
+
label: 'Open With',
|
|
18
|
+
submenu: [{ label: 'Text Editor' }, { label: 'Web Browser' }, { label: 'Terminal' }],
|
|
19
|
+
},
|
|
20
|
+
] as const;
|
|
21
|
+
|
|
22
|
+
export const popoverMenuMeta: StoryMeta = {
|
|
23
|
+
title: 'Layout/Popover Menu',
|
|
24
|
+
description:
|
|
25
|
+
'Gtk.PopoverMenu — a Gtk.Popover whose contents are a menu model instead of a child widget. ' +
|
|
26
|
+
'A submenu swaps the page of the ONE surface rather than opening a second popup beside it, ' +
|
|
27
|
+
'which is why the open page is a named one (`visible-submenu`).',
|
|
28
|
+
controls: [
|
|
29
|
+
{ name: 'menuTitle', label: 'Heading', type: ControlType.TEXT, defaultValue: 'Document' },
|
|
30
|
+
{
|
|
31
|
+
name: 'position',
|
|
32
|
+
label: 'Position',
|
|
33
|
+
type: ControlType.SELECT,
|
|
34
|
+
options: [
|
|
35
|
+
{ label: 'Bottom', value: 'bottom' },
|
|
36
|
+
{ label: 'Top', value: 'top' },
|
|
37
|
+
{ label: 'Start', value: 'start' },
|
|
38
|
+
{ label: 'End', value: 'end' },
|
|
39
|
+
],
|
|
40
|
+
defaultValue: 'bottom',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'align',
|
|
44
|
+
label: 'Align',
|
|
45
|
+
type: ControlType.SELECT,
|
|
46
|
+
options: [
|
|
47
|
+
{ label: 'Start', value: 'start' },
|
|
48
|
+
{ label: 'End', value: 'end' },
|
|
49
|
+
],
|
|
50
|
+
defaultValue: 'start',
|
|
51
|
+
},
|
|
52
|
+
{ name: 'autohide', label: 'Dismiss on outside click', type: ControlType.BOOLEAN, defaultValue: true },
|
|
53
|
+
],
|
|
54
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Gtk.PopoverMenu — a Gtk.Popover whose contents are a menu model.
|
|
2
|
+
// original implementation.
|
|
3
|
+
|
|
4
|
+
import Gio from 'gi://Gio?version=2.0';
|
|
5
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
6
|
+
import GObject from 'gi://GObject?version=2.0';
|
|
7
|
+
import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
|
|
8
|
+
import { POPOVER_MENU_ITEMS, popoverMenuMeta } from './popover-menu.meta.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Story: a Gtk.PopoverMenu over a Gio.Menu with a section, a submenu and accelerators,
|
|
12
|
+
* anchored to a plain button.
|
|
13
|
+
*
|
|
14
|
+
* `GtkPopoverMenu.new_from_model` builds SLIDING submenus by default
|
|
15
|
+
* (gtkpopovermenu.c:786-799), which is the page-swap this element's replica draws; the
|
|
16
|
+
* nested form is the `flags` argument of `new_from_model_full` and is left at the default on
|
|
17
|
+
* purpose, so both renderings show the same shape.
|
|
18
|
+
*/
|
|
19
|
+
/** A detailed action name GIO parses: a label's spaces would make `g_menu_item_set_detailed_action` abort. */
|
|
20
|
+
const actionOf = (label: string): string => `app.${label.toLowerCase().replace(/[^a-z0-9]+/g, '-')}`;
|
|
21
|
+
|
|
22
|
+
export class PopoverMenuStory extends StoryWidget {
|
|
23
|
+
private _anchor: Gtk.Button | null = null;
|
|
24
|
+
private _popover: Gtk.PopoverMenu | null = null;
|
|
25
|
+
|
|
26
|
+
static {
|
|
27
|
+
GObject.registerClass({ GTypeName: 'AdwStorybookPopoverMenu' }, PopoverMenuStory);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
super(StoryWidget.fromMeta(PopoverMenuStory.getMetadata(), 'Default'));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static getMetadata(): StoryMeta {
|
|
35
|
+
return { ...popoverMenuMeta, component: Gtk.PopoverMenu.$gtype };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
initialize(): void {
|
|
39
|
+
this._anchor = new Gtk.Button({ label: 'Open menu', halign: Gtk.Align.CENTER });
|
|
40
|
+
this._apply();
|
|
41
|
+
this.addContent(this._anchor);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateArgs(_args: StoryArgs): void {
|
|
45
|
+
this._apply();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The portable menu (ADR 0042) as a `Gio.Menu`: a submenu is a `Gio.Menu` appended
|
|
50
|
+
* under its label, and an accelerator is a display string — nothing here binds a key,
|
|
51
|
+
* exactly as in GTK, where the binding is `gtk_application_set_accels_for_action`.
|
|
52
|
+
*
|
|
53
|
+
* THE HEADING IS THE FIRST SECTION, because `GMenuModel` has no title of its own. The
|
|
54
|
+
* browser element's `menu-title` is that shorthand, and this is the GTK half of the
|
|
55
|
+
* same fact: `gtk_popover_menu_open_submenu`'s "main" page is a `GtkStack` of
|
|
56
|
+
* `GtkMenuSectionBox`es, each of which can carry a label (gtkpopovermenu.c:152-164).
|
|
57
|
+
*/
|
|
58
|
+
private _buildMenu(title: string): Gio.Menu {
|
|
59
|
+
const menu = new Gio.Menu();
|
|
60
|
+
// The items that carry no section of their own, kept aside until the title decides
|
|
61
|
+
// whether they stand alone or become the heading's group.
|
|
62
|
+
const loose: string[] = [];
|
|
63
|
+
for (const entry of POPOVER_MENU_ITEMS) {
|
|
64
|
+
if ('submenu' in entry) {
|
|
65
|
+
const submenu = new Gio.Menu();
|
|
66
|
+
for (const item of entry.submenu) submenu.append(item.label, actionOf(item.label));
|
|
67
|
+
menu.append_submenu(entry.label, submenu);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if ('section' in entry) {
|
|
71
|
+
const section = new Gio.Menu();
|
|
72
|
+
for (const item of entry.section) section.append(item.label, actionOf(item.label));
|
|
73
|
+
menu.append_section('Edit', section);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
loose.push(entry.label);
|
|
77
|
+
}
|
|
78
|
+
// A heading IS a labelled section — `GMenuModel` has no title, which is exactly why
|
|
79
|
+
// the browser element's `menu-title` is a shorthand for one. With no title the
|
|
80
|
+
// loose items are appended one by one, so the menu reads the same without one.
|
|
81
|
+
if (title.length > 0) {
|
|
82
|
+
const section = new Gio.Menu();
|
|
83
|
+
for (const label of loose) section.append(label, actionOf(label));
|
|
84
|
+
menu.append_section(title, section);
|
|
85
|
+
} else {
|
|
86
|
+
for (const label of loose) menu.append(label, actionOf(label));
|
|
87
|
+
}
|
|
88
|
+
return menu;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private _apply(): void {
|
|
92
|
+
if (!this._anchor) return;
|
|
93
|
+
// Rebuilt rather than mutated: a `Gio.Menu` is immutable to the popover once shown,
|
|
94
|
+
// and `gtk_popover_menu_set_menu_model` REPLACES the whole stack on every call
|
|
95
|
+
// (gtkpopovermenu.c:838-852).
|
|
96
|
+
const previous = this._popover;
|
|
97
|
+
this._popover = Gtk.PopoverMenu.new_from_model(this._buildMenu(this.args.menuTitle as string));
|
|
98
|
+
this._popover.set_parent(this._anchor);
|
|
99
|
+
previous?.unparent();
|
|
100
|
+
// The four GtkPositionType values, by name, so both renderers read one control.
|
|
101
|
+
const positions: Record<string, Gtk.PositionType> = {
|
|
102
|
+
bottom: Gtk.PositionType.BOTTOM,
|
|
103
|
+
top: Gtk.PositionType.TOP,
|
|
104
|
+
start: Gtk.PositionType.LEFT,
|
|
105
|
+
end: Gtk.PositionType.RIGHT,
|
|
106
|
+
};
|
|
107
|
+
this._popover.position = positions[this.args.position as string] ?? Gtk.PositionType.BOTTOM;
|
|
108
|
+
// `GtkPopover` has no align property: alignment is the parent widget's `halign`, which
|
|
109
|
+
// is why the browser element carries an `align` attribute of its own.
|
|
110
|
+
if (this._anchor) {
|
|
111
|
+
this._anchor.halign = (this.args.align as string) === 'end' ? Gtk.Align.END : Gtk.Align.START;
|
|
112
|
+
}
|
|
113
|
+
this._popover.autohide = this.args.autohide as boolean;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
GObject.type_ensure(PopoverMenuStory.$gtype);
|
|
118
|
+
|
|
119
|
+
export const PopoverMenuStories: StoryModule = { stories: [PopoverMenuStory] };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// <gtk-popover> story: the plain content popover. Shared, renderer-agnostic metadata for the
|
|
2
|
+
// GTK renderer (popover.story.ts) and the browser one
|
|
3
|
+
// (browser/layout/popover.web.ts), so both expose identical controls.
|
|
4
|
+
|
|
5
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
6
|
+
|
|
7
|
+
export const popoverMeta: StoryMeta = {
|
|
8
|
+
title: 'Layout/Popover',
|
|
9
|
+
description:
|
|
10
|
+
'Gtk.Popover — the bubble-like surface. No model and no menu: it holds whatever widget you ' +
|
|
11
|
+
'put in it, and everything here is about WHERE it appears and WHEN it goes away. ' +
|
|
12
|
+
'`autohide` off is entry completion: the list follows the typing and the caret never leaves.',
|
|
13
|
+
controls: [
|
|
14
|
+
{
|
|
15
|
+
name: 'position',
|
|
16
|
+
label: 'Position',
|
|
17
|
+
type: ControlType.SELECT,
|
|
18
|
+
options: [
|
|
19
|
+
{ label: 'Bottom', value: 'bottom' },
|
|
20
|
+
{ label: 'Top', value: 'top' },
|
|
21
|
+
{ label: 'Start', value: 'start' },
|
|
22
|
+
{ label: 'End', value: 'end' },
|
|
23
|
+
],
|
|
24
|
+
defaultValue: 'bottom',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'align',
|
|
28
|
+
label: 'Align',
|
|
29
|
+
type: ControlType.SELECT,
|
|
30
|
+
options: [
|
|
31
|
+
{ label: 'Start', value: 'start' },
|
|
32
|
+
{ label: 'End', value: 'end' },
|
|
33
|
+
],
|
|
34
|
+
defaultValue: 'start',
|
|
35
|
+
},
|
|
36
|
+
{ name: 'autohide', label: 'Dismiss on outside click', type: ControlType.BOOLEAN, defaultValue: true },
|
|
37
|
+
],
|
|
38
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Gtk.Popover — the bubble-like surface, with arbitrary content.
|
|
2
|
+
// original implementation.
|
|
3
|
+
|
|
4
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
5
|
+
import GObject from 'gi://GObject?version=2.0';
|
|
6
|
+
import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
|
|
7
|
+
import { popoverMeta } from './popover.meta.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Story: a Gtk.Popover over a button, holding a box of labels.
|
|
11
|
+
*
|
|
12
|
+
* `autohide` is the control worth trying: with it off the popover takes no grab
|
|
13
|
+
* (gtkpopover.c:1245-1247), so an outside click and an Escape stop dismissing it — which is
|
|
14
|
+
* what an entry's completion list needs.
|
|
15
|
+
*/
|
|
16
|
+
export class PopoverStory extends StoryWidget {
|
|
17
|
+
private _anchor: Gtk.Button | null = null;
|
|
18
|
+
private _popover: Gtk.Popover | null = null;
|
|
19
|
+
|
|
20
|
+
static {
|
|
21
|
+
GObject.registerClass({ GTypeName: 'AdwStorybookPopover' }, PopoverStory);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
super(StoryWidget.fromMeta(PopoverStory.getMetadata(), 'Default'));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static getMetadata(): StoryMeta {
|
|
29
|
+
return { ...popoverMeta, component: Gtk.Popover.$gtype };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
initialize(): void {
|
|
33
|
+
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 6 });
|
|
34
|
+
box.append(new Gtk.Label({ label: 'Anything you like' }));
|
|
35
|
+
box.append(new Gtk.Label({ label: 'in here' }));
|
|
36
|
+
|
|
37
|
+
this._anchor = new Gtk.Button({ label: 'Show popover', halign: Gtk.Align.CENTER });
|
|
38
|
+
this._popover = new Gtk.Popover({ child: box });
|
|
39
|
+
this._popover.set_parent(this._anchor);
|
|
40
|
+
this._apply();
|
|
41
|
+
this.addContent(this._anchor);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateArgs(_args: StoryArgs): void {
|
|
45
|
+
this._apply();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _apply(): void {
|
|
49
|
+
if (!this._popover) return;
|
|
50
|
+
const positions: Record<string, Gtk.PositionType> = {
|
|
51
|
+
bottom: Gtk.PositionType.BOTTOM,
|
|
52
|
+
top: Gtk.PositionType.TOP,
|
|
53
|
+
start: Gtk.PositionType.LEFT,
|
|
54
|
+
end: Gtk.PositionType.RIGHT,
|
|
55
|
+
};
|
|
56
|
+
this._popover.position = positions[this.args.position as string] ?? Gtk.PositionType.BOTTOM;
|
|
57
|
+
if (this._anchor) {
|
|
58
|
+
this._anchor.halign = (this.args.align as string) === 'end' ? Gtk.Align.END : Gtk.Align.START;
|
|
59
|
+
}
|
|
60
|
+
this._popover.autohide = this.args.autohide as boolean;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
GObject.type_ensure(PopoverStory.$gtype);
|
|
65
|
+
|
|
66
|
+
export const PopoverStories: StoryModule = { stories: [PopoverStory] };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Shared, renderer-agnostic metadata for the Revealer story. Imported by the GTK renderer
|
|
2
|
+
// (revealer.story.ts) and the browser renderer (browser/layout/revealer.web.ts), so both
|
|
3
|
+
// expose identical controls.
|
|
4
|
+
|
|
5
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
6
|
+
|
|
7
|
+
export const revealerMeta: StoryMeta = {
|
|
8
|
+
title: 'Layout/Revealer',
|
|
9
|
+
description:
|
|
10
|
+
'Gtk.Revealer — shows and hides its child with an animation. The transition is one of ' +
|
|
11
|
+
'fourteen nicks and it is not only an opacity change: a slide scales the box along one ' +
|
|
12
|
+
'axis while allocating the child at its UNSCALED size, and a swing folds it in with ' +
|
|
13
|
+
'sin (π · pos / 2). Libadwaita styles no revealer node of its own, so everything here is ' +
|
|
14
|
+
'GTK behaviour the browser element ports.',
|
|
15
|
+
controls: [
|
|
16
|
+
{
|
|
17
|
+
name: 'transitionType',
|
|
18
|
+
label: 'Transition',
|
|
19
|
+
type: ControlType.SELECT,
|
|
20
|
+
options: [
|
|
21
|
+
{ label: 'Slide down (the default)', value: 'slide-down' },
|
|
22
|
+
{ label: 'Slide up', value: 'slide-up' },
|
|
23
|
+
{ label: 'Slide left', value: 'slide-left' },
|
|
24
|
+
{ label: 'Slide right', value: 'slide-right' },
|
|
25
|
+
{ label: 'Crossfade', value: 'crossfade' },
|
|
26
|
+
{ label: 'Fade + slide down', value: 'fade-slide-down' },
|
|
27
|
+
{ label: 'Swing down (fold)', value: 'swing-down' },
|
|
28
|
+
{ label: 'Swing right (fold)', value: 'swing-right' },
|
|
29
|
+
{ label: 'None', value: 'none' },
|
|
30
|
+
],
|
|
31
|
+
defaultValue: 'slide-down',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'transitionDuration',
|
|
35
|
+
label: 'Duration (ms)',
|
|
36
|
+
type: ControlType.RANGE,
|
|
37
|
+
min: 0,
|
|
38
|
+
max: 800,
|
|
39
|
+
step: 50,
|
|
40
|
+
defaultValue: 250,
|
|
41
|
+
},
|
|
42
|
+
{ name: 'revealChild', label: 'Reveal', type: ControlType.BOOLEAN, defaultValue: true },
|
|
43
|
+
],
|
|
44
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Gtk.Revealer — one of the fourteen transitions, driven by the shared controls.
|
|
2
|
+
// original implementation.
|
|
3
|
+
|
|
4
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
5
|
+
import GObject from 'gi://GObject?version=2.0';
|
|
6
|
+
import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
|
|
7
|
+
import { revealerMeta } from './revealer.meta.js';
|
|
8
|
+
|
|
9
|
+
/** The story arg is the transition's GIR nick, which is also what `Gtk.Revealer` takes. */
|
|
10
|
+
const TRANSITIONS: Record<string, Gtk.RevealerTransitionType> = {
|
|
11
|
+
none: Gtk.RevealerTransitionType.NONE,
|
|
12
|
+
crossfade: Gtk.RevealerTransitionType.CROSSFADE,
|
|
13
|
+
'slide-right': Gtk.RevealerTransitionType.SLIDE_RIGHT,
|
|
14
|
+
'slide-left': Gtk.RevealerTransitionType.SLIDE_LEFT,
|
|
15
|
+
'slide-up': Gtk.RevealerTransitionType.SLIDE_UP,
|
|
16
|
+
'slide-down': Gtk.RevealerTransitionType.SLIDE_DOWN,
|
|
17
|
+
'swing-right': Gtk.RevealerTransitionType.SWING_RIGHT,
|
|
18
|
+
'swing-left': Gtk.RevealerTransitionType.SWING_LEFT,
|
|
19
|
+
'swing-up': Gtk.RevealerTransitionType.SWING_UP,
|
|
20
|
+
'swing-down': Gtk.RevealerTransitionType.SWING_DOWN,
|
|
21
|
+
'fade-slide-right': Gtk.RevealerTransitionType.FADE_SLIDE_RIGHT,
|
|
22
|
+
'fade-slide-left': Gtk.RevealerTransitionType.FADE_SLIDE_LEFT,
|
|
23
|
+
'fade-slide-up': Gtk.RevealerTransitionType.FADE_SLIDE_UP,
|
|
24
|
+
'fade-slide-down': Gtk.RevealerTransitionType.FADE_SLIDE_DOWN,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Story: a Gtk.Revealer over a box, so every transition has room to move. */
|
|
28
|
+
export class RevealerStory extends StoryWidget {
|
|
29
|
+
private _revealer: Gtk.Revealer | null = null;
|
|
30
|
+
|
|
31
|
+
static {
|
|
32
|
+
GObject.registerClass({ GTypeName: 'AdwStorybookRevealer' }, RevealerStory);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
constructor() {
|
|
36
|
+
super(StoryWidget.fromMeta(RevealerStory.getMetadata(), 'Default'));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static getMetadata(): StoryMeta {
|
|
40
|
+
return { ...revealerMeta, component: Gtk.Revealer.$gtype };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initialize(): void {
|
|
44
|
+
const content = new Gtk.Box({
|
|
45
|
+
orientation: Gtk.Orientation.VERTICAL,
|
|
46
|
+
spacing: 6,
|
|
47
|
+
margin_top: 12,
|
|
48
|
+
margin_bottom: 12,
|
|
49
|
+
margin_start: 12,
|
|
50
|
+
margin_end: 12,
|
|
51
|
+
});
|
|
52
|
+
content.append(new Gtk.Label({ label: 'The revealed child' }));
|
|
53
|
+
const hint = new Gtk.Label({ label: 'Drag the controls to change the transition' });
|
|
54
|
+
hint.add_css_class('dim-label');
|
|
55
|
+
content.append(hint);
|
|
56
|
+
|
|
57
|
+
this._revealer = new Gtk.Revealer();
|
|
58
|
+
this._revealer.set_child(content);
|
|
59
|
+
this._apply();
|
|
60
|
+
this.addContent(this._revealer);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
updateArgs(_args: StoryArgs): void {
|
|
64
|
+
this._apply();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private _apply(): void {
|
|
68
|
+
if (!this._revealer) return;
|
|
69
|
+
// `effective_transition` is not reachable from outside, so the story sets the nick the
|
|
70
|
+
// property takes and lets GTK mirror it for an RTL direction.
|
|
71
|
+
this._revealer.transition_type = TRANSITIONS[String(this.args.transitionType)];
|
|
72
|
+
this._revealer.transition_duration = Number(this.args.transitionDuration);
|
|
73
|
+
this._revealer.reveal_child = this.args.revealChild as boolean;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
GObject.type_ensure(RevealerStory.$gtype);
|
|
78
|
+
|
|
79
|
+
export const RevealerStories: StoryModule = { stories: [RevealerStory] };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Shared, renderer-agnostic metadata for the Scrollbar story. Imported by the GTK renderer
|
|
2
|
+
// (layout/scrollbar.story.ts) and the browser renderer (browser/layout/scrollbar.web.ts), so
|
|
3
|
+
// both expose identical controls.
|
|
4
|
+
|
|
5
|
+
// THE CONTROL NAMES ARE CAMEL-CASE ARG NAMES, not the adjustment's GIR field spellings: the
|
|
6
|
+
// control panel's reader takes `name` as an identifier
|
|
7
|
+
// (`scripts/check-storybook-control-parity.mjs` reads `\bname:\s*'([A-Za-z0-9_]+)'`), and
|
|
8
|
+
// each renderer writes it into the adjustment whose own field it is.
|
|
9
|
+
|
|
10
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
11
|
+
|
|
12
|
+
export const scrollbarMeta: StoryMeta = {
|
|
13
|
+
title: 'Layout/Scrollbar',
|
|
14
|
+
description:
|
|
15
|
+
'Gtk.Scrollbar — a trough and a slider, positioned by a GtkAdjustment. The slider is ' +
|
|
16
|
+
'page_size over the whole range long and sits at the position over the SCROLLABLE range, ' +
|
|
17
|
+
'which is why the two numbers it is made of do not share a denominator.',
|
|
18
|
+
controls: [
|
|
19
|
+
{
|
|
20
|
+
name: 'orientation',
|
|
21
|
+
label: 'Orientation',
|
|
22
|
+
type: ControlType.SELECT,
|
|
23
|
+
options: [
|
|
24
|
+
{ label: 'Horizontal', value: 'horizontal' },
|
|
25
|
+
{ label: 'Vertical', value: 'vertical' },
|
|
26
|
+
],
|
|
27
|
+
defaultValue: 'vertical',
|
|
28
|
+
},
|
|
29
|
+
{ name: 'upper', label: 'Adjustment upper', type: ControlType.NUMBER, defaultValue: 400 },
|
|
30
|
+
{ name: 'pageSize', label: 'Adjustment page size', type: ControlType.NUMBER, defaultValue: 120 },
|
|
31
|
+
{ name: 'value', label: 'Adjustment value', type: ControlType.NUMBER, defaultValue: 80 },
|
|
32
|
+
],
|
|
33
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Gtk.Scrollbar — one adjustment, drawn as a trough and a slider.
|
|
2
|
+
// original implementation.
|
|
3
|
+
|
|
4
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
5
|
+
import GObject from 'gi://GObject?version=2.0';
|
|
6
|
+
import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
|
|
7
|
+
import { scrollbarMeta } from './scrollbar.meta.js';
|
|
8
|
+
|
|
9
|
+
/** Story: a Gtk.Scrollbar over one adjustment, with every adjustment field bound to args. */
|
|
10
|
+
export class ScrollbarStory extends StoryWidget {
|
|
11
|
+
private _scrollbar: Gtk.Scrollbar | null = null;
|
|
12
|
+
|
|
13
|
+
static {
|
|
14
|
+
GObject.registerClass({ GTypeName: 'AdwStorybookScrollbar' }, ScrollbarStory);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
super(StoryWidget.fromMeta(ScrollbarStory.getMetadata(), 'Default'));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static getMetadata(): StoryMeta {
|
|
22
|
+
return { ...scrollbarMeta, component: Gtk.Scrollbar.$gtype };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
initialize(): void {
|
|
26
|
+
// `GtkScrollbar` has no adjustment of its own — unlike `GtkRange`, it makes none — so
|
|
27
|
+
// the construct bag is where one arrives (gtkscrollbar.c:409-420).
|
|
28
|
+
this._scrollbar = new Gtk.Scrollbar({
|
|
29
|
+
adjustment: new Gtk.Adjustment({ step_increment: 10, page_increment: 80 }),
|
|
30
|
+
});
|
|
31
|
+
this._apply();
|
|
32
|
+
this.addContent(this._scrollbar);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
updateArgs(_args: StoryArgs): void {
|
|
36
|
+
this._apply();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private _apply(): void {
|
|
40
|
+
const scrollbar = this._scrollbar;
|
|
41
|
+
if (!scrollbar) return;
|
|
42
|
+
scrollbar.orientation =
|
|
43
|
+
(this.args.orientation as string) === 'horizontal' ? Gtk.Orientation.HORIZONTAL : Gtk.Orientation.VERTICAL;
|
|
44
|
+
const adjustment = scrollbar.get_adjustment();
|
|
45
|
+
if (!adjustment) return;
|
|
46
|
+
// `configure` is all six at once, "so that the change notifications are compressed into
|
|
47
|
+
// one" — the GIR's own sentence for the method the C prefers over the setters.
|
|
48
|
+
adjustment.configure(
|
|
49
|
+
Number(this.args.value),
|
|
50
|
+
0,
|
|
51
|
+
Number(this.args.upper),
|
|
52
|
+
adjustment.step_increment,
|
|
53
|
+
adjustment.page_increment,
|
|
54
|
+
Number(this.args.pageSize),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
GObject.type_ensure(ScrollbarStory.$gtype);
|
|
60
|
+
|
|
61
|
+
export const ScrollbarStories: StoryModule = { stories: [ScrollbarStory] };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Shared, renderer-agnostic metadata for the Scrolled Window story. Imported by the GTK
|
|
2
|
+
// renderer (layout/scrolled-window.story.ts) and the browser renderer
|
|
3
|
+
// (browser/layout/scrolled-window.web.ts), so both expose identical controls.
|
|
4
|
+
//
|
|
5
|
+
// THE CONTROL NAMES ARE CAMEL-CASE ARG NAMES, not GIR property spellings: the control
|
|
6
|
+
// panel's reader takes `name` as an identifier (`scripts/check-storybook-control-parity.mjs`
|
|
7
|
+
// reads `\bname:\s*'([A-Za-z0-9_]+)'`), and each renderer writes it onto the property
|
|
8
|
+
// whose own name it is — `hscrollbar-policy` here.
|
|
9
|
+
|
|
10
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
11
|
+
|
|
12
|
+
export const scrolledWindowMeta: StoryMeta = {
|
|
13
|
+
title: 'Layout/ScrolledWindow',
|
|
14
|
+
description:
|
|
15
|
+
'Gtk.ScrolledWindow — one child, two adjustments, and a scrollbar per edge that can ' +
|
|
16
|
+
'actually scroll. The policies decide whether a bar appears, window-placement which ' +
|
|
17
|
+
'edge it takes, and overlay-scrolling turns the bars into the auto-hiding indicators ' +
|
|
18
|
+
'GNOME draws over the content.',
|
|
19
|
+
controls: [
|
|
20
|
+
{
|
|
21
|
+
name: 'hPolicy',
|
|
22
|
+
label: 'Horizontal policy',
|
|
23
|
+
type: ControlType.SELECT,
|
|
24
|
+
options: [
|
|
25
|
+
{ label: 'Automatic', value: 'automatic' },
|
|
26
|
+
{ label: 'Always', value: 'always' },
|
|
27
|
+
{ label: 'Never', value: 'never' },
|
|
28
|
+
],
|
|
29
|
+
defaultValue: 'automatic',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'vPolicy',
|
|
33
|
+
label: 'Vertical policy',
|
|
34
|
+
type: ControlType.SELECT,
|
|
35
|
+
options: [
|
|
36
|
+
{ label: 'Automatic', value: 'automatic' },
|
|
37
|
+
{ label: 'Always', value: 'always' },
|
|
38
|
+
{ label: 'Never', value: 'never' },
|
|
39
|
+
],
|
|
40
|
+
defaultValue: 'automatic',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'placement',
|
|
44
|
+
label: 'Window placement',
|
|
45
|
+
type: ControlType.SELECT,
|
|
46
|
+
options: [
|
|
47
|
+
{ label: 'Top left', value: 'top-left' },
|
|
48
|
+
{ label: 'Top right', value: 'top-right' },
|
|
49
|
+
{ label: 'Bottom left', value: 'bottom-left' },
|
|
50
|
+
{ label: 'Bottom right', value: 'bottom-right' },
|
|
51
|
+
],
|
|
52
|
+
defaultValue: 'top-left',
|
|
53
|
+
},
|
|
54
|
+
{ name: 'frame', label: 'Frame', type: ControlType.BOOLEAN, defaultValue: false },
|
|
55
|
+
{ name: 'overlayScrolling', label: 'Overlay scrolling', type: ControlType.BOOLEAN, defaultValue: true },
|
|
56
|
+
],
|
|
57
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Gtk.ScrolledWindow — a tall column in a window that scrolls it.
|
|
2
|
+
// original implementation.
|
|
3
|
+
|
|
4
|
+
import Gtk from 'gi://Gtk?version=4.0';
|
|
5
|
+
import GObject from 'gi://GObject?version=2.0';
|
|
6
|
+
import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
|
|
7
|
+
import { scrolledWindowMeta } from './scrolled-window.meta.js';
|
|
8
|
+
|
|
9
|
+
/** `GtkPolicyType`'s four nicks as the constants, and `GtkCornerType`'s four. */
|
|
10
|
+
const POLICIES: Record<string, Gtk.PolicyType> = {
|
|
11
|
+
automatic: Gtk.PolicyType.AUTOMATIC,
|
|
12
|
+
always: Gtk.PolicyType.ALWAYS,
|
|
13
|
+
never: Gtk.PolicyType.NEVER,
|
|
14
|
+
};
|
|
15
|
+
const PLACEMENTS: Record<string, Gtk.CornerType> = {
|
|
16
|
+
'top-left': Gtk.CornerType.TOP_LEFT,
|
|
17
|
+
'top-right': Gtk.CornerType.TOP_RIGHT,
|
|
18
|
+
'bottom-left': Gtk.CornerType.BOTTOM_LEFT,
|
|
19
|
+
'bottom-right': Gtk.CornerType.BOTTOM_RIGHT,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Story: a Gtk.ScrolledWindow over a column of labels, with every policy bound to args. */
|
|
23
|
+
export class ScrolledWindowStory extends StoryWidget {
|
|
24
|
+
private _window: Gtk.ScrolledWindow | null = null;
|
|
25
|
+
|
|
26
|
+
static {
|
|
27
|
+
GObject.registerClass({ GTypeName: 'AdwStorybookScrolledWindow' }, ScrolledWindowStory);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
super(StoryWidget.fromMeta(ScrolledWindowStory.getMetadata(), 'Default'));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static getMetadata(): StoryMeta {
|
|
35
|
+
return { ...scrolledWindowMeta, component: Gtk.ScrolledWindow.$gtype };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
initialize(): void {
|
|
39
|
+
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 8 });
|
|
40
|
+
for (let i = 1; i <= 16; i++) {
|
|
41
|
+
box.append(new Gtk.Label({ label: `Row ${i}` }));
|
|
42
|
+
}
|
|
43
|
+
this._window = new Gtk.ScrolledWindow({
|
|
44
|
+
child: box,
|
|
45
|
+
// An allocation, which is what GTK hands this widget and what makes it scroll
|
|
46
|
+
// rather than grow: `min_content_height` is one of the two size requests the C
|
|
47
|
+
// answers with the child's minimum.
|
|
48
|
+
min_content_height: 240,
|
|
49
|
+
halign: Gtk.Align.CENTER,
|
|
50
|
+
});
|
|
51
|
+
this._apply();
|
|
52
|
+
this.addContent(this._window);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
updateArgs(_args: StoryArgs): void {
|
|
56
|
+
this._apply();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private _apply(): void {
|
|
60
|
+
const window = this._window;
|
|
61
|
+
if (!window) return;
|
|
62
|
+
window.set_policy(
|
|
63
|
+
POLICIES[this.args.hPolicy as string] ?? Gtk.PolicyType.AUTOMATIC,
|
|
64
|
+
POLICIES[this.args.vPolicy as string] ?? Gtk.PolicyType.AUTOMATIC,
|
|
65
|
+
);
|
|
66
|
+
window.set_placement(PLACEMENTS[this.args.placement as string] ?? Gtk.CornerType.TOP_LEFT);
|
|
67
|
+
window.has_frame = this.args.frame as boolean;
|
|
68
|
+
window.set_overlay_scrolling(this.args.overlayScrolling as boolean);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
GObject.type_ensure(ScrolledWindowStory.$gtype);
|
|
73
|
+
|
|
74
|
+
export const ScrolledWindowStories: StoryModule = { stories: [ScrolledWindowStory] };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Shared, renderer-agnostic metadata for the Separator story. Imported by the GTK
|
|
2
|
+
// renderer (separator.story.ts) and the browser renderer (browser/layout/separator.web.ts),
|
|
3
|
+
// so both expose identical controls.
|
|
4
|
+
|
|
5
|
+
import { ControlType, type StoryMeta } from '@gjsify/stories';
|
|
6
|
+
|
|
7
|
+
export const separatorMeta: StoryMeta = {
|
|
8
|
+
title: 'Layout/Separator',
|
|
9
|
+
description:
|
|
10
|
+
'Gtk.Separator — a one-pixel rule between two groups of widgets. Libadwaita ships no Adw.Separator; ' +
|
|
11
|
+
'it only styles the GTK one, and the .spacer style class turns the rule into an empty 12px gap.',
|
|
12
|
+
controls: [
|
|
13
|
+
{
|
|
14
|
+
name: 'orientation',
|
|
15
|
+
label: 'Orientation',
|
|
16
|
+
type: ControlType.SELECT,
|
|
17
|
+
options: [
|
|
18
|
+
{ label: 'Horizontal', value: 'horizontal' },
|
|
19
|
+
{ label: 'Vertical', value: 'vertical' },
|
|
20
|
+
],
|
|
21
|
+
defaultValue: 'horizontal',
|
|
22
|
+
},
|
|
23
|
+
{ name: 'spacer', label: 'Spacer (draws nothing)', type: ControlType.BOOLEAN, defaultValue: false },
|
|
24
|
+
],
|
|
25
|
+
};
|