Browse Source

CTRLNameTablesStore created (untested). Added UI elements for CTRLNameTableStore (not fully complete).

dev
Bryan Miller 5 years ago
parent
commit
7c836337e0
3 changed files with 327 additions and 1 deletions
  1. +314
    -0
      app/js/ctrls/CTRLNameTablesStore.js
  2. +1
    -1
      views/index.html
  3. +12
    -0
      views/nametableListItem.html

+ 314
- 0
app/js/ctrls/CTRLNameTablesStore.js View File

@@ -0,0 +1,314 @@
import GlobalEvents from "/app/js/common/EventCaller.js";
import Utils from "/app/js/common/Utils.js";
import JSONSchema from "/app/js/common/JSONSchema.js";
import EditableText from "/app/js/ui/EditableText.js";
import Renderer from "/app/js/ui/Renderer.js";
import NESNameTable from "/app/js/models/NESNameTable.js";
import NESPalette from "/app/js/models/NESPalette.js";
import CTRLBanksStore from "/app/js/ctrls/CTRLBanksStore.js";

const NTLI_TEMPLATE = "nametable-list-item-template";
const NTLI_CANVAS = "nametable-img";
const NTLI_TITLE = "title";
const NTLI_SELECTED = "list-item-selected";


var Nametables = {};
var CurrentNT = "";


const SCHEMA_ID="http://nespaint/NametableStoreSchema.json";
JSONSchema.add({
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": SCHEMA_ID,
"type": "array",
"items":{
"type": "object",
"properties":{
"name":{
"type": "string",
"minLength": 1
},
"data":{
"type": "string",
"media": {
"binaryEncoding": "base64"
}
},
"bank":{
"type": "string",
"minLength": 1
}
},
"required":["name", "data"]
}
});


function HANDLE_NTClick(e){
var name = this.getAttribute("ntname");
if (name !== CurrentNT){
if (CurrentNT !== "")
Nametables[CurrentNT].el.classList.remove(NTLI_SELECTED);
CurrentNT = name;
Nametables[CurrentNT].el.classList.add(NTLI_SELECTED);
GlobalEvents.emit("change_surface", Nametables[CurrentNT].nametable);
}
}


function SetElNTName(el, name){
var et = new EditableText(el, "title");
et.listen("value_change", (v) => {el.setAttribute("ntname", v);});
et.value = name;
return et;
}


var RenderNametableToEl = Utils.throttle(function(el, nametable){
var cnv = el.querySelector("." + NTLI_CANVAS);
var ctx = cnv.getContext("2d");

Renderer.renderToFit(nametable, ctx);
}, 500); // Only update twice a second.


function HANDLE_NametableDataChange(nametable, e){
RenderNametableToEl(this, nametable);
}

function ConnectElementToNametable(el, nametable){
nametable.listen("data_changed", HANDLE_NametableDataChange.bind(el, nametable));
}


function CreateNametableDOMEntry(name, nametable){
var baseel = document.querySelector("." + NTLI_TEMPLATE);
if (!baseel){
console.log("WARNING: Failed to find nametable list item template.");
return null;
}
var el = baseel.cloneNode(true);
el.classList.remove(NTLI_TEMPLATE);
el.classList.remove("hidden");
el.setAttribute("ntname", name);
ConnectElementToNametable(el, nametable);
el.addEventListener("click", HANDLE_NametableClick);
baseel.parentNode.appendChild(el);
setTimeout(()=>{
RenderNametableToEl(el, nametable);
}, 500); // Make the render call in about a half second. Allow DOM time to catch up?
return el;
}


