add remaining widgets

This commit is contained in:
Aylur
2023-08-15 14:15:58 +02:00
parent 87a7f0cf5f
commit 2bf9e59c87
18 changed files with 967 additions and 136 deletions
+11
View File
@@ -12,6 +12,17 @@
<file>widgets/box.js</file>
<file>widgets/eventbox.js</file>
<file>widgets/centerbox.js</file>
<file>widgets/icon.js</file>
<file>widgets/label.js</file>
<file>widgets/button.js</file>
<file>widgets/slider.js</file>
<file>widgets/scrollable.js</file>
<file>widgets/stack.js</file>
<file>widgets/overlay.js</file>
<file>widgets/revealer.js</file>
<file>widgets/progressbar.js</file>
<file>widgets/menu.js</file>
<file>widgets/entry.js</file>
<file>service/service.js</file>
<file>service/apps.js</file>
+12 -6
View File
@@ -162,18 +162,24 @@ export function timeout(ms: number, callback: () => void) {
});
}
export function runCmd(cmd: string | ((...args: any[]) => void), ...args: any[]) {
if (typeof cmd !== 'string' && typeof cmd !== 'function')
return warning('Command has to be string or function');
export function runCmd(cmd: string | ((...args: any[]) => boolean), ...args: any[]) {
if (typeof cmd !== 'string' && typeof cmd !== 'function') {
warning('Command has to be string or function');
return false;
}
if (!cmd)
return;
return false;
if (typeof cmd === 'string')
return GLib.spawn_command_line_async(cmd);
if (typeof cmd === 'string') {
GLib.spawn_command_line_async(cmd);
return true;
}
if (typeof cmd === 'function')
return cmd(...args);
return false;
}
export function getConfig() {
+29 -4
View File
@@ -1,9 +1,21 @@
import Gtk from 'gi://Gtk?version=3.0';
import { typecheck, error, warning, interval } from './utils.js';
import * as Widgets from './widgets.js';
import { constructor } from './widgets/shared.js';
import Box from './widgets/box.js';
import EventBox from './widgets/eventbox.js';
import CenterBox from './widgets/centerbox.js';
import EventBox from './widgets/eventbox.js';
import Icon from './widgets/icon.js';
import Label from './widgets/label.js';
import Button from './widgets/button.js';
import Slider from './widgets/slider.js';
import Scrollable from './widgets/scrollable.js';
import Stack from './widgets/stack.js';
import Overlay from './widgets/overlay.js';
import Revealer from './widgets/revealer.js';
import ProgressBar from './widgets/progressbar.js';
import Entry from './widgets/entry.js';
import { Menu, MenuItem } from './widgets/menu.js';
interface ServiceAPI {
instance: {
@@ -193,6 +205,19 @@ export default function Widget(params: Widget | string | (() => Gtk.Widget) | Gt
}
Widget.widgets = widgets;
Widget.Box = Box;
Widget.EventBox = EventBox;
Widget.CenterBox = CenterBox;
Widget.Box = (params: object) => constructor(Box, params);
Widget.CenterBox = (params: object) => constructor(CenterBox, params);
Widget.EventBox = (params: object) => constructor(EventBox, params);
Widget.Icon = (params: object) => constructor(Icon, params);
Widget.Label = (params: object) => constructor(Label, params);
Widget.Button = (params: object) => constructor(Button, params);
Widget.Slider = (params: object) => constructor(Slider, params);
Widget.Stack = (params: object) => constructor(Stack, params);
Widget.Scrollable = (params: object) => constructor(Scrollable, params);
Widget.Overlay = (params: object) => constructor(Overlay, params);
Widget.Revealer = (params: object) => constructor(Revealer, params);
Widget.ProgressBar = (params: object) => constructor(ProgressBar, params);
Widget.Menu = (params: object) => constructor(Menu, params);
Widget.MenuItem = (params: object) => constructor(MenuItem, params);
Widget.Entry = (params: object) => constructor(Entry, params);
Widget.Widget = ({ type, ...params }: { type: { new(...args: any[]): Gtk.Widget } }) => constructor(type, params);
+7 -26
View File
@@ -1,60 +1,41 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import { separateCommon, parseCommon, CommonParams } from './shared.js';
interface Params extends CommonParams {
children?: Gtk.Widget[]
[key: string]: any
}
export class Box extends Gtk.Box {
export default class Box extends Gtk.Box {
static {
GObject.registerClass({
GTypeName: 'AgsBox',
Properties: {
'vertical': GObject.ParamSpec.boolean(
'vertical', 'Vertical', 'Vertical',
GObject.ParamFlags.READWRITE,
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
false,
),
},
}, this);
}
constructor({ children, ...params }: Params = {}) {
const [common, rest] = separateCommon(params);
constructor({ children, ...rest }: { children?: Gtk.Widget[] | null }) {
super(rest);
parseCommon(this, common);
if (children)
this.children = children;
}
get children() { return this.get_children(); }
set children(children: Gtk.Widget[] | null) {
this.get_children().forEach(ch => ch.destroy());
this.get_children().forEach(ch => this.remove(ch));
if (!children)
return;
children.forEach(w => {
if (w)
this.add(w);
});
children.forEach(w => w && this.add(w));
this.show_all();
}
get children() {
return this.get_children();
}
get vertical() {
return this.orientation === Gtk.Orientation.VERTICAL;
}
get vertical() { return this.orientation === Gtk.Orientation.VERTICAL; }
set vertical(vertical) {
this.orientation = vertical
? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL;
}
}
export default (params: object) => new Box(params);
+102
View File
@@ -0,0 +1,102 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import Gdk from 'gi://Gdk?version=3.0';
import { runCmd } from '../utils.js';
export default class Button extends Gtk.Button {
static {
GObject.registerClass({ GTypeName: 'AgsButton' }, this);
}
onClicked: string | ((...args: any[]) => boolean);
onPrimaryClick: string | ((...args: any[]) => boolean);
onSecondaryClick: string | ((...args: any[]) => boolean);
onMiddleClick: string | ((...args: any[]) => boolean);
onPrimaryClickRelease: string | ((...args: any[]) => boolean);
onSecondaryClickRelease: string | ((...args: any[]) => boolean);
onMiddleClickRelease: string | ((...args: any[]) => boolean);
onScrollUp: string | ((...args: any[]) => boolean);
onScrollDown: string | ((...args: any[]) => boolean);
constructor(params: object | string) {
const {
onClicked = '',
onPrimaryClick = '',
onSecondaryClick = '',
onMiddleClick = '',
onPrimaryClickRelease = '',
onSecondaryClickRelease = '',
onMiddleClickRelease = '',
onScrollUp = '',
onScrollDown = '',
...rest
} = params as { [key: string]: any };
super(typeof params === 'string' ? { label: params } : rest);
this.add_events(Gdk.EventMask.SCROLL_MASK);
this.onClicked = onClicked;
this.onPrimaryClick = onPrimaryClick;
this.onSecondaryClick = onSecondaryClick;
this.onMiddleClick = onMiddleClick;
this.onPrimaryClickRelease = onPrimaryClickRelease;
this.onSecondaryClickRelease = onSecondaryClickRelease;
this.onMiddleClickRelease = onMiddleClickRelease;
this.onScrollUp = onScrollUp;
this.onScrollDown = onScrollDown;
}
// @ts-ignore
get child() { return this.get_child(); }
set child(child: Gtk.Widget) {
const widget = this.get_child();
if (widget)
this.remove(widget);
if (child)
this.add(child);
}
vfunc_clicked(): void {
runCmd(this.onClicked, this);
}
vfunc_button_press_event(event: Gdk.EventButton): boolean {
super.vfunc_button_press_event(event);
this.set_state_flags(Gtk.StateFlags.ACTIVE, false);
if (event.button === Gdk.BUTTON_PRIMARY)
return runCmd(this.onPrimaryClick, this, event);
else if (event.button === Gdk.BUTTON_SECONDARY)
return runCmd(this.onSecondaryClick, this, event);
else if (event.button === Gdk.BUTTON_MIDDLE)
return runCmd(this.onMiddleClick, this, event);
return false;
}
vfunc_button_release_event(event: Gdk.EventButton): boolean {
super.vfunc_button_release_event(event);
this.unset_state_flags(Gtk.StateFlags.ACTIVE);
if (event.button === Gdk.BUTTON_PRIMARY)
return runCmd(this.onPrimaryClickRelease, this, event);
else if (event.button === Gdk.BUTTON_SECONDARY)
return runCmd(this.onSecondaryClickRelease, this, event);
else if (event.button === Gdk.BUTTON_MIDDLE)
return runCmd(this.onMiddleClickRelease, this, event);
return false;
}
vfunc_scroll_event(event: Gdk.EventScroll): boolean {
if (event.direction === Gdk.ScrollDirection.UP)
return runCmd(this.onScrollUp, this, event);
else if (event.direction === Gdk.ScrollDirection.DOWN)
return runCmd(this.onScrollDown, this, event);
return false;
}
}
+49 -36
View File
@@ -1,47 +1,76 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import { Box } from './box.js';
import Box from './box.js';
class CenterBox extends Box {
export default class CenterBox extends Box {
static {
GObject.registerClass({
GTypeName: 'AgsCenterBox',
Properties: {
'start-widget': GObject.ParamSpec.object(
'start-widget', 'Start Widget', 'Start Widget',
GObject.ParamFlags.READWRITE,
GObject.Object.$gtype,
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
Gtk.Widget.$gtype,
),
'center-widget': GObject.ParamSpec.object(
'center-widget', 'Center Widget', 'Center Widget',
GObject.ParamFlags.READWRITE,
GObject.Object.$gtype,
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
Gtk.Widget.$gtype,
),
'end-widget': GObject.ParamSpec.object(
'end-widget', 'End Widget', 'End Widget',
GObject.ParamFlags.READWRITE,
GObject.Object.$gtype,
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
Gtk.Widget.$gtype,
),
},
}, this);
}
_start_widget!: Gtk.Widget | null;
_end_widget!: Gtk.Widget | null;
set children(children: Gtk.Widget[] | null) {
this.get_children().forEach(ch => this.remove(ch));
get start_widget() { return this._start_widget || null; }
set start_widget(child: Gtk.Widget | null) {
if (this._start_widget)
this.remove(this._start_widget);
if (!child) {
this._start_widget = null;
if (!children)
return;
if (children[0])
this.start_widget = children[0];
if (children[1])
this.center_widget = children[1];
if (children[2])
this.end_widget = children[2];
}
_start!: Gtk.Widget | null;
get start_widget() { return this._start || null; }
set start_widget(child: Gtk.Widget | null) {
print('test', this._start);
if (this._start)
this.remove(this._start);
this._start = child;
if (!child)
return;
}
this._start_widget = child;
this.pack_start(child, true, true, 0);
print('packed');
this.show_all();
}
_end!: Gtk.Widget | null;
get end_widget() { return this._end || null; }
set end_widget(child: Gtk.Widget | null) {
if (this._end)
this.remove(this._end);
this._end = child;
if (!child)
return;
this.pack_end(child, true, true, 0);
this.show_all();
}
get center_widget() { return this.get_center_widget(); }
@@ -54,20 +83,4 @@ class CenterBox extends Box {
this.set_center_widget(child);
}
get end_widget() { return this._end_widget || null; }
set end_widget(child: Gtk.Widget | null) {
if (this._end_widget)
this.remove(this._end_widget);
if (!child) {
this._end_widget = null;
return;
}
this._end_widget = child;
this.pack_end(child, true, true, 0);
}
}
export default (params: object) => new CenterBox(params);
+35
View File
@@ -0,0 +1,35 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import { runCmd } from '../utils.js';
export default class Entry extends Gtk.Entry {
static {
GObject.registerClass({ GTypeName: 'AgsEntry' }, this);
}
onAccept: string | ((...args: any[]) => void);
onChange: string | ((...args: any[]) => void);
constructor({
onAccept = '',
onChange = '',
...rest
}: { [key: string]: any }) {
super(rest);
this.onAccept = onAccept;
this.onChange = onChange;
this.connect('activate', () => {
typeof this.onAccept === 'function'
? this.onAccept(this)
: runCmd(this.onAccept.replace(/\{\}/g, this.text));
});
this.connect('notify::text', ({ text }, event) => {
typeof this.onChange === 'function'
? this.onChange(this, event)
: runCmd(this.onChange.replace(/\{\}/g, text));
});
}
}
+67 -59
View File
@@ -2,33 +2,28 @@ import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import Gdk from 'gi://Gdk?version=3.0';
import { runCmd } from '../utils.js';
import { separateCommon, parseCommon, CommonParams } from './shared.js';
interface Params extends CommonParams {
[key: string]: any
}
class EventBox extends Gtk.EventBox {
export default class EventBox extends Gtk.EventBox {
static {
GObject.registerClass({ GTypeName: 'AgsEventBox' }, this);
}
onClick: string | ((...args: any[]) => void);
onSecondaryClick: string | ((...args: any[]) => void);
onMiddleClick: string | ((...args: any[]) => void);
onClickRelease: string | ((...args: any[]) => void);
onSecondaryClickRelease: string | ((...args: any[]) => void);
onMiddleClickRelease: string | ((...args: any[]) => void);
onHover: string | ((...args: any[]) => void);
onHoverLost: string | ((...args: any[]) => void);
onScrollUp: string | ((...args: any[]) => void);
onScrollDown: string | ((...args: any[]) => void);
onPrimaryClick: string | ((...args: any[]) => boolean);
onSecondaryClick: string | ((...args: any[]) => boolean);
onMiddleClick: string | ((...args: any[]) => boolean);
onPrimaryClickRelease: string | ((...args: any[]) => boolean);
onSecondaryClickRelease: string | ((...args: any[]) => boolean);
onMiddleClickRelease: string | ((...args: any[]) => boolean);
onHover: string | ((...args: any[]) => boolean);
onHoverLost: string | ((...args: any[]) => boolean);
onScrollUp: string | ((...args: any[]) => boolean);
onScrollDown: string | ((...args: any[]) => boolean);
constructor({
onClick = '',
onPrimaryClick = '',
onSecondaryClick = '',
onMiddleClick = '',
onClickRelease = '',
onPrimaryClickRelease = '',
onSecondaryClickRelease = '',
onMiddleClickRelease = '',
onHover = '',
@@ -36,65 +31,78 @@ class EventBox extends Gtk.EventBox {
onScrollUp = '',
onScrollDown = '',
...params
}: Params = {}) {
const [common, rest] = separateCommon(params);
super(rest);
parseCommon(this, common);
} = {}) {
super(params);
this.add_events(Gdk.EventMask.SCROLL_MASK);
this.onClick = onClick;
this.onPrimaryClick = onPrimaryClick;
this.onSecondaryClick = onSecondaryClick;
this.onMiddleClick = onMiddleClick;
this.onClickRelease = onClickRelease;
this.onPrimaryClickRelease = onPrimaryClickRelease;
this.onSecondaryClickRelease = onSecondaryClickRelease;
this.onMiddleClickRelease = onMiddleClickRelease;
this.onHover = onHover;
this.onHoverLost = onHoverLost;
this.onScrollUp = onScrollUp;
this.onScrollDown = onScrollDown;
}
this.connect('enter-notify-event', (box, event) => {
box.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
runCmd(this.onHover, box, event);
});
// @ts-ignore
get child() { return this.get_child(); }
set child(child: Gtk.Widget) {
const widget = this.get_child();
if (widget)
this.remove(widget);
this.connect('leave-notify-event', (box, event) => {
box.unset_state_flags(Gtk.StateFlags.PRELIGHT);
runCmd(this.onHoverLost, box, event);
});
if (child)
this.add(child);
}
this.connect('button-press-event', (box, event) => {
box.set_state_flags(Gtk.StateFlags.ACTIVE, false);
if (event.get_button()[1] === Gdk.BUTTON_PRIMARY)
runCmd(this.onClick, box, event);
vfunc_enter_notify_event(event: Gdk.EventCrossing): boolean {
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
return runCmd(this.onHover, this, event);
}
else if (event.get_button()[1] === Gdk.BUTTON_SECONDARY)
runCmd(this.onSecondaryClick, box, event);
vfunc_leave_notify_event(event: Gdk.EventCrossing): boolean {
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
return runCmd(this.onHoverLost, this, event);
}
else if (event.get_button()[1] === Gdk.BUTTON_MIDDLE)
runCmd(this.onMiddleClick, box, event);
});
vfunc_button_press_event(event: Gdk.EventButton): boolean {
this.set_state_flags(Gtk.StateFlags.ACTIVE, false);
if (event.button === Gdk.BUTTON_PRIMARY)
return runCmd(this.onPrimaryClick, this, event);
this.connect('button-release-event', (box, event) => {
box.unset_state_flags(Gtk.StateFlags.ACTIVE);
if (event.get_button()[1] === Gdk.BUTTON_PRIMARY)
runCmd(this.onClickRelease, box, event);
else if (event.button === Gdk.BUTTON_SECONDARY)
return runCmd(this.onSecondaryClick, this, event);
else if (event.get_button()[1] === Gdk.BUTTON_SECONDARY)
runCmd(this.onSecondaryClickRelease, box, event);
else if (event.button === Gdk.BUTTON_MIDDLE)
return runCmd(this.onMiddleClick, this, event);
else if (event.get_button()[1] === Gdk.BUTTON_MIDDLE)
runCmd(this.onMiddleClickRelease, box, event);
});
return false;
}
this.add_events(Gdk.EventMask.SCROLL_MASK);
this.connect('scroll-event', (box, event) => {
if (event.get_scroll_direction()[1] === Gdk.ScrollDirection.UP)
runCmd(this.onScrollUp, box, event);
vfunc_button_release_event(event: Gdk.EventButton): boolean {
this.unset_state_flags(Gtk.StateFlags.ACTIVE);
if (event.button === Gdk.BUTTON_PRIMARY)
return runCmd(this.onPrimaryClickRelease, this, event);
else if (event.get_scroll_direction()[1] === Gdk.ScrollDirection.DOWN)
runCmd(this.onScrollDown, box, event);
});
else if (event.button === Gdk.BUTTON_SECONDARY)
return runCmd(this.onSecondaryClickRelease, this, event);
else if (event.button === Gdk.BUTTON_MIDDLE)
return runCmd(this.onMiddleClickRelease, this, event);
return false;
}
vfunc_scroll_event(event: Gdk.EventScroll): boolean {
if (event.direction === Gdk.ScrollDirection.UP)
return runCmd(this.onScrollUp, this, event);
else if (event.direction === Gdk.ScrollDirection.DOWN)
return runCmd(this.onScrollDown, this, event);
return false;
}
}
export default (params: object) => new EventBox(params);
+81
View File
@@ -0,0 +1,81 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import GLib from 'gi://GLib';
import GdkPixbuf from 'gi://GdkPixbuf';
import { Context } from 'gi-types/cairo1';
export default class Icon extends Gtk.Image {
static {
GObject.registerClass({
GTypeName: 'AgsIcon',
Properties: {
'size': GObject.ParamSpec.int(
'size', 'Size', 'Size',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
0, 1024, 0,
),
'icon': GObject.ParamSpec.string(
'icon', 'Icon', 'Icon',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'',
),
},
}, this);
}
constructor(params: object | string) {
const { icon = '', size = 0 } = params as { icon: string, size: number };
super(typeof params === 'string' ? { icon: params } : params);
if (typeof params === 'object') {
this.size = size;
this.icon = icon;
}
}
_size = 0;
get size() { return this._size; }
set size(size: number) {
size ||= 0;
this._size = size;
this.icon = this._icon;
}
_file = false;
_icon = '';
get icon() { return this._icon; }
set icon(icon: string) {
if (!icon)
return;
this._icon = icon;
if (GLib.file_test(icon, GLib.FileTest.EXISTS)) {
this._file = true;
this.set_from_pixbuf(
GdkPixbuf.Pixbuf.new_from_file_at_size(icon, this.size, this.size),
);
}
else {
this._file = false;
this.icon_name = icon;
this.pixel_size = this.size;
}
}
vfunc_draw(cr: Context): boolean {
if (this._size)
return super.vfunc_draw(cr);
const size = this.get_style_context()
.get_property('font-size', Gtk.StateFlags.NORMAL) as number || 11;
if (this._file) {
this.set_from_pixbuf(
GdkPixbuf.Pixbuf.new_from_file_at_size(this.icon, size, size),
);
} else {
this.pixel_size = size;
}
return super.vfunc_draw(cr);
}
}
+37
View File
@@ -0,0 +1,37 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
const justification = ['left', 'center', 'right', 'fill'];
export default class Label extends Gtk.Label {
static {
GObject.registerClass({
GTypeName: 'AgsLabel',
Properties: {
'justification': GObject.ParamSpec.string(
'justification', 'Justification', 'Justification',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'',
),
},
}, this);
}
constructor(params: object | string) {
super(typeof params === 'string' ? { label: params } : params);
}
get justification() { return justification[this.justify]; }
set justification(justify) {
if (!justify)
return;
if (!justification.includes(justify)) {
console.error('wrong justification value for Label');
return;
}
// @ts-ignore
this.justify = Gtk.Justification[justify.toUpperCase()];
}
}
+85
View File
@@ -0,0 +1,85 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import { runCmd } from '../utils.js';
export class Menu extends Gtk.Menu {
static {
GObject.registerClass({ GTypeName: 'AgsMenu' }, this);
}
onPopup: string | ((...args: any[]) => boolean);
onMoveScroll: string | ((...args: any[]) => boolean);
constructor({
children,
onPopup = '',
onMoveScroll = '',
...rest
}: { [key: string]: any }) {
super(rest);
if (children)
this.children = children;
this.onPopup = onPopup;
this.onMoveScroll = onMoveScroll;
this.connect('popped-up', (...args) => runCmd(this.onPopup, ...args));
this.connect('move-scroll', (...args) => runCmd(this.onMoveScroll, ...args));
}
get children() { return this.get_children(); }
set children(children: Gtk.Widget[] | null) {
this.get_children().forEach(ch => this.remove(ch));
if (!children)
return;
children.forEach(w => {
if (w)
this.add(w);
});
const visible = this.visible;
this.show_all();
this.visible = visible;
}
}
export class MenuItem extends Gtk.MenuItem {
static {
GObject.registerClass({ GTypeName: 'AgsMenuItem' }, this);
}
onActivate: string | ((...args: any[]) => boolean);
onSelect: string | ((...args: any[]) => boolean);
onDeselect: string | ((...args: any[]) => boolean);
constructor({
onActivate = '',
onSelect = '',
onDeselect = '',
...rest
}: { [key: string]: any }) {
super(rest);
this.onActivate = onActivate;
this.onSelect = onSelect;
this.onDeselect = onDeselect;
this.connect('activate', (...args) => runCmd(this.onActivate, ...args));
this.connect('select', (...args) => runCmd(this.onSelect, ...args));
this.connect('deselect', (...args) => runCmd(this.onDeselect, ...args));
}
// @ts-ignore
get child() { return this.get_child(); }
set child(child: Gtk.Widget) {
const widget = this.get_child();
if (widget)
this.remove(widget);
if (child)
this.add(child);
}
}
+63
View File
@@ -0,0 +1,63 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
export default class Overlay extends Gtk.Overlay {
static {
GObject.registerClass({
GTypeName: 'AgsOverlay',
Properties: {
'child': GObject.ParamSpec.object(
'child', 'Child', 'Child',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
Gtk.Widget.$gtype,
),
// @ts-ignore
'overlays': GObject.ParamSpec.jsobject(
'overlays', 'Overlays', 'Overlays',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
[],
),
'pass-through': GObject.ParamSpec.boolean(
'pass-through', 'Pass Through', 'Pass Through',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
false,
),
},
}, this);
}
_passthrough = false;
get pass_through() { return this._passthrough; }
set pass_through(passthrough: boolean) {
this._passthrough = passthrough;
this.get_children().forEach(ch => this.set_overlay_pass_through(ch, passthrough));
}
_child!: Gtk.Widget;
get child() { return this._child; }
set child(child: Gtk.Widget) {
const widget = this.get_child();
if (widget)
this.remove(widget);
this._child = child;
if (child)
this.add(child);
}
_overlays!: Gtk.Widget[];
get overlays() { return this._overlays; }
set overlays(overlays: Gtk.Widget[]) {
overlays ||= [];
this.get_children().filter(ch => ch !== this._child)
.forEach(ch => this.remove(ch));
this._overlays = [];
overlays.forEach(ch => this.add_overlay(ch));
}
add_overlay(widget: Gtk.Widget): void {
this._overlays.push(widget);
super.add_overlay(widget);
}
}
+34
View File
@@ -0,0 +1,34 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
export default class ProgressBar extends Gtk.ProgressBar {
static {
GObject.registerClass({
GTypeName: 'AgsProgressBar',
Properties: {
'vertical': GObject.ParamSpec.boolean(
'vertical', 'Vertical', 'Vertical',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
false,
),
'value': GObject.ParamSpec.int(
'value', 'Value', 'Same as fraction',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
0, 1, 0,
),
},
}, this);
}
get value() { return this.fraction; }
set value(value: number) {
this.fraction = value;
this.notify('value');
}
get vertical() { return this.orientation === Gtk.Orientation.VERTICAL; }
set vertical(vertical) {
this.orientation = vertical
? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL;
}
}
+46
View File
@@ -0,0 +1,46 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
const transitions = [
'none', 'crossfade',
'slide_right', 'slide_left',
'slide_up', 'slide_down',
];
export default class Revealer extends Gtk.Revealer {
static {
GObject.registerClass({
GTypeName: 'AgsRevealer',
Properties: {
'transition': GObject.ParamSpec.string(
'transition', 'Transition', 'transition-type as a string',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'none',
),
},
}, this);
}
get transition() { return transitions[this.transitionType]; }
set transition(transition: string) {
if (!transition)
return;
if (!transitions.includes(transition)) {
console.error('wrong transition value for Revealer');
return;
}
// @ts-ignore
this.transitionType = Gtk.RevealerTransitionType[transition.toUpperCase()];
}
set child(child: Gtk.Widget) {
const widget = this.get_child();
if (widget)
this.remove(widget);
if (child)
this.add(child);
}
}
+71
View File
@@ -0,0 +1,71 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
const policy = ['automatic', 'always', 'never', 'external'];
export default class Scrollable extends Gtk.ScrolledWindow {
static {
GObject.registerClass({
GTypeName: 'AgsScrollable',
Properties: {
'hscroll': GObject.ParamSpec.string(
'hscroll', 'HScroll', 'Horizontal Scroll Policy',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'automatic',
),
'vscroll': GObject.ParamSpec.string(
'vscroll', 'VScroll', 'Vertical Scroll Policy',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'automatic',
),
},
}, this);
}
constructor(params: object) {
super({
...params,
hadjustment: new Gtk.Adjustment(),
vadjustment: new Gtk.Adjustment(),
});
}
_hscroll = 'automatic';
get hscroll() { return this._hscroll; }
set hscroll(hscroll: string) {
if (!hscroll)
return;
if (!policy.includes(hscroll)) {
console.error('wrong hscroll value for Scrollable');
return;
}
this._hscroll = hscroll;
this.policy();
}
_vscroll = 'automatic';
get vscroll() { return this._vscroll; }
set vscroll(vscroll: string) {
if (!vscroll)
return;
if (!policy.includes(vscroll)) {
console.error('wrong vscroll value for Scrollable');
return;
}
this._vscroll = vscroll;
this.policy();
}
policy() {
this.set_policy(
// @ts-ignore
Gtk.PolicyType[this._hscroll?.toUpperCase() || 'AUTOMATIC'],
// @ts-ignore
Gtk.PolicyType[this._vscroll?.toUpperCase() || 'AUTOMATIC'],
);
}
}
+17 -5
View File
@@ -7,7 +7,7 @@ interface ServiceAPI {
}
}
export interface CommonParams {
interface CommonParams {
className?: string
style?: string
halign?: 'start' | 'center' | 'end' | 'fill'
@@ -21,20 +21,20 @@ export interface CommonParams {
setup?: (widget: Gtk.Widget) => void
}
export function setStyle(widget: Gtk.Widget, css: string) {
function setStyle(widget: Gtk.Widget, css: string) {
const provider = new Gtk.CssProvider();
const style = `* { ${css} }`;
provider.load_from_data(style);
widget.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
}
export function toggleClassName(widget: Gtk.Widget, className: string, condition = true) {
function toggleClassName(widget: Gtk.Widget, className: string, condition = true) {
condition
? widget.get_style_context().add_class(className)
: widget.get_style_context().remove_class(className);
}
export function separateCommon({
function separateCommon({
className, style, halign, valign, connections, properties, setup,
...rest
}: CommonParams) {
@@ -44,7 +44,7 @@ export function separateCommon({
];
}
export function parseCommon(widget: Gtk.Widget, {
function parseCommon(widget: Gtk.Widget, {
className, style,
halign, valign,
connections, properties, setup,
@@ -103,3 +103,15 @@ export function parseCommon(widget: Gtk.Widget, {
if (typeof setup === 'function')
setup(widget);
}
export function constructor(ctor: { new(...args: any[]): Gtk.Widget }, params: CommonParams | string = {}) {
let widget;
if (typeof params === 'string') {
widget = new ctor(params);
} else {
const [common, rest] = separateCommon(params);
widget = new ctor(rest);
parseCommon(widget, common);
}
return widget;
}
+145
View File
@@ -0,0 +1,145 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
import { runCmd } from '../utils.js';
import { EventButton, EventScroll } from 'gi-types/gdk3';
export default class Slider extends Gtk.Scale {
static {
GObject.registerClass({
GTypeName: 'AgsSlider',
Properties: {
'value': GObject.ParamSpec.float(
'value', 'Value', 'Value',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
-100, 100, 0,
),
'min': GObject.ParamSpec.float(
'min', 'Min', 'Min',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
-100, 100, 0,
),
'max': GObject.ParamSpec.float(
'max', 'Max', 'Max',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
-100, 100, 1,
),
'step': GObject.ParamSpec.float(
'step', 'Step', 'Step',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
-100, 100, 0.01,
),
'dragging': GObject.ParamSpec.boolean(
'dragging', 'Dragging', 'Dragging',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
false,
),
'vertical': GObject.ParamSpec.boolean(
'vertical', 'Vertical', 'Vertical',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
false,
),
},
}, this);
}
onChange: string | ((...args: any[]) => boolean);
constructor({ onChange = '', ...rest }) {
super({ ...rest, adjustment: new Gtk.Adjustment() });
this.onChange = onChange;
this.bind_property(
'value', this.adjustment, 'value',
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE,
);
this.bind_property(
'min', this.adjustment, 'lower',
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE,
);
this.bind_property(
'max', this.adjustment, 'upper',
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE,
);
this.bind_property(
'step', this.adjustment, 'step-increment',
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE,
);
this.connect('notify::value', ({ value }, event) => {
if (!this._dragging)
return;
typeof this.onChange === 'function'
? this.onChange(this, event, value)
: runCmd(onChange.replace(/\{\}/g, value));
});
}
_value = 0;
get value() { return this._value; }
set value(value: number) {
this._value = value;
this.notify('value');
}
_min = 0;
get min() { return this._min; }
set min(min: number) {
this._min = min;
this.notify('min');
}
_max = 1;
get max() { return this._max; }
set max(max: number) {
this._max = max;
this.notify('max');
}
_step = 0.01;
get step() { return this._step; }
set step(step: number) {
this._step = step;
this.notify('step');
}
_dragging = false;
get dragging() { return this._dragging; }
set dragging(dragging: boolean) {
this._dragging = dragging;
this.notify('dragging');
}
get vertical() { return this.orientation === Gtk.Orientation.VERTICAL; }
set vertical(vertical) {
this.orientation = vertical
? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL;
}
vfunc_button_release_event(event: EventButton): boolean {
this.dragging = false;
return super.vfunc_button_release_event(event);
}
vfunc_button_press_event(event: EventButton): boolean {
this.dragging = true;
return super.vfunc_button_press_event(event);
}
vfunc_scroll_event(event: EventScroll): boolean {
this.dragging = true;
event.delta_y > 0
? this.adjustment.value -= this.step
: this.adjustment.value += this.step;
this.dragging = false;
return super.vfunc_scroll_event(event);
}
}
+76
View File
@@ -0,0 +1,76 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk?version=3.0';
const transitions = [
'none', 'crossfade',
'slide_right', 'slide_left', 'slide_up', 'slide_down',
'slide_left_right', 'slide_up_down',
'over_up', 'over_down', 'over_left', 'over_right',
'under_up', 'under_down', 'under_left', 'under_right',
'over_up_down', 'over_down_up', 'over_left_right', 'over_right_left',
];
export default class Stack extends Gtk.Stack {
static {
GObject.registerClass({
GTypeName: 'AgsStack',
Properties: {
'transition': GObject.ParamSpec.string(
'transition', 'Transition', 'Transition',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'none',
),
// @ts-ignore
'items': GObject.ParamSpec.jsobject(
'items', 'Items', 'Items',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
[],
),
'shown': GObject.ParamSpec.string(
'shown', 'Shown', 'Shown',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
'',
),
},
}, this);
}
add_named(child: Gtk.Widget, name: string): void {
this._items.push([name, child]);
super.add_named(child, name);
}
_items: [string, Gtk.Widget][] = [];
get items() { return this._items; }
set items(items: [string, Gtk.Widget][]) {
this.get_children().forEach(ch => this.remove(ch));
this._items = [];
items.forEach(([name, widget]) => {
if (widget)
this.add_named(widget, name);
});
this.show_all();
}
get transition() { return transitions[this.transitionType]; }
set transition(transition: string) {
if (typeof transition !== 'string')
return;
if (!transitions.includes(transition)) {
console.error('wrong transition value for Stack');
return;
}
// @ts-ignore
this.transitionType = Gtk.StackTransitionType[transition.toUpperCase()];
}
get shown() { return this.visible_child_name; }
set shown(name: string) {
if (!name)
return;
this.set_visible_child_name(name);
}
}