Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor refresh() #513

Merged
merged 1 commit into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions packages/core/src/blade/binding/api/binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {Emitter} from '../../../common/model/emitter';
import {ValueEvents} from '../../../common/model/value';
import {forceCast} from '../../../misc/type-util';
import {BladeApi} from '../../common/api/blade';
import {Refreshable} from '../../common/api/refreshable';
import {TpChangeEvent} from '../../common/api/tp-event';
import {BindingController} from '../controller/binding';

Expand All @@ -15,10 +16,13 @@ export interface BindingApiEvents<Ex> {
* @template Ex The external type.
*/
export class BindingApi<
In = unknown,
Ex = unknown,
C extends BindingController<In> = BindingController<In>,
> extends BladeApi<C> {
In = unknown,
Ex = unknown,
C extends BindingController<In> = BindingController<In>,
>
extends BladeApi<C>
implements Refreshable
{
private readonly emitter_: Emitter<BindingApiEvents<Ex>>;

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/blade/common/api/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {FolderApi} from '../../folder/api/folder';
import {TabApi} from '../../tab/api/tab';
import {BladeApi} from './blade';
import {BindingParams, ButtonParams, FolderParams, TabParams} from './params';
import {Refreshable} from './refreshable';

export interface ContainerApi {
export interface ContainerApi extends Refreshable {
/**
* Children of the container.
*/
Expand Down
29 changes: 29 additions & 0 deletions packages/core/src/blade/common/api/rack-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {forceCast} from '../../../misc/type-util';
import {createDefaultPluginPool} from '../../../plugin/plugins';
import {PluginPool} from '../../../plugin/pool';
import {BindingApi} from '../../binding/api/binding';
import {InputBindingApi} from '../../binding/api/input-binding';
import {FolderApi} from '../../folder/api/folder';
import {LabeledValueController} from '../../label/controller/value-label';
import {LabelPropsObject} from '../../label/view/label';
import {TestValueBladeApi, TestValueBladePlugin} from '../../test-util';
Expand Down Expand Up @@ -141,4 +143,31 @@ describe(RackApi.name, () => {

b['controller_'].value.rawValue = 2;
});

it('should refresh children', () => {
const doc = createTestWindow().document;
const api = createApi({document: doc});
const obj = {foo: 1};
api.addBinding(obj, 'foo');
obj.foo = 2;

const bapi = api.children[0] as InputBindingApi;
assert.strictEqual(bapi['controller_'].value.rawValue, 1);
api.refresh();
assert.strictEqual(bapi['controller_'].value.rawValue, 2);
});

it('should refresh nested children', () => {
const doc = createTestWindow().document;
const api = createApi({document: doc});
const obj = {foo: 1};
api.addFolder({title: ''}).addBinding(obj, 'foo');
obj.foo = 2;

const fapi = api.children[0] as FolderApi;
const bapi = fapi.children[0] as InputBindingApi;
assert.strictEqual(bapi['controller_'].value.rawValue, 1);
api.refresh();
assert.strictEqual(bapi['controller_'].value.rawValue, 2);
});
});
9 changes: 9 additions & 0 deletions packages/core/src/blade/common/api/rack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
ContainerApi,
} from './container';
import {BindingParams, ButtonParams, FolderParams, TabParams} from './params';
import {isRefreshable} from './refreshable';
import {TpChangeEvent} from './tp-event';

/**
Expand Down Expand Up @@ -116,6 +117,14 @@ export class RackApi implements ContainerApi {
return this;
}

public refresh(): void {
this.children.forEach((c) => {
if (isRefreshable(c)) {
c.refresh();
}
});
}

private onRackValueChange_(ev: RackEvents['valuechange']): void {
const bc = ev.bladeController;
const api = this.pool_.createApi(bc);
Expand Down
24 changes: 24 additions & 0 deletions packages/core/src/blade/common/api/refreshable-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as assert from 'assert';
import {describe, it} from 'mocha';

import {isRefreshable} from './refreshable';

describe(isRefreshable.name, () => {
it('should determine Refreshable', () => {
assert.strictEqual(
isRefreshable({
refresh: () => {},
}),
true,
);
});

it('should not determine variable as Refreshable', () => {
assert.strictEqual(
isRefreshable({
refresh: 1,
}),
false,
);
});
});
15 changes: 15 additions & 0 deletions packages/core/src/blade/common/api/refreshable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {isObject} from '../../../misc/type-util';

export interface Refreshable {
/**
* Refreshes the target.
*/
refresh(): void;
}

export function isRefreshable(value: unknown): value is Refreshable {
if (!isObject(value)) {
return false;
}
return 'refresh' in value && typeof value.refresh === 'function';
}
4 changes: 4 additions & 0 deletions packages/core/src/blade/folder/api/folder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,8 @@ export class FolderApi
});
return this;
}

public refresh(): void {
this.rackApi_.refresh();
}
}
4 changes: 4 additions & 0 deletions packages/core/src/blade/tab/api/tab-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ export class TabPageApi
public addBlade(params: BaseBladeParams): BladeApi {
return this.rackApi_.addBlade(params);
}

public refresh(): void {
this.rackApi_.refresh();
}
}
38 changes: 1 addition & 37 deletions packages/tweakpane/src/main/ts/blade/root/api/root.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,7 @@
import {
BindingValue,
FolderApi,
isInputBindingController,
isMonitorBindingController,
MonitorBindingValue,
PluginPool,
Rack,
} from '@tweakpane/core';
import {FolderApi, PluginPool} from '@tweakpane/core';

import {RootController} from '../controller/root';

function findInputBindingValues(rack: Rack): BindingValue<unknown>[] {
const vcs = rack.find(isInputBindingController);
return vcs.map((vc) => vc.value);
}

function findMonitorBindingValues(rack: Rack): MonitorBindingValue<unknown>[] {
return rack
.find(isMonitorBindingController)
.map((vc) => vc.value as MonitorBindingValue<unknown>);
}

export class RootApi extends FolderApi {
/**
* @hidden
Expand All @@ -32,21 +13,4 @@ export class RootApi extends FolderApi {
get element(): HTMLElement {
return this.controller_.view.element;
}

/**
* Refreshes all bindings of the pane.
*/
public refresh(): void {
// Force-read all input bindings
findInputBindingValues(this.controller_.rackController.rack).forEach((bv) =>
bv.fetch(),
);

// Force-read all monitor bindings
findMonitorBindingValues(this.controller_.rackController.rack).forEach(
(mbv) => {
mbv.fetch();
},
);
}
}