class CTRLNametablesStore{
constructor(){
var HANDLE_ChangeSurface = function(surf){
if (!(surf instanceof NESNameTable)){
if (CurrentNT !== ""){
Nametables[CurrentNT].el.classList.remove(NTLI_SELECTED);
CurrentNT = "";
}
} else {
if (Nametables.length <= 0 || (CurrentNT !== "" && Nametables[CurrentNT].nametable !== surf)){
console.log("WARNING: Nametable object being set outside of Nametables Store.");
}
}
}
GlobalEvents.listen("change_surface", HANDLE_ChangeSurface);


GlobalEvents.listen("ntstore-add", (function(ev){
GlobalEvents.emit("modal-close");
var e = document.querySelector(".nt-store-add");
if (e){
var eform = e.querySelector("form");
var einput = e.querySelector('input[name="storeitemname"]');
if (eform && einput){
var name = einput.value;
eform.reset();
this.createNametable(name);
this.activateNametable(name);
}
}
}).bind(this));

GlobalEvents.listen("ntstore-remove", (function(e){
if (CurrentNT !== "")
this.removeNametable(CurrentNT);
}).bind(this));
}

get length(){
return Object.keys(Nametables).length;
}

get obj(){
var data = [];
Object.keys(Nametables).forEach((key) => {
if (Nametables.hasOwnProperty(key)){
jdata = {
name: key,
data: Nametables[key].nametable.base64
};
if (Nametables[key].nametable.bank !== null){
var bankname = CTRLBanksStore.getBankName(Nametables[key].nametable.bank);
if (bankname !== null)
jdata.bank = bankname;
}
data.push(jdata);
}
});
return data;
}

set obj(d){
var validator = JSONSchema.getValidator(SCHEMA_ID);
if (validator !== null && validator(d)){
this.clear();
d.forEach((item) => {
this.createNametable(item.name, item.data);
if ("bank" in item){
var bnk = CTRLBanksStore.getBank(item.bank);
if (bnk !== null && item.name in Nametables)
Nametables[item.name].nametable.bank = bnk;
}
});
} else {
var errs = JSONSchema.getLastErrors();
if (errs !== null){
console.log(errs);
}
throw new Error("Object failed to validate against NametableStoreSchema.");
}
}

get json(){
return JSON.stringify(this.obj);
}

set json(j){
try {
this.obj = JSON.parse(j);
} catch (e) {
throw e;
}
}

get currentNametable(){
return (CurrentNT === "") ? null : Nametables[CurrentNT].nametable;
}

get currentNTName(){
return CurrentNT;
}

get keys(){
return Object.keys(Nametables);
}

initialize(){
if (this.length <= 0){
this.createNametable("Nametable");
}
return this;
}


createBank(name, bbase64){
if (!(name in Nametables)){
var nametable = new NESNameTable();
if (typeof(bbase64) === "string"){
try {
nametable.base64 = bbase64;
} catch (e) {
console.log("Failed to create Nametable. " + e.toString());
nametable = null;
}
}
if (nametable !== null){
var el = CreateNametableDOMEntry(name, nametable);
if (el){
var elname = SetElNTName(el, name);
Nametables[name] = {nametable:nametable, el:el, elname:elname};

if (this.length <= 1){
Nametables[name].el.click();
}
}
}
}
return this;
}


removeBank(name){
if (name in Nametables){
if (name === CurrentNT){
var keys = Object.keys(Nametables);
if (keys.length > 1){
CurrentNT = (keys[0] !== name) ? keys[0] : keys[1];
} else {
CurrentNT = "";
}
}
Nametables[name].el.parentNode.removeChild(Nametables[name].el);
delete Nametables[name];
if (CurrentNT !== ""){
Nametables[CurrentNT].el.click();
} else {
GlobalEvents.emit("change_surface", null);
}
}
return this;
}

renameBank(name, newname){
if ((name in Nametables) && !(newname in Nametables)){
Nametables[newname] = Nametables[name];
Nametables[newname].elname.value = newname;
delete Nametables[name];
}
return this;
}

activateBank(name){
if (CurrentNT !== name && (name in Nametables)){
Nametables[name].el.click();
}
return this;
}

getNametableName(nametable){
if (!(nametable instanceof NESNameTable))
throw new TypeError("Expected NESNameTable instance.");
var keys = Object.keys(Nametables);
for (let i=0; i < keys.length; i++){
if (Nametables[keys[i]].nametable.eq(nametable))
return keys[i];
}
return null;
}

getNametable(name){
return (name in Nametables) ? Nametables[name].nametable : null;
}

clear(){
Object.keys(Nametables).forEach((item) => {
Nametables[item].el.parentNode.removeChild(Nametables[item].el);
});
Nametables = {};
if (CurrentNT !== ""){
CurrentNT = "";
GlobalEvents.emit("change_surface", null);
}
}
}


const instance = new CTRLNametablesStore();
export default instance;



+ 1
- 1
views/index.html View File

@@ -19,7 +19,7 @@
tabs:[
{name:"Palettes", id:"palettes", tmpl:"paletteListItem.html", addbtntt:"Add Palette", addevent:"palettes-store-add", rembtntt:"Remove Selected Palette", remevent:"palstore-remove", selected:true},
{name:"Banks", id:"banks", tmpl:"bankListItem.html", addbtntt:"Add Bank", addevent:"banks-store-add", rembtntt:"Remove Selected Bank", remevent:"bankstore-remove", selected:false},
{name:"Attrib. Tables", id:"attrtbls", selected:false}
{name:"Name Tables", id:"nametbls", tmpl:"nametableListItem.html", addbtntt:"Add Nametable", addevent:"nt-store-add", rembtntt:"Remove Selected Nametable", remevent:"ntstore-remove", selected:false}
]
}); %>
</div>

+ 12
- 0
views/nametableListItem.html View File

@@ -0,0 +1,12 @@
<div class="list-item-container nametable-list-item-template hidden">
<div class="list-h-padding list-v-padding" style="display:flex">
<canvas class="nametable-img" width="152" height="74"></canvas>
<div class="pure-g">
<div class="pure-u-1">&nbsp;</div>
<div class="pure-u-1">
<span class="title list-item-title simple-padding-left">Title here</span>
<input class="title hidden" type="text" value="Title here"></input>
</div>
</div>
</div>
</div>

Loading…
Cancel
Save