neingeist
/
cosmos
Archived
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

431 lines
11 KiB
JavaScript

/*global Quintus:false */
Quintus.UI = function(Q) {
if(Q._isUndefined(Quintus.Touch)) {
throw "Quintus.UI requires Quintus.Touch Module";
}
Q.UI = {};
// Draw a rounded rectangle centered on 0,0
Q.UI.roundRect = function(ctx, rect) {
ctx.beginPath();
ctx.moveTo(-rect.cx + rect.radius, -rect.cy);
ctx.lineTo(-rect.cx + rect.w - rect.radius, -rect.cy);
ctx.quadraticCurveTo(-rect.cx + rect.w, -rect.cy, -rect.cx + rect.w, -rect.cy + rect.radius);
ctx.lineTo(-rect.cx + rect.w, -rect.cy + rect.h - rect.radius);
ctx.quadraticCurveTo(-rect.cx + rect.w,
-rect.cy + rect.h,
-rect.cx + rect.w - rect.radius,
-rect.cy + rect.h);
ctx.lineTo(-rect.cx + rect.radius, -rect.cy + rect.h);
ctx.quadraticCurveTo(-rect.cx, -rect.cy + rect.h, -rect.cx, -rect.cy + rect.h - rect.radius);
ctx.lineTo(-rect.cx, -rect.cy + rect.radius);
ctx.quadraticCurveTo(-rect.cx, -rect.cy, -rect.cx + rect.radius, -rect.cy);
ctx.closePath();
};
Q.UI.Container = Q.Sprite.extend("UI.Container", {
init: function(p,defaults) {
var adjustedP = Q._clone(p||{}),
match;
if(p && Q._isString(p.w) && (match = p.w.match(/^[0-9]+%$/))) {
adjustedP.w = parseInt(p.w,10) * Q.width / 100;
adjustedP.x = Q.width/2 - adjustedP.w/2;
}
if(p && Q._isString(p.h) && (match = p.h.match(/^[0-9]+%$/))) {
adjustedP.h = parseInt(p.h,10) * Q.height / 100;
adjustedP.y = Q.height /2 - adjustedP.h/2;
}
this._super(Q._defaults(adjustedP,defaults),{
opacity: 1,
hidden: false, // Set to true to not show the container
fill: null, // Set to color to add background
highlight: null, // Set to color to for button
radius: 5, // Border radius
stroke: "#000",
border: false, // Set to a width to show a border
shadow: false, // Set to true or a shadow offest
shadowColor: false, // Set to a rgba value for the shadow
type: Q.SPRITE_NONE
});
},
insert: function(obj) {
this.stage.insert(obj,this);
return obj;
},
fit: function(paddingY,paddingX) {
if(this.children.length === 0) { return; }
if(paddingY === void 0) { paddingY = 0; }
if(paddingX === void 0) { paddingX = paddingY; }
var minX = Infinity,
minY = Infinity,
maxX = -Infinity,
maxY = -Infinity;
for(var i =0;i < this.children.length;i++) {
var obj = this.children[i];
var minObjX = obj.p.x - obj.p.cx,
minObjY = obj.p.y - obj.p.cy,
maxObjX = obj.p.x - obj.p.cx + obj.p.w,
maxObjY = obj.p.y - obj.p.cy + obj.p.h;
if(minObjX < minX) { minX = minObjX; }
if(minObjY < minY) { minY = minObjY; }
if(maxObjX > maxX) { maxX = maxObjX; }
if(maxObjY > maxY) { maxY = maxObjY; }
}
this.p.cx = -minX + paddingX;
this.p.cy = -minY + paddingY;
this.p.w = maxX - minX + paddingX * 2;
this.p.h = maxY - minY + paddingY * 2;
},
addShadow: function(ctx) {
if(this.p.shadow) {
var shadowAmount = Q._isNumber(this.p.shadow) ? this.p.shadow : 5;
ctx.shadowOffsetX=shadowAmount;
ctx.shadowOffsetY=shadowAmount;
ctx.shadowColor = this.p.shadowColor || "rgba(0,0,50,0.1)";
}
},
clearShadow: function(ctx) {
ctx.shadowColor = "transparent";
},
drawRadius: function(ctx) {
Q.UI.roundRect(ctx,this.p);
this.addShadow(ctx);
ctx.fill();
if(this.p.border) {
this.clearShadow(ctx);
ctx.lineWidth = this.p.border;
ctx.stroke();
}
},
drawSquare: function(ctx) {
this.addShadow(ctx);
if(this.p.fill) {
ctx.fillRect(-this.p.cx,-this.p.cy,
this.p.w,this.p.h);
}
if(this.p.border) {
this.clearShadow(ctx);
ctx.lineWidth = this.p.border;
ctx.strokeRect(-this.p.cx,-this.p.cy,
this.p.w,this.p.h);
}
},
draw: function(ctx) {
if(this.p.hidden) { return false; }
if(!this.p.border && !this.p.fill) { return; }
ctx.globalAlpha = this.p.opacity;
if(this.p.frame === 1 && this.p.highlight) {
ctx.fillStyle = this.p.highlight;
} else {
ctx.fillStyle = this.p.fill;
}
ctx.strokeStyle = this.p.stroke;
if(this.p.radius > 0) {
this.drawRadius(ctx);
} else {
this.drawSquare(ctx);
}
}
});
Q.UI.Text = Q.Sprite.extend("UI.Text", {
init: function(p,defaultProps) {
this._super(Q._defaults(p||{},defaultProps),{
type: Q.SPRITE_UI,
size: 24
});
//this.el = document.createElement("canvas");
//this.ctx = this.el.getContext("2d");
if(this.p.label) {
this.calcSize();
}
//this.prerender();
},
calcSize: function() {
this.setFont(Q.ctx);
this.splitLabel = this.p.label.split("\n");
var maxLabel = "";
for(var i = 0;i < this.splitLabel.length;i++) {
if(this.splitLabel[i].length > maxLabel.length) {
maxLabel = this.splitLabel[i];
}
}
var metrics = Q.ctx.measureText(maxLabel);
this.p.h = (this.p.size || 24) * this.splitLabel.length * 1.2;
this.p.w = metrics.width;
this.p.cx = this.p.w / 2;
this.p.cy = this.p.h / 2;
},
prerender: function() {
if(this.p.oldLabel === this.p.label) { return; }
this.p.oldLabel = this.p.label;
this.calcSize();
this.el.width = this.p.w;
this.el.height = this.p.h * 4;
this.ctx.clearRect(0,0,this.p.w,this.p.h);
this.ctx.fillStyle = "#FF0";
this.ctx.fillRect(0,0,this.p.w,this.p.h/2);
this.setFont(this.ctx);
this.ctx.fillText(this.p.label,0,0);
},
draw: function(ctx) {
//this.prerender();
if(this.p.opacity === 0) { return; }
if(this.p.oldLabel !== this.p.label) { this.calcSize(); }
this.setFont(ctx);
if(this.p.opacity !== void 0) { ctx.globalAlpha = this.p.opacity; }
for(var i =0;i<this.splitLabel.length;i++) {
if(this.p.align === 'center') {
ctx.fillText(this.splitLabel[i],0,-this.p.cy + i * this.p.size * 1.2);
} else if(this.p.align === 'right') {
ctx.fillText(this.splitLabel[i],this.p.cx,-this.p.cy + i * this.p.size * 1.2);
} else {
ctx.fillText(this.splitLabel[i],-this.p.cx,-this.p.cy +i * this.p.size * 1.2);
}
}
},
asset: function() {
return this.el;
},
setFont: function(ctx) {
ctx.textBaseline = "top";
ctx.font= this.font();
ctx.fillStyle = this.p.color || "black";
ctx.textAlign = this.p.align || "left";
},
font: function() {
if(this.fontString) { return this.fontString; }
this.fontString = (this.p.weight || "800") + " " +
(this.p.size || 24) + "px " +
(this.p.family || "Arial");
return this.fontString;
}
});
Q.UI.Button = Q.UI.Container.extend("UI.Button", {
init: function(p,callback) {
this._super(Q._defaults(p,{
type: Q.SPRITE_UI | Q.SPRITE_DEFAULT
}));
if(this.p.label && (!this.p.w || !this.p.h)) {
Q.ctx.save();
this.setFont(Q.ctx);
var metrics = Q.ctx.measureText(this.p.label);
Q.ctx.restore();
if(!this.p.h) { this.p.h = 24 + 20; }
if(!this.p.w) { this.p.w = metrics.width + 20; }
}
if(isNaN(this.p.cx)) { this.p.cx = this.p.w / 2; }
if(isNaN(this.p.cy)) { this.p.cy = this.p.h / 2; }
this.callback = callback;
this.on('touch',this,"highlight");
this.on('touchEnd',this,"push");
},
highlight: function() {
if(!this.sheet() || this.sheet().frames > 1) {
this.p.frame = 1;
}
},
push: function() {
this.p.frame = 0;
if(this.callback) { this.callback(); }
this.trigger('click');
},
draw: function(ctx) {
this._super(ctx);
if(this.p.asset || this.p.sheet) {
Q.Sprite.prototype.draw.call(this,ctx);
}
if(this.p.label) {
ctx.save();
this.setFont(ctx);
ctx.fillText(this.p.label,0,0);
ctx.restore();
}
},
setFont: function(ctx) {
ctx.textBaseline = "middle";
ctx.font = this.p.font || "400 24px arial";
ctx.fillStyle = this.p.fontColor || "black";
ctx.textAlign = "center";
}
});
Q.UI.IFrame = Q.Sprite.extend("UI.IFrame", {
init: function(p) {
this._super(p, { opacity: 1, type: Q.SPRITE_UI | Q.SPRITE_DEFAULT });
Q.wrapper.style.overflow = "hidden";
this.iframe = document.createElement("IFRAME");
this.iframe.setAttribute("src",this.p.url);
this.iframe.style.position = "absolute";
this.iframe.style.zIndex = 500;
this.iframe.setAttribute("width",this.p.w);
this.iframe.setAttribute("height",this.p.h);
this.iframe.setAttribute("frameborder",0);
if(this.p.background) {
this.iframe.style.backgroundColor = this.p.background;
}
Q.wrapper.appendChild(this.iframe);
this.on("inserted",function(parent) {
this.positionIFrame();
parent.on("destroyed",this,"remove");
});
},
positionIFrame: function() {
var x = this.p.x;
var y = this.p.y;
if(this.stage.viewport) {
x -= this.stage.viewport.x;
y -= this.stage.viewport.y;
}
if(this.oldX !== x || this.oldY !== y || this.oldOpacity !== this.p.opacity) {
this.iframe.style.top = (y - this.p.cy) + "px";
this.iframe.style.left = (x - this.p.cx) + "px";
this.iframe.style.opacity = this.p.opacity;
this.oldX = x;
this.oldY = y;
this.oldOpacity = this.p.opacity;
}
},
step: function(dt) {
this._super(dt);
this.positionIFrame();
},
remove: function() {
if(this.iframe) {
Q.wrapper.removeChild(this.iframe);
this.iframe = null;
}
}
});
Q.UI.HTMLElement = Q.Sprite.extend("UI.HTMLElement", {
init: function(p) {
this._super(p, { opacity: 1, type: Q.SPRITE_UI });
Q.wrapper.style.overflow = "hidden";
this.el = document.createElement("div");
this.el.innerHTML = this.p.html;
Q.wrapper.appendChild(this.el);
this.on("inserted",function(parent) {
this.position();
parent.on("destroyed",this,"remove");
parent.on("clear",this,"remove");
});
},
position: function() {
},
step: function(dt) {
this._super(dt);
this.position();
},
remove: function() {
if(this.el) {
Q.wrapper.removeChild(this.el);
this.el= null;
}
}
});
Q.UI.VerticalLayout = Q.Sprite.extend("UI.VerticalLayout",{
init: function(p) {
this.children = [];
this._super(p, { type: 0 });
},
insert: function(sprite) {
this.stage.insert(sprite,this);
this.relayout();
// Bind to destroy
return sprite;
},
relayout: function() {
var totalHeight = 0;
for(var i=0;i<this.children.length;i++) {
totalHeight += this.children[i].p.h || 0;
}
// Center?
var totalSepartion = this.p.h - totalHeight;
// Make sure all elements have the same space between them
}
});
};