/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'); } }