Skip to content

Commit

Permalink
support overrides
Browse files Browse the repository at this point in the history
also move gobject.object overrides to new file
allowing to construct objects by extending

remove girepository symbol
  • Loading branch information
vixalien committed Jan 17, 2024
1 parent 4593680 commit 1490163
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 62 deletions.
3 changes: 3 additions & 0 deletions src/gi.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { cast_u64_ptr, deref_buf, deref_str } from "./base_utils/convert.ts";
import g from "./bindings/mod.js";
import handleInfo from "./handleInfo.js";
import { ExtendedDataView } from "./utils/dataview.js";
import { loadOverride } from "./overrides/mod.ts";

const repos = new Map();

Expand Down Expand Up @@ -94,6 +95,8 @@ export function require(namespace, version) {
g.base_info.unref(info);
}

loadOverride(namespace, repo);

repos.set(key, repo);

return repo;
Expand Down
68 changes: 68 additions & 0 deletions src/overrides/GObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// deno-lint-ignore-file no-explicit-any
import { GConnectFlags } from "../bindings/enums.js";
import g from "../bindings/mod.js";
import { createCallback } from "../types/callback.js";

type Handler = (...args: unknown[]) => unknown;

function addObjectMethods(object: any) {
object.prototype.connect = function (
action: string,
callback: Handler,
) {
const signalInfo = Reflect.getMetadata(
"gi:signals",
this.constructor,
action.split("::")[0],
);

const cb = createCallback(signalInfo, callback, this);
const handler = g.signal.connect_data(
Reflect.getOwnMetadata("gi:ref", this),
action,
cb.pointer,
null,
null,
GConnectFlags.SWAPPED,
);

return handler;
};

object.prototype.on = function (
action: string,
callback: Handler,
) {
return this.connect(action, callback);
};

object.prototype.once = function (
action: string,
callback: Handler,
) {
const handler = this.connect(action, (...args: unknown[]) => {
callback(...args);
this.off(handler);
});

return handler;
};

object.prototype.off = function (handler: Handler) {
g.signal.handler_disconnect(
Reflect.getOwnMetadata("gi:ref", this),
handler as any,
);
};

object.prototype.emit = function (action: string) {
g.signal.emit_by_name(
Reflect.getOwnMetadata("gi:ref", this),
action,
);
};
}

export function _init(GObject: any) {
addObjectMethods(GObject.Object);
}
22 changes: 22 additions & 0 deletions src/overrides/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as GObject from "./GObject.ts";

export interface GIOverride {
name: string;
version: string;
// deno-lint-ignore no-explicit-any
module: any;
}

export const overrides: GIOverride[] = [
{ name: "GObject", version: "2.0", module: GObject },
];

export function loadOverride(namespace: string, repo: unknown) {
const override = overrides.find((override) => {
return override.name === namespace;
});

if (override) {
override.module._init(repo);
}
}
74 changes: 12 additions & 62 deletions src/types/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@ import g from "../bindings/mod.js";
import { getName } from "../utils/string.ts";
import { handleCallable, handleStructCallable } from "./callable.js";
import { objectByGType } from "../utils/gobject.js";
import { GConnectFlags } from "../bindings/enums.js";
import { createCallback } from "./callback.js";
import { handleSignal } from "./signal.js";
import { handleProp } from "./prop.js";

function extendObject(target, info) {
function getParentClass(info) {
const parent = g.object_info.get_parent(info);

if (parent) {
const gType = g.registered_type_info.get_g_type(parent);

const ParentClass = objectByGType(gType);
Object.setPrototypeOf(target.prototype, ParentClass.prototype);
//Object.assign(target.__signals__, ParentClass.__signals__);

g.base_info.unref(parent);
return ParentClass;
}
}

Expand Down Expand Up @@ -102,63 +98,18 @@ function defineClassStructMethods(target, info) {
}

export function createObject(info, gType) {
const ObjectClass = class {
constructor(props = {}) {
Reflect.defineMetadata("gi:ref", g.object.new(gType, null), this);
Object.entries(props).forEach(([key, value]) => {
this[key] = value;
});
}

connect(action, callback) {
const signalInfo = Reflect.getMetadata(
"gi:signals",
ObjectClass,
action.split("::")[0],
);

const cb = createCallback(signalInfo, callback, this);
const handler = g.signal.connect_data(
Reflect.getOwnMetadata("gi:ref", this),
action,
cb.pointer,
null,
null,
GConnectFlags.SWAPPED,
);

return handler;
}

disconnect(handler) {
g.signal.handler_disconnect(
Reflect.getOwnMetadata("gi:ref", this),
handler,
);
}
const ParentClass = getParentClass(info) ?? Object;

emit(action) {
g.signal.emit_by_name(
Reflect.getOwnMetadata("gi:ref", this),
action,
);
}

on(action, callback) {
return this.connect(action, callback);
}
const ObjectClass = class extends ParentClass {
constructor(props = {}, init = true) {
super(props, false);

once(action, callback) {
const handler = this.connect(action, (...args) => {
callback(...args);
this.off(handler);
});

return handler;
}

off(handler) {
return this.disconnect(handler);
if (init) {
Reflect.defineMetadata("gi:ref", g.object.new(gType, null), this);
Object.entries(props).forEach(([key, value]) => {
this[key] = value;
});
}
}
};

Expand All @@ -172,7 +123,6 @@ export function createObject(info, gType) {
defineVFuncs(ObjectClass, info);
defineSignals(ObjectClass, info);
defineProps(ObjectClass, info);
extendObject(ObjectClass, info);
inheritInterfaces(ObjectClass, info);
defineClassStructMethods(ObjectClass, info);

Expand Down

0 comments on commit 1490163

Please sign in to comment.