diff --git a/Makefile b/Makefile index 69994b1..5ce62ac 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ -all: coreLib symbolLib editorLib testsLib +all: coreLib + +#symbolLib editorLib testsLib coreLib: diff --git a/components/Core/Makefile b/components/Core/Makefile index 6283df2..b00ca1d 100644 --- a/components/Core/Makefile +++ b/components/Core/Makefile @@ -1,5 +1,5 @@ OutputName=coreLib -SourceFiles=src/Core.ts src/Fragment.ts src/Paper.ts +SourceFiles=src/Core.ts src/Fragment.ts src/Paper.ts src/Value.ts src/StandardLibrary.ts src/Dictionary.ts BaseDir=../.. OutputDir=$(BaseDir)/js Out=$(OutputDir)/$(OutputName).js diff --git a/components/Core/lib.ts b/components/Core/lib.ts index 5e19123..32e71ba 100644 --- a/components/Core/lib.ts +++ b/components/Core/lib.ts @@ -1,3 +1,6 @@ /// /// /// +/// +/// +/// diff --git a/components/Core/src/Core.ts b/components/Core/src/Core.ts index dcc1c8c..f56243f 100644 --- a/components/Core/src/Core.ts +++ b/components/Core/src/Core.ts @@ -1,4 +1,13 @@ module Sanara.Core { export type SanaraContext = CanvasRenderingContext2D; + export class Exception { + static FEW_CHILDREN = new Exception("Few children"); + static FEW_PARAMETERS = new Exception("Few parameters"); + + constructor(public message:string) {}; + toString() : string { + return this.message; + } + } } diff --git a/components/Core/src/Dictionary.ts b/components/Core/src/Dictionary.ts new file mode 100644 index 0000000..5e4b8d2 --- /dev/null +++ b/components/Core/src/Dictionary.ts @@ -0,0 +1,31 @@ +/// + +module Sanara.Core{ + export type DictionaryEntry = Sanara.Core.FragmentClass// | Sanara.Core.Transformer; + export class Dictionary { + constructor(private entries : DictionaryEntry[]) {} + hasEntry(name:string) : boolean { + for(var i = 0 ; i < this.entries.length ; i++) { + if(this.entries[i].doc.name === name){ + return true; + } + } + return false; + } + getEntry(name:string) : Sanara.Core.DictionaryEntry { + for(var i = 0 ; i < this.entries.length ; i++) { + if(this.entries[i].doc.name === name){ + return this.entries[i]; + } + } + return null; + } + listNames() : string[] { + var list = []; + for(var i = 0 ; i < this.entries.length ; i++) { + list.push(this.entries[i].doc.name) + } + return list; + } + } +} diff --git a/components/Core/src/Fragment.ts b/components/Core/src/Fragment.ts index 0173984..b18875a 100644 --- a/components/Core/src/Fragment.ts +++ b/components/Core/src/Fragment.ts @@ -1,24 +1,83 @@ /// +/// +/// + module Sanara.Core { - export interface Fragment { - paint(paper: Paper) : void; - paintMe(paper : Paper) : void; - } - export class BaseFragment implements Fragment { - children : [Fragment]; - constructor (children : [Fragment] = <[Fragment]>[]) { - this.children = children; - } - paint(paper: Paper) { - paper.context.save(); - this.paintMe(paper); - paper.context.restore(); - } - paintMe(paper : Paper) { - this.children.forEach(function (v) { - v.paint(paper); - }) - } - } + /** + valueGetter because properties will change over time!. + */ + export type Property = {name:string, getter:ValueGetter}; + /** + Type of Fragment classes. FragmentTemplate is a class that extends Fragment + */ + export type FragmentClass = typeof Fragment; + export interface FragmentClassDoc { + name : string, + discription : string, + parameters? : {name:string, discription:string}[], + properties? : {name:string, discription:string}[], + children? : {name:string, discription:string, propertiesRequired?:string[]}[] + } + export class Fragment { + static doc:FragmentClassDoc = { + name : "fragment-base-class", + discription : "SHOULD NOT BE INSTANTIATED: base class for all fragment classes" + } + + private static ZERO_GETTER = ()=>Value.ZERO; + + private properties : Property[]; + + constructor (children:Fragment[], parameters:Value[], properties? : Property[]) { + // children and parameters are ignored in baseclass but should be + // implemented in classes that extends fragment class + if(properties) { + this.properties = properties; + } else { + this.properties = []; + } + + if(! this.hasProperty("width")) { + this.properties.push({name:"width", getter:Fragment.ZERO_GETTER}); + } + if(! this.hasProperty("height")) { + this.properties.push({name:"height", getter:Fragment.ZERO_GETTER}) + } + } + + paint(context : SanaraContext) { + context.save(); + this.paintImplementation(context); + context.restore(); + } + paintImplementation(context : SanaraContext) {} + + hasProperty(name:string) : boolean{ + for(var i = 0 ; i < this.properties.length ; i++) { + if(this.properties[i].name === name) { + return true; + } + } + return false; + } + /** + fragment must have the property Or unexpected results + */ + getPropertyValue(name:string) : Value { + for(var i = 0 ; i < this.properties.length ; i++) { + if(this.properties[i].name === name) { + return this.properties[i].getter(); + } + } + return Value.ZERO; + } + + width() : number { + return this.getPropertyValue("width").toNumber(); + } + height() : number { + return this.getPropertyValue("height").toNumber(); + } + } } diff --git a/components/Core/src/Paper.ts b/components/Core/src/Paper.ts index 8b5c0e7..b917247 100644 --- a/components/Core/src/Paper.ts +++ b/components/Core/src/Paper.ts @@ -5,26 +5,27 @@ module Sanara.Core { export interface Paper { domElement : HTMLCanvasElement; context : SanaraContext; - w : number; - h : number; root : Fragment; repaint(time:number) : void; } export class BasicPaper implements Paper { domElement : HTMLCanvasElement; context : SanaraContext; - w : number; - h : number; + private width : number; + private height : number; root : Fragment; constructor (w:number = 100, h:number = 100) { - this.w = w; - this.h = h; + this.width = w; + this.height = h; this.domElement = document.createElement("canvas"); + this.domElement.width = this.width; + this.domElement.height = this.height; + this.context = this.domElement.getContext("2d"); } repaint(time:number = 0) : void { - this.root.paint(this); + this.root.paint(this.context); } } } diff --git a/components/Core/src/StandardLibrary.ts b/components/Core/src/StandardLibrary.ts new file mode 100644 index 0000000..e18aa3f --- /dev/null +++ b/components/Core/src/StandardLibrary.ts @@ -0,0 +1,160 @@ +/// +/// + + +module Sanara.Std { + + export class Bitree extends Sanara.Core.Fragment { + static doc:Sanara.Core.FragmentClassDoc = { + name : "bitree", + discription : "binary tree", + properties : [ + { + name:"node-pivot", + discription:"place to hold" + } + ], + children : [ + { + name: "main-node", + discription : "main node", + }, { + name: "lefty", + discription : "left node", + }, { + name: "righty", + discription : "right node", + } + ] + } + + private content : Sanara.Core.Fragment; + private lefty : Sanara.Core.Fragment; + private righty : Sanara.Core.Fragment; + + constructor(children : Sanara.Core.Fragment[]) { + if(children.length < 3) { + throw Sanara.Core.Exception.FEW_CHILDREN; + } + this.content = children[0]; + this.lefty = children[1]; + this.righty = children[2]; + + var properties = []; + + var widthGetter = () => { + return new Sanara.Core.Value(Math.max(this.lefty.width()+this.righty.width(),this.content.width())) + } + properties.push({name:"width",getter:widthGetter}); + + var heightGetter = () => { + return new Sanara.Core.Value(this.content.height() + Math.max(this.lefty.height(), this.righty.height())); + } + properties.push({name:"height",getter:heightGetter}); + + var nodePivotGetter = () => { + return new Sanara.Core.Value(this.lefty.width() + this.content.width()/2); + } + properties.push({name:"node-pivot",getter:nodePivotGetter}); + + super(null,null,properties); + } + + paintImplementation(context : Sanara.Core.SanaraContext) { + context.save(); + { + context.translate((this.width()-this.content.width())/2,0); + this.content.paint(context); + } + context.restore(); + + context.translate(0,this.content.height()); + this.lefty.paint(context); + + context.translate(this.lefty.width(),0); + this.righty.paint(context); + } + } + export class Circle extends Sanara.Core.Fragment { + static doc:Sanara.Core.FragmentClassDoc = { + name: "circle", + discription: "circle of diameter 100" + } + + private static CIRCLE : Circle = new Circle(); + + constructor() { + if(typeof Circle.CIRCLE === "undefined") { + Circle.CIRCLE = this; + } else { + return Circle.CIRCLE; + } + + var diameterGetter =function(){return new Sanara.Core.Value(100)}; + + super(null,null,[ + {name:"width",getter: diameterGetter}, + {name:"height",getter: diameterGetter} + ]); + } + + + paintImplementation(context: Sanara.Core.SanaraContext) { + context.beginPath(); + context.arc(50, 50, 50, 0, 2 * Math.PI, false); + context.fill(); + } + } + export class FillColor extends Sanara.Core.Fragment { + static doc:Sanara.Core.FragmentClassDoc = { + name: "fill-color", + discription: "Changes fill color for child environment", + children : [ + { + name : "colored", + discription : "fragment that will recieve new fill color" + } + ], + parameters : [ + { + name: "color", + discription : "New color. e.g. \"#f3422e\"" + } + ] + } + + private color : Sanara.Core.Value; + private child : Sanara.Core.Fragment; + + constructor(children:Sanara.Core.Fragment[], parameters: Sanara.Core.Value[]) { + if(children.length < 1) { + throw Sanara.Core.Exception.FEW_CHILDREN; + } + if(parameters.length < 1) { + throw Sanara.Core.Exception.FEW_PARAMETERS; + } + this.color = parameters[0]; + this.child = children[0]; + + super(null,null,[ + {name:"width",getter: ()=>this.child.getPropertyValue("width")}, + {name:"height",getter: ()=>this.child.getPropertyValue("height")}, + ]); + } + + paintImplementation(context: Sanara.Core.SanaraContext) { + context.fillStyle = this.color.toColor(); + this.child.paint(context); + } + } + + export var dictionary : Sanara.Core.Dictionary = (function() { + var entries = []; + // + entries.push(Sanara.Std.Circle); + entries.push(Sanara.Std.Bitree); + entries.push(Sanara.Std.FillColor); + // + return new Sanara.Core.Dictionary(entries); + })(); +} diff --git a/components/Core/src/Value.ts b/components/Core/src/Value.ts new file mode 100644 index 0000000..ebf140a --- /dev/null +++ b/components/Core/src/Value.ts @@ -0,0 +1,81 @@ +/** +*/ +module Sanara.Core { + export type ValueGetter = () => Value; + export type ValueInput = number|boolean|string; + export class Value { + //numbers + static ZERO : Value = new Value(0); + static ONE : Value = new Value(1); + //boolean + static FALSE : Value = new Value(false); + static TRUE : Value = new Value(true); + //colors + static WHITE : Value = new Value("#ffffff"); + static BLACK : Value = new Value("#000000"); + + private value:ValueInput; + + constructor(value:ValueInput) { + this.value = value; + + if(typeof value === "boolean") { + if(value) { + if(typeof Value.TRUE !== "undefined") { + return Value.TRUE; + } else { + Value.TRUE = this; + } + } else { + if(typeof Value.FALSE !== "undefined") { + return Value.FALSE; + } else { + Value.FALSE = this; + } + } + } + } + toString() : string { + var v = this.value; + if(typeof v === "string") { + return v; + } else { + return v.toString(); + } + } + toNumber() : number { + var v = this.value; + if(typeof v === "number") { + return v; + } else if(typeof v === "string") { + return 0; + } else if(typeof v === "boolean") { + return (v?1:0); + } + } + toBoolean() : boolean { + var v = this.value; + if(typeof v === "number") { + return (v===0 ? false : true); + } else if(typeof v === "string") { + return false; + } else if(typeof v === "boolean") { + return v; + } + } + toColor() : string { + var v = this.value; + if(typeof v === "number") { + return "#ffffff"; + } else if(typeof v === "string") { + if(v.length !== 0 && v.charAt(0)==='#') { + return v; + } else { + return "#000000"; + } + } else if(typeof v === "boolean") { + return (v?"#ffffff": "#000000") + } + } + } +} diff --git a/components/Core/tsconfig.json b/components/Core/tsconfig.json index 060ac0f..5028853 100644 --- a/components/Core/tsconfig.json +++ b/components/Core/tsconfig.json @@ -11,7 +11,10 @@ "files": [ "./lib.ts", "./src/Core.ts", + "./src/Dictionary.ts", "./src/Fragment.ts", - "./src/Paper.ts" + "./src/Paper.ts", + "./src/StandardLibrary.ts", + "./src/Value.ts" ] } diff --git a/components/declareFiles/coreLib.d.ts b/components/declareFiles/coreLib.d.ts index 384e4a3..1406308 100644 --- a/components/declareFiles/coreLib.d.ts +++ b/components/declareFiles/coreLib.d.ts @@ -1,34 +1,126 @@ declare module Sanara.Core { type SanaraContext = CanvasRenderingContext2D; + class Exception { + message: string; + static FEW_CHILDREN: Exception; + static FEW_PARAMETERS: Exception; + constructor(message: string); + toString(): string; + } } declare module Sanara.Core { interface Paper { domElement: HTMLCanvasElement; context: SanaraContext; - w: number; - h: number; root: Fragment; repaint(time: number): void; } class BasicPaper implements Paper { domElement: HTMLCanvasElement; context: SanaraContext; - w: number; - h: number; + private width; + private height; root: Fragment; constructor(w?: number, h?: number); repaint(time?: number): void; } } +/** +*/ +declare module Sanara.Core { + type ValueGetter = () => Value; + type ValueInput = number | boolean | string; + class Value { + static ZERO: Value; + static ONE: Value; + static FALSE: Value; + static TRUE: Value; + static WHITE: Value; + static BLACK: Value; + private value; + constructor(value: ValueInput); + toString(): string; + toNumber(): number; + toBoolean(): boolean; + toColor(): string; + } +} declare module Sanara.Core { - interface Fragment { - paint(paper: Paper): void; - paintMe(paper: Paper): void; + /** + valueGetter because properties will change over time!. + */ + type Property = { + name: string; + getter: ValueGetter; + }; + /** + Type of Fragment classes. FragmentTemplate is a class that extends Fragment + */ + type FragmentClass = typeof Fragment; + interface FragmentClassDoc { + name: string; + discription: string; + parameters?: { + name: string; + discription: string; + }[]; + properties?: { + name: string; + discription: string; + }[]; + children?: { + name: string; + discription: string; + propertiesRequired?: string[]; + }[]; + } + class Fragment { + static doc: FragmentClassDoc; + private static ZERO_GETTER; + private properties; + constructor(children: Fragment[], parameters: Value[], properties?: Property[]); + paint(context: SanaraContext): void; + paintImplementation(context: SanaraContext): void; + hasProperty(name: string): boolean; + /** + fragment must have the property Or unexpected results + */ + getPropertyValue(name: string): Value; + width(): number; + height(): number; + } +} +declare module Sanara.Core { + type DictionaryEntry = Sanara.Core.FragmentClass; + class Dictionary { + private entries; + constructor(entries: DictionaryEntry[]); + hasEntry(name: string): boolean; + getEntry(name: string): Sanara.Core.DictionaryEntry; + listNames(): string[]; + } +} +declare module Sanara.Std { + class Bitree extends Sanara.Core.Fragment { + static doc: Sanara.Core.FragmentClassDoc; + private content; + private lefty; + private righty; + constructor(children: Sanara.Core.Fragment[]); + paintImplementation(context: Sanara.Core.SanaraContext): void; + } + class Circle extends Sanara.Core.Fragment { + static doc: Sanara.Core.FragmentClassDoc; + private static CIRCLE; + constructor(); + paintImplementation(context: Sanara.Core.SanaraContext): void; } - class BaseFragment implements Fragment { - children: [Fragment]; - constructor(children?: [Fragment]); - paint(paper: Paper): void; - paintMe(paper: Paper): void; + class FillColor extends Sanara.Core.Fragment { + static doc: Sanara.Core.FragmentClassDoc; + private color; + private child; + constructor(children: Sanara.Core.Fragment[], parameters: Sanara.Core.Value[]); + paintImplementation(context: Sanara.Core.SanaraContext): void; } + var dictionary: Sanara.Core.Dictionary; } diff --git a/index.html b/index.html index 998d4b0..472123c 100644 --- a/index.html +++ b/index.html @@ -2,11 +2,19 @@ - - - +