/src/objecteditor.ts
import FragmentManager from './fragmentmanager';
import { GameObject } from './object';
import { ID } from './id';
import gs from './gamestate';
export default class ObjectEditor {
container: FragmentManager
listRef: HTMLSelectElement
idRef: HTMLInputElement
nameRef: HTMLInputElement
descriptionRef: HTMLTextAreaElement
originalID: ID
constructor() {
this.container = new FragmentManager(`
<div class="box vflex">
<h1>Object Editor</h1>
<div class="hflex flex-auto">
<div class="vflex" style="width: 200px; margin-right: 8px">
<select multiple name="objectlist" class="flex-auto" style="width: calc(100% - 8px)">
</select>
<div class="hflex">
<button id="object-add" class="flex-auto">+</button>
<button id="object-remove" class="flex-auto">-</button>
</div>
</div>
<div class="vflex flex-auto">
<h2>ID</h2>
<input name="id">
<h2>Name</h2>
<input name="name">
<h2>Description</h2>
<textarea name="description" class="flex-auto"></textarea>
</div>
</div>
<div class="hflex">
<button id="object-editor-close">Close</button>
</div>
</div>
`);
this.container.mountInto('object-editor-container');
this.container.elem.addEventListener('keydown', function(e: KeyboardEvent) {
e.cancelBubble = true;
});
this.listRef = <HTMLSelectElement>this.container.q('[name="objectlist"]');
this.idRef = <HTMLInputElement>this.container.q('[name="id"]');
this.nameRef = <HTMLInputElement>this.container.q('[name="name"]');
this.descriptionRef = <HTMLTextAreaElement>this.container.q('[name=description]');
const closeButton = this.container.q('#object-editor-close');
closeButton.addEventListener('click', this.closeHandler.bind(this));
const objectAddButton = this.container.q('#object-add');
objectAddButton.addEventListener('click', this.createObject.bind(this));
const objectRemoveButton = this.container.q('#object-remove');
objectRemoveButton.addEventListener('click', this.deleteObject.bind(this));
this.listRef.addEventListener('change', event => {
const id = (<HTMLInputElement>event.target).value;
this.commitObject();
this.selectObject(id);
});
}
open(object?: GameObject) {
this.refreshObjectList();
if (object) {
this.selectObject(object.id);
}
this.container.elem.classList.add('visible');
this.nameRef.focus();
}
refreshObjectList() {
while (this.listRef.firstChild)
this.listRef.removeChild(this.listRef.firstChild);
for (let [k, v] of gs.objects) {
const option = document.createElement('option');
option.value = k;
option.innerText = v.name;
this.listRef.appendChild(option);
}
}
selectObject(id?: ID) {
if (id) {
if (!gs.objects.has(id)) {
throw new Error('Invalid object ID: ' + id);
}
}
for (let i = 0; i < this.listRef.children.length; i++) {
const child = <HTMLOptionElement>this.listRef.children[i];
child.selected = child.value == id;
}
if (id) {
const object = gs.objects.get(id);
this.idRef.value = this.originalID = object.id;
this.nameRef.value = object.name || 'Unnamed Object';
this.descriptionRef.value = object.description || '';
} else {
this.originalID = undefined;
this.idRef.value = '';
this.nameRef.value = '';
this.descriptionRef.value = '';
}
}
createObject() {
this.commitObject();
const obj = new GameObject();
obj.name = 'Unnamed Object';
gs.addObject(obj);
this.refreshObjectList();
this.selectObject(obj.id);
}
deleteObject() {
this.commitObject();
const objID = this.originalID;
const obj = gs.objects.get(objID);
if (window.confirm("Really delete " + obj.name + "?")) {
gs.removeObject(objID);
this.refreshObjectList();
this.selectObject(null);
}
}
commitObject() {
if (!this.originalID) return;
const obj = gs.objects.get(this.originalID);
obj.name = this.nameRef.value;
obj.description = this.descriptionRef.value;
const objID = this.idRef.value
if (objID != this.originalID) {
gs.removeObject(this.originalID);
obj.id = objID;
gs.addObject(obj);
this.refreshObjectList();
this.selectObject(objID);
} else {
this.refreshObjectList();
}
}
close() {
this.closeHandler();
}
closeHandler() {
this.commitObject();
this.container.elem.classList.remove('visible');
}
}