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
  • Loading branch information
vixalien committed Dec 11, 2023
1 parent 11315e1 commit da4ed1a
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 57 deletions.
1 change: 1 addition & 0 deletions src/bindings/girepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const { g } = openLib(libName("girepository-1.0", 1), {
},
base_info: {
get_name: $string($pointer),
get_namespace: $string($pointer),
is_deprecated: $bool($pointer),
get_type: $i32($pointer),
unref: $void($pointer),
Expand Down
3 changes: 3 additions & 0 deletions src/gi.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import g from "./bindings/mod.js";
import handleInfo from "./handleInfo.js";
import { loadOverride } from "./overrides/mod.ts";

/**
* @param {string} namespace
Expand All @@ -25,5 +26,7 @@ export function require(namespace, version) {
g.base_info.unref(info);
}

loadOverride(namespace, repo);

return repo;
}
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);
}
}
79 changes: 22 additions & 57 deletions src/types/object.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import g from "../bindings/mod.js";
import { getName } from "../utils/string.ts";
import { handleCallable } from "./callable.js";
import { handleCallable, handleMethod } 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 @@ -86,60 +82,30 @@ function defineProps(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;
});
}
function defineStructMethods(target, structInfo) {
const nMethods = g.struct_info.get_n_methods(structInfo);

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;
}

on(action, callback) {
return this.connect(action, callback);
for (let i = 0; i < nMethods; i++) {
const methodInfo = g.struct_info.get_method(structInfo, i);
if (!Object.hasOwn(target.prototype, getName(methodInfo))) {
handleMethod(target, methodInfo);
}
}
}

once(action, callback) {
const handler = this.connect(action, (...args) => {
callback(...args);
this.off(handler);
});
export function createObject(info, gType) {
const ParentClass = getParentClass(info) ?? Object;

return handler;
}
const ObjectClass = class extends ParentClass {
constructor(props = {}, init = true) {
super(props, false);

off(handler) {
g.signal.handler_disconnect(
Reflect.getOwnMetadata("gi:ref", this),
handler,
);
}

emit(action) {
g.signal.emit_by_name(
Reflect.getOwnMetadata("gi:ref", this),
action,
);
if (init) {
Reflect.defineMetadata("gi:ref", g.object.new(gType, null), this);
Object.entries(props).forEach(([key, value]) => {
this[key] = value;
});
}
}
};

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

return ObjectClass;
Expand Down

0 comments on commit da4ed1a

Please sign in to comment.