Skip to content

Commit

Permalink
fix: Renderer remove nested controls, updated types
Browse files Browse the repository at this point in the history
  • Loading branch information
Max committed Feb 4, 2021
1 parent f69860f commit e161a9b
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- uses: actions/[email protected]
with:
registry-url: 'https://registry.npmjs.org'
scope: '@garment'
scope: '@pixinsight'

- name: Install dependencies
run: yarn
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@pixinsight:registry=https://registry.npmjs.org
33 changes: 19 additions & 14 deletions packages/core/types/controls.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ declare class Frame extends Control {
lineWidth: any;
}
declare class GroupBox extends Control {
checked: any;
onCheck: any;
title: any;
titleCheckBox: any;
checked: boolean;
onCheck: (checked: boolean) => void;
title: string;
titleCheckBox: boolean;
}
declare class Label extends Frame {
clear: any;
Expand Down Expand Up @@ -453,32 +453,37 @@ declare class WebView extends Control {

declare class Sizer {
constructor(...args: any[]);
add: any;
add(child: Sizer | Control, stretchFactor?: number, alignment?: number): void;
addScaledSpacing: any;
addSpacing: any;
addStretch: any;
addUnscaledSpacing: any;
displayPixelRatio: any;
has: any;
indexOf: any;
insert: any;
has(child: Sizer | Control): boolean;
indexOf(child: Sizer | Control): number;
insert(
index: number,
child: Sizer | Control,
stretchFactor?: number,
alignment?: number
): void;
insertScaledSpacing: any;
insertSpacing: any;
insertStretch: any;
insertUnscaledSpacing: any;
isHorizontal: any;
isVertical: any;
isHorizontal: boolean;
isVertical: boolean;
logicalPixelsToPhysical: any;
margin: any;
numberOfItems: any;
margin: number;
numberOfItems: number;
parentControl: Control;
physicalPixelsToLogical: any;
remove: any;
remove(child: Sizer | Control): void;
scaledMargin: any;
scaledSpacing: any;
setAlignment: any;
setStretchFactor: any;
spacing: any;
spacing: number;
unscaledMargin: any;
unscaledSpacing: any;
}
122 changes: 103 additions & 19 deletions packages/react/src/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ const sizerPropsSet = new Set([
"unscaledSpacing",
] as const);

type SizerProps = typeof sizerPropsSet extends Set<infer T> ? T : never;

jsStrictMode = false;
console.clear();

console.log = (...args: any[]) => console.writeln(args.join(" "));
console.warn = console.warning;
Expand All @@ -44,6 +45,56 @@ const debug = (...args: any[]) => {
};

const garbage = new Control();
const childrenBySizerMap = new Map<Sizer, (Control | Sizer)[]>();

function addChild(
parent: Sizer,
...[child, ...args]: Parameters<typeof Sizer.prototype.add>
) {
if (!childrenBySizerMap.has(parent)) {
childrenBySizerMap.set(parent, []);
}
const children = childrenBySizerMap.get(parent)!;
children.push(child);
parent.add(child, ...args);
}

function insertChild(
parent: Sizer,
...[index, child, ...args]: Parameters<typeof Sizer.prototype.insert>
) {
if (!childrenBySizerMap.has(parent)) {
childrenBySizerMap.set(parent, []);
}
const children = childrenBySizerMap.get(parent)!;
children.splice(index, 0, child);
parent.insert(index, child, ...args);
}

function removeChild(
parent: Sizer,
...[childToRemove]: Parameters<typeof Sizer.prototype.remove>
) {
if (!childrenBySizerMap.has(parent)) {
childrenBySizerMap.set(parent, []);
}
const children = childrenBySizerMap.get(parent)!;

if (childToRemove instanceof Sizer && childrenBySizerMap.has(childToRemove)) {
childrenBySizerMap
.get(childToRemove)
?.forEach((subchild) => removeChild(childToRemove, subchild));
childrenBySizerMap.delete(childToRemove);
}

childrenBySizerMap.set(
parent,
children.filter((child) => child !== childToRemove)
);
if (childToRemove instanceof Control) {
childToRemove.parent = garbage;
}
}

const PixInsightReconciler = Reconciler({
supportsMutation: true,
Expand Down Expand Up @@ -88,13 +139,15 @@ const PixInsightReconciler = Reconciler({
constructorProps,
stretchFactor = 0,
alignment = 0,
children,
...props
}: {
type: string;
ctor: new (...args: any[]) => any;
constructorProps?: any[];
stretchFactor?: number;
alignment?: number;
children: any;
}
) {
debug("createInstance", controlType, props);
Expand All @@ -113,7 +166,7 @@ const PixInsightReconciler = Reconciler({

for (const key of Object.keys(instanceProps)) {
if (sizerPropsSet.has(key as any) && instance instanceof Control) {
instance.sizer[key as keyof Sizer] = instanceProps[key];
instance.sizer[key as SizerProps] = instanceProps[key];
} else {
instance[key] = instanceProps[key];
}
Expand All @@ -134,70 +187,90 @@ const PixInsightReconciler = Reconciler({

return label;
},

appendInitialChild(parent: Instance, child: Instance) {
debug(`appendInitialChild ${parent.__id} ${child.__id}`);
if (child instanceof Dialog) {
return;
}
const args = [child, child.stretchFactor];
const args: Parameters<typeof Sizer.prototype.add> = [
child,
child.stretchFactor,
];
if (!(child instanceof Sizer)) {
args.push(child.alignment);
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
child.parentSizer = sizer;
sizer.add(...args);

addChild(sizer, ...args);
},
appendChild(parent: Instance, child: Instance) {
debug(`appendChild ${parent.__id} ${child.__id}`);
if (child instanceof Dialog) {
return;
}
const args = [child, child.stretchFactor];
const args: Parameters<typeof Sizer.prototype.add> = [
child,
child.stretchFactor,
];
if (!(child instanceof Sizer)) {
args.push(child.alignment);
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
child.parentSizer = sizer;
sizer.add(...args);

addChild(sizer, ...args);
},
appendChildToContainer(parent: Instance, child: Instance) {
debug(`appendChildToContainer ${parent.__id} ${child.__id}`);
if (child instanceof Dialog) {
return;
}
const args = [child, child.stretchFactor];
const args: Parameters<typeof Sizer.prototype.add> = [
child,
child.stretchFactor,
];
if (!(child instanceof Sizer)) {
args.push(child.alignment);
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
child.parentSizer = sizer;
sizer.add(...args);

addChild(sizer, ...args);
},

finalizeInitialChildren(domElement, type, props) {
debug("finalizeInitialChildren");
return false;
},

insertBefore(parent: Instance, child: Instance, beforeChild: Instance) {
debug(`insertBefore ${parent.__id} ${child.__id}`);
if (child instanceof Dialog) {
return;
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
const args = [sizer.indexOf(beforeChild), child, child.stretchFactor];
const args: Parameters<typeof Sizer.prototype.insert> = [
sizer.indexOf(beforeChild),
child,
child.stretchFactor,
];
if (!(child instanceof Sizer)) {
args.push(child.alignment);
}
child.parentSizer = sizer;
sizer.insert(...args);
insertChild(sizer, ...args);
},

removeChild(parent: Extended<Control>, child: Extended<Control>) {
debug(`removeChild ${parent.__id} ${child.__id}`);
if (child instanceof Dialog) {
return;
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
sizer.remove(child);
child.parent = garbage;

removeChild(sizer, child);
},
removeChildFromContainer(
parent: Extended<Control>,
Expand All @@ -208,8 +281,7 @@ const PixInsightReconciler = Reconciler({
return;
}
const sizer = parent instanceof Sizer ? parent : parent.sizer;
sizer.remove(child);
child.parent = garbage;
removeChild(sizer, child);
},
prepareUpdate(control: Extended<Control>, type, oldProps, newProps) {
debug(`prepareUpdate ${control.__id} ${type}`);
Expand All @@ -220,17 +292,29 @@ const PixInsightReconciler = Reconciler({
updatePayload: any,
type: string,
oldProps: any,
newProps: any
allNewProps: any
) {
const {
type: controlType,
ctor,
constructorProps,
children,
...newProps
} = allNewProps;

debug(`commitUpdate ${control.__id} ${type}`);
Object.keys(newProps).forEach((propName) => {
const propValue = newProps[propName];

if (sizerPropsSet.has(propName as any)) {
const sizer = control instanceof Sizer ? control : control.sizer;
sizer[propName as keyof Sizer] = propValue;
if (sizer[propName as SizerProps] !== propValue) {
sizer[propName as SizerProps] = propValue;
};
} else {
(control as any)[propName] = propValue;
if ((control as any)[propName] !== propValue) {
(control as any)[propName] = propValue;
}
}
});
if (newProps.stretchFactor !== oldProps.stretchFactor) {
Expand Down Expand Up @@ -286,11 +370,11 @@ export function render(
sizer.dialog = dialog;
dialog.sizer = sizer;

global.setTimeout = function (cb: () => void, ms: number) {
global.setTimeout = function(cb: () => void, ms: number) {
var timer = new Timer();
timer.interval = ms / 1000;
timer.periodic = false;
timer.onTimeout = function () {
timer.onTimeout = function() {
cb();
};
timer.start();
Expand Down

0 comments on commit e161a9b

Please sign in to comment.