Refactored widget properties to simplify the interface.

This commit is contained in:
Daan Vanden Bosch 2019-08-28 00:50:38 +02:00
parent 3fd4d7c882
commit f100220176
33 changed files with 285 additions and 254 deletions

View File

@ -1,10 +1,10 @@
import { NavigationView } from "./NavigationView";
import { MainContentView } from "./MainContentView";
import { create_element } from "../../core/gui/dom";
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
export class ApplicationView extends ResizableView {
element = create_element("div", { class: "application_ApplicationView" });
export class ApplicationView extends ResizableWidget {
readonly element = create_element("div", { class: "application_ApplicationView" });
private menu_view = this.disposable(new NavigationView());
private main_content_view = this.disposable(new MainContentView());

View File

@ -1,10 +1,10 @@
import { create_element } from "../../core/gui/dom";
import { gui_store, GuiTool } from "../../core/stores/GuiStore";
import { LazyView } from "../../core/gui/LazyView";
import { ResizableView } from "../../core/gui/ResizableView";
import { LazyWidget } from "../../core/gui/LazyWidget";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { ChangeEvent } from "../../core/observable/Observable";
const TOOLS: [GuiTool, () => Promise<ResizableView>][] = [
const TOOLS: [GuiTool, () => Promise<ResizableWidget>][] = [
[GuiTool.Viewer, async () => new (await import("../../viewer/gui/ViewerView")).ViewerView()],
[
GuiTool.QuestEditor,
@ -12,11 +12,11 @@ const TOOLS: [GuiTool, () => Promise<ResizableView>][] = [
],
];
export class MainContentView extends ResizableView {
element = create_element("div", { class: "application_MainContentView" });
export class MainContentView extends ResizableWidget {
readonly element = create_element("div", { class: "application_MainContentView" });
private tool_views = new Map(
TOOLS.map(([tool, create_view]) => [tool, this.disposable(new LazyView(create_view))]),
TOOLS.map(([tool, create_view]) => [tool, this.disposable(new LazyWidget(create_view))]),
);
constructor() {

View File

@ -1,7 +1,7 @@
import { create_element } from "../../core/gui/dom";
import "./NavigationView.css";
import { gui_store, GuiTool } from "../../core/stores/GuiStore";
import { View } from "../../core/gui/View";
import { Widget } from "../../core/gui/Widget";
const TOOLS: [GuiTool, string][] = [
[GuiTool.Viewer, "Viewer"],
@ -9,7 +9,7 @@ const TOOLS: [GuiTool, string][] = [
[GuiTool.HuntOptimizer, "Hunt Optimizer"],
];
export class NavigationView extends View {
export class NavigationView extends Widget {
readonly element = create_element("div", { class: "application_NavigationView" });
readonly height = 30;
@ -44,7 +44,7 @@ export class NavigationView extends View {
};
}
class ToolButton extends View {
class ToolButton extends Widget {
element: HTMLElement = create_element("span");
private input: HTMLInputElement = create_element("input");

View File

@ -3,15 +3,20 @@ import "./Button.css";
import { Observable } from "../observable/Observable";
import { emitter } from "../observable";
import { Control } from "./Control";
import { Emitter } from "../observable/Emitter";
import { ViewOptions } from "./Widget";
export class Button extends Control {
readonly element: HTMLButtonElement = create_element("button", { class: "core_Button" });
private readonly _click = emitter<MouseEvent>();
readonly click: Observable<MouseEvent> = this._click;
readonly click: Observable<MouseEvent>;
constructor(text: string) {
super();
private readonly _click: Emitter<MouseEvent> = emitter<MouseEvent>();
constructor(text: string, options?: ViewOptions) {
super(options);
this.click = this._click;
this.element.append(create_element("span", { class: "core_Button_inner", text }));
@ -19,4 +24,9 @@ export class Button extends Control {
this.element.onclick = (e: MouseEvent) => this._click.emit({ value: e });
}
protected set_enabled(enabled: boolean): void {
super.set_enabled(enabled);
this.element.disabled = !enabled;
}
}

View File

@ -1,27 +1,36 @@
import { create_element } from "./dom";
import { WritableProperty } from "../observable/WritableProperty";
import { property } from "../observable";
import { LabelledControl } from "./LabelledControl";
import { LabelledControl, LabelledControlOptions } from "./LabelledControl";
import { WidgetProperty } from "../observable/WidgetProperty";
export type CheckBoxOptions = LabelledControlOptions;
export class CheckBox extends LabelledControl {
readonly element: HTMLInputElement = create_element("input", { class: "core_CheckBox" });
readonly checked: WritableProperty<boolean> = property(false);
readonly preferred_label_position = "right";
constructor(checked: boolean = false, label?: string) {
super(label);
readonly checked: WritableProperty<boolean>;
private readonly _checked: WidgetProperty<boolean>;
constructor(checked: boolean = false, options?: CheckBoxOptions) {
super(options);
this._checked = new WidgetProperty(this, checked, this.set_checked);
this.checked = this._checked;
this.set_checked(checked);
this.element.type = "checkbox";
this.element.onchange = () => (this.checked.val = this.element.checked);
this.element.onchange = () => (this._checked.val = this.element.checked);
}
this.disposables(
this.checked.observe(({ value }) => (this.element.checked = value)),
protected set_enabled(enabled: boolean): void {
super.set_enabled(enabled);
this.element.disabled = !enabled;
}
this.enabled.observe(({ value }) => (this.element.disabled = !value)),
);
this.checked.val = checked;
protected set_checked(checked: boolean): void {
this.element.checked = checked;
}
}

View File

@ -1,7 +1,3 @@
import { View } from "./View";
import { WritableProperty } from "../observable/WritableProperty";
import { property } from "../observable";
import { Widget } from "./Widget";
export abstract class Control extends View {
readonly enabled: WritableProperty<boolean> = property(true);
}
export abstract class Control extends Widget {}

View File

@ -4,22 +4,26 @@ import "./Button.css";
import { property } from "../observable";
import { Property } from "../observable/Property";
import { Control } from "./Control";
import { WritableProperty } from "../observable/WritableProperty";
export class FileButton extends Control {
readonly element: HTMLLabelElement = create_element("label", {
class: "core_FileButton core_Button",
});
private readonly _files = property<File[]>([]);
readonly files: Property<File[]> = this._files;
readonly files: Property<File[]>;
private input: HTMLInputElement = create_element("input", {
class: "core_FileButton_input core_Button_inner",
});
private readonly _files: WritableProperty<File[]> = property<File[]>([]);
constructor(text: string, accept: string = "") {
super();
this.files = this._files;
this.input.type = "file";
this.input.accept = accept;
this.input.onchange = () => {

View File

@ -1,9 +1,12 @@
/* eslint-disable no-dupe-class-members */
import { LabelledControl } from "./LabelledControl";
import { LabelledControl, LabelledControlOptions } from "./LabelledControl";
import { create_element } from "./dom";
import { WritableProperty } from "../observable/WritableProperty";
import { is_any_property, Property } from "../observable/Property";
import "./Input.css";
import { WidgetProperty } from "../observable/WidgetProperty";
export type InputOptions = LabelledControlOptions;
export abstract class Input<T> extends LabelledControl {
readonly element: HTMLElement;
@ -12,16 +15,20 @@ export abstract class Input<T> extends LabelledControl {
protected readonly input: HTMLInputElement;
private readonly _value: WidgetProperty<T>;
private ignore_input_change = false;
protected constructor(
value: WritableProperty<T>,
value: T,
class_name: string,
input_type: string,
input_class_name: string,
label?: string,
options?: InputOptions,
) {
super(label);
super(options);
this.value = value;
this._value = new WidgetProperty<T>(this, value, this.set_value);
this.value = this._value;
this.element = create_element("span", { class: `${class_name} core_Input` });
@ -30,47 +37,26 @@ export abstract class Input<T> extends LabelledControl {
});
this.input.type = input_type;
this.input.onchange = () => {
if (this.input_value_changed()) {
this.value.val = this.get_input_value();
}
this._value.val = this.get_value();
};
this.set_input_value(value.val);
this.element.append(this.input);
this.disposables(
this.value.observe(({ value }) => {
this.set_input_value(value);
}),
this.enabled.observe(({ value }) => {
this.input.disabled = !value;
if (value) {
this.element.classList.remove("disabled");
} else {
this.element.classList.add("disabled");
}
}),
);
}
set_value(value: T, options: { silent?: boolean } = {}): void {
this.value.set_val(value, options);
if (options.silent) {
this.set_input_value(value);
}
protected set_enabled(enabled: boolean): void {
super.set_enabled(enabled);
this.input.disabled = !enabled;
}
protected input_value_changed(): boolean {
return true;
protected abstract get_value(): T;
protected abstract set_value(value: T): void;
protected ignore_change(f: () => void): void {
this.ignore_input_change = true;
f();
}
protected abstract get_input_value(): T;
protected abstract set_input_value(value: T): void;
protected set_attr<T>(attr: InputAttrsOfType<T>, value?: T | Property<T>): void;
protected set_attr<T, U>(
attr: InputAttrsOfType<U>,

View File

@ -1,39 +1,34 @@
import { View } from "./View";
import { ViewOptions, Widget } from "./Widget";
import { create_element } from "./dom";
import { WritableProperty } from "../observable/WritableProperty";
import "./Label.css";
import { property } from "../observable";
import { Property } from "../observable/Property";
import { WidgetProperty } from "../observable/WidgetProperty";
export class Label extends View {
export class Label extends Widget {
readonly element = create_element<HTMLLabelElement>("label", { class: "core_Label" });
set for(id: string) {
this.element.htmlFor = id;
}
readonly enabled: WritableProperty<boolean> = property(true);
readonly text: WritableProperty<string>;
constructor(text: string | Property<string>, options: { enabled?: boolean } = {}) {
super();
private readonly _text = new WidgetProperty<string>(this, "", this.set_text);
constructor(text: string | Property<string>, options?: ViewOptions) {
super(options);
this.text = this._text;
if (typeof text === "string") {
this.element.append(text);
this.set_text(text);
} else {
this.element.append(text.val);
this.disposable(text.observe(({ value }) => (this.element.textContent = value)));
this.disposable(this._text.bind_to(text));
}
}
this.disposables(
this.enabled.observe(({ value }) => {
if (value) {
this.element.classList.remove("disabled");
} else {
this.element.classList.add("disabled");
}
}),
);
if (options.enabled != undefined) this.enabled.val = options.enabled;
protected set_text(text: string): void {
this.element.textContent = text;
}
}

View File

@ -1,12 +1,14 @@
import { Label } from "./Label";
import { Control } from "./Control";
import { ViewOptions } from "./Widget";
export type LabelledControlOptions = ViewOptions & {
label?: string;
};
export abstract class LabelledControl extends Control {
abstract readonly preferred_label_position: "left" | "right" | "top" | "bottom";
private readonly _label_text: string;
private _label?: Label;
get label(): Label {
if (!this._label) {
this._label = this.disposable(new Label(this._label_text));
@ -21,10 +23,13 @@ export abstract class LabelledControl extends Control {
return this._label;
}
protected constructor(label: string | undefined) {
super();
private readonly _label_text: string;
private _label?: Label;
this._label_text = label || "";
protected constructor(options?: LabelledControlOptions) {
super(options);
this._label_text = (options && options.label) || "";
}
}

View File

@ -1,41 +0,0 @@
import { View } from "./View";
import { create_element } from "./dom";
import { Resizable } from "./Resizable";
import { ResizableView } from "./ResizableView";
export class LazyView extends ResizableView {
readonly element = create_element("div", { class: "core_LazyView" });
private initialized = false;
private view: View & Resizable | undefined;
constructor(private create_view: () => Promise<View & Resizable>) {
super();
this.visible.val = false;
this.disposables(
this.visible.observe(({ value }) => {
if (value && !this.initialized) {
this.initialized = true;
this.create_view().then(view => {
this.view = this.disposable(view);
this.view.resize(this.width, this.height);
this.element.append(view.element);
});
}
}),
);
}
resize(width: number, height: number): this {
super.resize(width, height);
if (this.view) {
this.view.resize(width, height);
}
return this;
}
}

View File

@ -0,0 +1,43 @@
import { Widget } from "./Widget";
import { create_element } from "./dom";
import { Resizable } from "./Resizable";
import { ResizableWidget } from "./ResizableWidget";
export class LazyWidget extends ResizableWidget {
readonly element = create_element("div", { class: "core_LazyView" });
private initialized = false;
private view: Widget & Resizable | undefined;
constructor(private create_view: () => Promise<Widget & Resizable>) {
super();
this.visible.val = false;
}
protected set_visible(visible: boolean): void {
super.set_visible(visible);
if (visible && !this.initialized) {
this.initialized = true;
this.create_view().then(view => {
if (!this.disposed) {
this.view = this.disposable(view);
this.view.resize(this.width, this.height);
this.element.append(view.element);
}
});
}
}
resize(width: number, height: number): this {
super.resize(width, height);
if (this.view) {
this.view.resize(width, height);
}
return this;
}
}

View File

@ -1,17 +1,15 @@
import { property } from "../observable";
import { Property } from "../observable/Property";
import { Input } from "./Input";
import { Input, InputOptions } from "./Input";
import "./NumberInput.css";
export class NumberInput extends Input<number> {
readonly preferred_label_position = "left";
private readonly rounding_factor: number;
private rounded_value: number = 0;
constructor(
value: number = 0,
options: {
options: InputOptions & {
label?: string;
min?: number | Property<number>;
max?: number | Property<number>;
@ -20,13 +18,7 @@ export class NumberInput extends Input<number> {
round_to?: number;
} = {},
) {
super(
property(value),
"core_NumberInput",
"number",
"core_NumberInput_inner",
options.label,
);
super(value, "core_NumberInput", "number", "core_NumberInput_inner", options);
const { min, max, step } = options;
this.set_attr("min", min, String);
@ -40,18 +32,18 @@ export class NumberInput extends Input<number> {
}
this.element.style.width = `${options.width == undefined ? 54 : options.width}px`;
this.set_value(value);
}
protected input_value_changed(): boolean {
return this.input.valueAsNumber !== this.rounded_value;
}
protected get_input_value(): number {
protected get_value(): number {
return this.input.valueAsNumber;
}
protected set_input_value(value: number): void {
this.input.valueAsNumber = this.rounded_value =
Math.round(this.rounding_factor * value) / this.rounding_factor;
protected set_value(value: number): void {
this.ignore_change(() => {
this.input.valueAsNumber =
Math.round(this.rounding_factor * value) / this.rounding_factor;
});
}
}

View File

@ -1,8 +1,8 @@
import { ResizableView } from "./ResizableView";
import { ResizableWidget } from "./ResizableWidget";
import { create_element } from "./dom";
import { Renderer } from "../rendering/Renderer";
export class RendererView extends ResizableView {
export class RendererWidget extends ResizableWidget {
readonly element = create_element("div");
constructor(private renderer: Renderer) {

View File

@ -1,7 +1,7 @@
import { View } from "./View";
import { Widget } from "./Widget";
import { Resizable } from "./Resizable";
export abstract class ResizableView extends View implements Resizable {
export abstract class ResizableWidget extends Widget implements Resizable {
protected width: number = 0;
protected height: number = 0;

View File

@ -1,21 +1,21 @@
import { View } from "./View";
import { Widget } from "./Widget";
import { create_element } from "./dom";
import { LazyView } from "./LazyView";
import { LazyWidget } from "./LazyWidget";
import { Resizable } from "./Resizable";
import { ResizableView } from "./ResizableView";
import { ResizableWidget } from "./ResizableWidget";
import "./TabContainer.css";
export type Tab = {
title: string;
key: string;
create_view: () => Promise<View & Resizable>;
create_view: () => Promise<Widget & Resizable>;
};
type TabInfo = Tab & { tab_element: HTMLSpanElement; lazy_view: LazyView };
type TabInfo = Tab & { tab_element: HTMLSpanElement; lazy_view: LazyWidget };
const BAR_HEIGHT = 28;
export class TabContainer extends ResizableView {
export class TabContainer extends ResizableWidget {
readonly element = create_element("div", { class: "core_TabContainer" });
private tabs: TabInfo[] = [];
@ -35,7 +35,7 @@ export class TabContainer extends ResizableView {
});
this.bar_element.append(tab_element);
const lazy_view = new LazyView(tab.create_view);
const lazy_view = new LazyWidget(tab.create_view);
this.tabs.push({
...tab,

View File

@ -1,8 +1,16 @@
import { LabelledControl } from "./LabelledControl";
import { LabelledControl, LabelledControlOptions } from "./LabelledControl";
import { el } from "./dom";
import { property } from "../observable";
import { WritableProperty } from "../observable/WritableProperty";
import "./TextArea.css";
import { WidgetProperty } from "../observable/WidgetProperty";
export type TextAreaOptions = LabelledControlOptions & {
max_length?: number;
font_family?: string;
rows?: number;
cols?: number;
};
export class TextArea extends LabelledControl {
readonly element: HTMLElement = el.div({ class: "core_TextArea" });
@ -15,17 +23,10 @@ export class TextArea extends LabelledControl {
class: "core_TextArea_inner",
});
constructor(
value = "",
options?: {
label?: string;
max_length?: number;
font_family?: string;
rows?: number;
cols?: number;
},
) {
super(options && options.label);
private readonly _value = new WidgetProperty<string>(this, "", this.set_value);
constructor(value = "", options?: TextAreaOptions) {
super(options);
if (options) {
if (options.max_length != undefined) this.text_element.maxLength = options.max_length;
@ -35,12 +36,15 @@ export class TextArea extends LabelledControl {
if (options.cols != undefined) this.text_element.cols = options.cols;
}
this.value = property(value);
this.value = this._value;
this.set_value(value);
this.text_element.onchange = () => (this.value.val = this.text_element.value);
this.disposables(this.value.observe(({ value }) => (this.text_element.value = value)));
this.text_element.onchange = () => (this._value.val = this.text_element.value);
this.element.append(this.text_element);
}
protected set_value(value: string): void {
this.text_element.value = value;
}
}

View File

@ -1,36 +1,29 @@
import { Input } from "./Input";
import { Input, InputOptions } from "./Input";
import { Property } from "../observable/Property";
import { property } from "../observable";
export type TextInputOptions = InputOptions & {
max_length?: number | Property<number>;
};
export class TextInput extends Input<string> {
readonly preferred_label_position = "left";
constructor(
value = "",
options?: {
label?: string;
max_length?: number | Property<number>;
},
) {
super(
property(value),
"core_TextInput",
"text",
"core_TextInput_inner",
options && options.label,
);
constructor(value = "", options?: TextInputOptions) {
super(value, "core_TextInput", "text", "core_TextInput_inner", options);
if (options) {
const { max_length } = options;
this.set_attr("maxLength", max_length);
}
this.set_value(value);
}
protected get_input_value(): string {
protected get_value(): string {
return this.input.value;
}
protected set_input_value(value: string): void {
protected set_value(value: string): void {
this.input.value = value;
}
}

View File

@ -1,13 +1,14 @@
import { View } from "./View";
import { Widget } from "./Widget";
import { create_element } from "./dom";
import "./ToolBar.css";
import { LabelledControl } from "./LabelledControl";
export class ToolBar extends View {
export class ToolBar extends Widget {
readonly element = create_element("div", { class: "core_ToolBar" });
readonly height = 33;
constructor(...children: View[]) {
constructor(...children: Widget[]) {
super();
this.element.style.height = `${this.height}px`;

View File

@ -3,9 +3,11 @@ import { Disposer } from "../observable/Disposer";
import { Observable } from "../observable/Observable";
import { bind_hidden } from "./dom";
import { WritableProperty } from "../observable/WritableProperty";
import { property } from "../observable";
import { WidgetProperty } from "../observable/WidgetProperty";
export abstract class View implements Disposable {
export type ViewOptions = {};
export abstract class Widget implements Disposable {
abstract readonly element: HTMLElement;
get id(): string {
@ -16,12 +18,18 @@ export abstract class View implements Disposable {
this.element.id = id;
}
readonly visible: WritableProperty<boolean> = property(true);
readonly visible: WritableProperty<boolean>;
readonly enabled: WritableProperty<boolean>;
protected disposed = false;
private disposer = new Disposer();
private _visible = new WidgetProperty<boolean>(this, true, this.set_visible);
private _enabled = new WidgetProperty<boolean>(this, true, this.set_enabled);
constructor() {
this.disposables(this.visible.observe(({ value }) => (this.element.hidden = !value)));
constructor(_options?: ViewOptions) {
this.visible = this._visible;
this.enabled = this._enabled;
}
focus(): void {
@ -31,6 +39,19 @@ export abstract class View implements Disposable {
dispose(): void {
this.element.remove();
this.disposer.dispose();
this.disposed = true;
}
protected set_visible(visible: boolean): void {
this.element.hidden = !visible;
}
protected set_enabled(enabled: boolean): void {
if (enabled) {
this.element.classList.remove("disabled");
} else {
this.element.classList.add("disabled");
}
}
protected bind_hidden(element: HTMLElement, observable: Observable<boolean>): void {

View File

@ -0,0 +1,13 @@
import { SimpleProperty } from "./SimpleProperty";
import { Widget } from "../gui/Widget";
export class WidgetProperty<T> extends SimpleProperty<T> {
constructor(private widget: Widget, val: T, private set_value: (this: Widget, val: T) => void) {
super(val);
}
set_val(val: T, options?: { silent?: boolean }): void {
this.set_value.call(this.widget, val);
super.set_val(val, options);
}
}

View File

@ -1,4 +1,4 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { el } from "../../core/gui/dom";
import { editor } from "monaco-editor";
import { asm_editor_store } from "../stores/AsmEditorStore";
@ -25,7 +25,7 @@ editor.defineTheme("phantasmal-world", {
const DUMMY_MODEL = editor.createModel("", "psoasm");
export class AsmEditorView extends ResizableView {
export class AsmEditorView extends ResizableWidget {
readonly element = el.div();
private readonly editor: IStandaloneCodeEditor = this.disposable(

View File

@ -1,9 +1,9 @@
import { View } from "../../core/gui/View";
import { Widget } from "../../core/gui/Widget";
import { el } from "../../core/gui/dom";
import { Label } from "../../core/gui/Label";
import "./DisabledView.css";
export class DisabledView extends View {
export class DisabledView extends Widget {
readonly element = el.div({ class: "quest_editor_DisabledView" });
private readonly label: Label;

View File

@ -1,4 +1,4 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { el } from "../../core/gui/dom";
import { DisabledView } from "./DisabledView";
import { quest_editor_store } from "../stores/QuestEditorStore";
@ -11,7 +11,7 @@ import { Property } from "../../core/observable/Property";
import { Vec3 } from "../../core/data_formats/vector";
import { QuestEntityModel } from "../model/QuestEntityModel";
export class EntityInfoView extends ResizableView {
export class EntityInfoView extends ResizableWidget {
readonly element = el.div({ class: "quest_editor_EntityInfoView", tab_index: -1 });
private readonly no_entity_view = new DisabledView("No entity selected.");
@ -153,9 +153,9 @@ export class EntityInfoView extends ResizableView {
this.entity_disposer.add_all(
pos.observe(
({ value: { x, y, z } }) => {
x_input.set_value(x, { silent: true });
y_input.set_value(y, { silent: true });
z_input.set_value(z, { silent: true });
x_input.value.set_val(x, { silent: true });
y_input.value.set_val(y, { silent: true });
z_input.value.set_val(z, { silent: true });
},
{ call_now: true },
),

View File

@ -1,4 +1,4 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { el } from "../../core/gui/dom";
import { quest_editor_store } from "../stores/QuestEditorStore";
import { npc_data, NpcType } from "../../core/data_formats/parsing/quest/npc_types";
@ -6,7 +6,7 @@ import { QuestModel } from "../model/QuestModel";
import "./NpcCountsView.css";
import { DisabledView } from "./DisabledView";
export class NpcCountsView extends ResizableView {
export class NpcCountsView extends ResizableWidget {
readonly element = el.div({ class: "quest_editor_NpcCountsView" });
private readonly table_element = el.table();

View File

@ -1,4 +1,4 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { el } from "../../core/gui/dom";
import { quest_editor_store } from "../stores/QuestEditorStore";
import { Episode } from "../../core/data_formats/parsing/quest/Episode";
@ -9,7 +9,7 @@ import { TextArea } from "../../core/gui/TextArea";
import "./QuesInfoView.css";
import { DisabledView } from "./DisabledView";
export class QuesInfoView extends ResizableView {
export class QuesInfoView extends ResizableWidget {
readonly element = el.div({ class: "quest_editor_QuesInfoView", tab_index: -1 });
private readonly table_element = el.table();

View File

@ -1,4 +1,4 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { create_element } from "../../core/gui/dom";
import { ToolBarView } from "./ToolBarView";
import GoldenLayout, { Container, ContentItem, ItemConfigType } from "golden-layout";
@ -15,7 +15,7 @@ import { EntityInfoView } from "./EntityInfoView";
const logger = Logger.get("quest_editor/gui/QuestEditorView");
// Don't change these values, as they are persisted in the user's browser.
const VIEW_TO_NAME = new Map<new () => ResizableView, string>([
const VIEW_TO_NAME = new Map<new () => ResizableWidget, string>([
[QuesInfoView, "quest_info"],
[NpcCountsView, "npc_counts"],
[QuestRendererView, "quest_renderer"],
@ -91,7 +91,7 @@ const DEFAULT_LAYOUT_CONTENT: ItemConfigType[] = [
},
];
export class QuestEditorView extends ResizableView {
export class QuestEditorView extends ResizableWidget {
readonly element = create_element("div", { class: "quest_editor_QuestEditorView" });
private readonly tool_bar_view = this.disposable(new ToolBarView());
@ -99,7 +99,7 @@ export class QuestEditorView extends ResizableView {
private readonly layout_element = create_element("div", { class: "quest_editor_gl_container" });
private readonly layout: Promise<GoldenLayout>;
private readonly sub_views = new Map<string, ResizableView>();
private readonly sub_views = new Map<string, ResizableWidget>();
constructor() {
super();

View File

@ -1,14 +1,14 @@
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { el } from "../../core/gui/dom";
import { RendererView } from "../../core/gui/RendererView";
import { RendererWidget } from "../../core/gui/RendererWidget";
import { QuestRenderer } from "../rendering/QuestRenderer";
import { gui_store, GuiTool } from "../../core/stores/GuiStore";
import { quest_editor_store } from "../stores/QuestEditorStore";
export class QuestRendererView extends ResizableView {
export class QuestRendererView extends ResizableWidget {
readonly element = el.div({ class: "quest_editor_QuestRendererView", tab_index: -1 });
private renderer_view = this.disposable(new RendererView(new QuestRenderer()));
private renderer_view = this.disposable(new RendererWidget(new QuestRenderer()));
constructor() {
super();

View File

@ -1,11 +1,11 @@
import { View } from "../../core/gui/View";
import { Widget } from "../../core/gui/Widget";
import { ToolBar } from "../../core/gui/ToolBar";
import { FileButton } from "../../core/gui/FileButton";
import { Button } from "../../core/gui/Button";
import { quest_editor_store } from "../stores/QuestEditorStore";
import { undo_manager } from "../../core/undo/UndoManager";
export class ToolBarView extends View {
export class ToolBarView extends Widget {
private readonly open_file_button = new FileButton("Open file...", ".qst");
private readonly save_as_button = new Button("Save as...");
private readonly undo_button = new Button("Undo");

View File

@ -1,12 +1,12 @@
import { create_element } from "../../core/gui/dom";
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { ToolBar } from "../../core/gui/ToolBar";
import "./Model3DView.css";
import { model_store } from "../stores/Model3DStore";
import { WritableProperty } from "../../core/observable/WritableProperty";
import { RendererView } from "../../core/gui/RendererView";
import { RendererWidget } from "../../core/gui/RendererWidget";
import { Model3DRenderer } from "../rendering/Model3DRenderer";
import { View } from "../../core/gui/View";
import { Widget } from "../../core/gui/Widget";
import { FileButton } from "../../core/gui/FileButton";
import { CheckBox } from "../../core/gui/CheckBox";
import { NumberInput } from "../../core/gui/NumberInput";
@ -17,7 +17,7 @@ import { PSO_FRAME_RATE } from "../../core/rendering/conversion/ninja_animation"
const MODEL_LIST_WIDTH = 100;
const ANIMATION_LIST_WIDTH = 140;
export class Model3DView extends ResizableView {
export class Model3DView extends ResizableWidget {
readonly element = create_element("div", { class: "viewer_Model3DView" });
private tool_bar_view = this.disposable(new ToolBarView());
@ -28,7 +28,7 @@ export class Model3DView extends ResizableView {
private animation_list_view = this.disposable(
new ModelSelectListView(model_store.animations, model_store.current_animation),
);
private renderer_view = this.disposable(new RendererView(new Model3DRenderer()));
private renderer_view = this.disposable(new RendererWidget(new Model3DRenderer()));
constructor() {
super();
@ -74,10 +74,10 @@ export class Model3DView extends ResizableView {
}
}
class ToolBarView extends View {
class ToolBarView extends Widget {
private readonly open_file_button = new FileButton("Open file...", ".nj, .njm, .xj, .xvm");
private readonly skeleton_checkbox = new CheckBox(false, "Show skeleton");
private readonly play_animation_checkbox = new CheckBox(true, "Play animation");
private readonly skeleton_checkbox = new CheckBox(false, { label: "Show skeleton" });
private readonly play_animation_checkbox = new CheckBox(true, { label: "Play animation" });
private readonly animation_frame_rate_input = new NumberInput(PSO_FRAME_RATE, {
label: "Frame rate:",
min: 1,
@ -144,7 +144,7 @@ class ToolBarView extends View {
}
}
class ModelSelectListView<T extends { name: string }> extends ResizableView {
class ModelSelectListView<T extends { name: string }> extends ResizableWidget {
element = create_element("ul", { class: "viewer_ModelSelectListView" });
set borders(borders: boolean) {

View File

@ -1,20 +1,20 @@
import { create_element } from "../../core/gui/dom";
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { FileButton } from "../../core/gui/FileButton";
import { ToolBar } from "../../core/gui/ToolBar";
import { texture_store } from "../stores/TextureStore";
import { RendererView } from "../../core/gui/RendererView";
import { RendererWidget } from "../../core/gui/RendererWidget";
import { TextureRenderer } from "../rendering/TextureRenderer";
import { gui_store, GuiTool } from "../../core/stores/GuiStore";
export class TextureView extends ResizableView {
export class TextureView extends ResizableWidget {
readonly element = create_element("div", { class: "viewer_TextureView" });
private readonly open_file_button = new FileButton("Open file...", ".xvm");
private readonly tool_bar = this.disposable(new ToolBar(this.open_file_button));
private readonly renderer_view = this.disposable(new RendererView(new TextureRenderer()));
private readonly renderer_view = this.disposable(new RendererWidget(new TextureRenderer()));
constructor() {
super();

View File

@ -1,7 +1,7 @@
import { TabContainer } from "../../core/gui/TabContainer";
import { ResizableView } from "../../core/gui/ResizableView";
import { ResizableWidget } from "../../core/gui/ResizableWidget";
export class ViewerView extends ResizableView {
export class ViewerView extends ResizableWidget {
private tabs = this.disposable(
new TabContainer(
{

View File

@ -57,9 +57,9 @@ export class Model3DStore implements Disposable {
readonly show_skeleton: WritableProperty<boolean> = property(false);
readonly current_animation: WritableProperty<CharacterClassAnimationModel | undefined> = property(
undefined,
);
readonly current_animation: WritableProperty<
CharacterClassAnimationModel | undefined
> = property(undefined);
private readonly _current_nj_motion = property<NjMotion | undefined>(undefined);
readonly current_nj_motion: Property<NjMotion | undefined> = this._current_nj_motion;