More panel work
This commit is contained in:
parent
73bf9d5852
commit
531b9327c6
3 changed files with 271 additions and 47 deletions
|
|
@ -130,7 +130,7 @@ function Bus(parmsBus, cpu, dbg)
|
|||
this.blockLimit = this.blockSize - 1;
|
||||
this.blockTotal = ((this.busLimit + this.blockSize) / this.blockSize) | 0;
|
||||
this.blockMask = this.blockTotal - 1;
|
||||
this.assert(this.blockTotal <= Bus.BLOCK.MASK);
|
||||
this.assert(this.blockTotal <= Bus.BLOCK.NUM_MASK);
|
||||
|
||||
/*
|
||||
* Lists of I/O notification functions: aPortInputNotify and aPortOutputNotify are arrays, indexed by
|
||||
|
|
@ -237,12 +237,18 @@ if (BACKTRACK) {
|
|||
}
|
||||
|
||||
/*
|
||||
* scanMemory() records block numbers in bits 0-14, a BackTrack "mod" bit in bit 15, and the block type at bit 16.
|
||||
* scanMemory() records block numbers in bits 0-14, a BackTrack "mod" bit in bit 15, and a block type at bit 28;
|
||||
* the bits reserved for a count are not used.
|
||||
*/
|
||||
Bus.BLOCK = {
|
||||
MASK: 0x7fff,
|
||||
NUM_SHIFT: 0,
|
||||
NUM_MASK: 0x7fff,
|
||||
BTMOD_SHIFT: 15,
|
||||
TYPE_SHIFT: 16
|
||||
BTMOD_MASK: 0x1,
|
||||
COUNT_SHIFT: 16,
|
||||
COUNT_MASK: 0x0fff,
|
||||
TYPE_SHIFT: 28,
|
||||
TYPE_MASK: 0x7
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -204,13 +204,11 @@ Memory.TYPE = {
|
|||
NONE: 0,
|
||||
RAM: 1,
|
||||
ROM: 2,
|
||||
VIDEO: 3
|
||||
VIDEO: 3,
|
||||
NAMES: ["NONE", "RAM", "ROM", "VIDEO"],
|
||||
COLORS: ["black", "blue", "green", "cyan"]
|
||||
};
|
||||
|
||||
if (DEBUG) {
|
||||
Memory.TYPE.NAMES = ["NONE", "RAM", "ROM", "VIDEO"];
|
||||
}
|
||||
|
||||
/**
|
||||
* readNone(off)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -84,6 +84,126 @@ Panel.LIVEREGISTERS = {
|
|||
HEIGHT: Panel.LIVECANVAS.HEIGHT
|
||||
};
|
||||
|
||||
/*
|
||||
* findRegions() records block numbers in bits 0-14, a BackTrack "mod" bit in bit 15, and the block type at bit 16.
|
||||
*/
|
||||
Panel.REGION = {
|
||||
MASK: 0x7fff,
|
||||
BTMOD_SHIFT: 15,
|
||||
TYPE_SHIFT: 16
|
||||
};
|
||||
|
||||
/**
|
||||
* Color(r, g, b, a)
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} [r]
|
||||
* @param {number} [g]
|
||||
* @param {number} [b]
|
||||
* @param {number} [a]
|
||||
*/
|
||||
function Color(r, g, b, a)
|
||||
{
|
||||
this.rgb = [r, g, b, a];
|
||||
this.sValue = null;
|
||||
if (r === undefined) this.randomize();
|
||||
}
|
||||
|
||||
/**
|
||||
* getRandom(nLimit)
|
||||
*
|
||||
* @this {Color}
|
||||
* @param {number} [nLimit]
|
||||
*/
|
||||
Color.prototype.getRandom = function(nLimit)
|
||||
{
|
||||
return (Math.random() * (nLimit || 0x100)) | 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* randomize()
|
||||
*
|
||||
* @this {Color}
|
||||
*/
|
||||
Color.prototype.randomize = function()
|
||||
{
|
||||
this.rgb[0] = this.getRandom(); this.rgb[1] = this.getRandom(); this.rgb[2] = this.getRandom(); this.rgb[3] = 0xff;
|
||||
this.sValue = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* toString()
|
||||
*
|
||||
* @this {Color}
|
||||
* @return {string}
|
||||
*/
|
||||
Color.prototype.toString = function()
|
||||
{
|
||||
if (!this.sValue) this.sValue = '#' + str.toHexByte(this.rgb[0]) + str.toHexByte(this.rgb[1]) + str.toHexByte(this.rgb[2]);
|
||||
return this.sValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rectangle(x, y, cx, cy)
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @param {number} cx
|
||||
* @param {number} cy
|
||||
*/
|
||||
function Rectangle(x, y, cx, cy)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.cx = cx;
|
||||
this.cy = cy;
|
||||
}
|
||||
|
||||
/**
|
||||
* subDivide(units, unitsTotal, fHorizontal)
|
||||
*
|
||||
* Return a new rectangle that is a subset of the current rectangle, based on the ratio of
|
||||
* units to unitsTotal, and then update the dimensions of the current rectangle. Whether the
|
||||
* original rectangle is divided horizontally or vertically is entirely arbitrary; currently,
|
||||
* the criteria is horizontal if the ratio is 1/4 or more, vertical otherwise.
|
||||
*
|
||||
* @this {Rectangle}
|
||||
* @param {number} units
|
||||
* @param {number} unitsTotal
|
||||
* @param {boolean} [fHorizontal]
|
||||
* @return {Rectangle}
|
||||
*/
|
||||
Rectangle.prototype.subDivide = function(units, unitsTotal, fHorizontal)
|
||||
{
|
||||
var rect;
|
||||
if (fHorizontal || units >= (unitsTotal >> 2)) {
|
||||
rect = new Rectangle(this.x, this.y, this.cx, ((this.cy * units) / unitsTotal) | 0);
|
||||
this.y += rect.cy;
|
||||
this.cy -= rect.cy;
|
||||
Component.assert(this.cy >= 0);
|
||||
} else {
|
||||
rect = new Rectangle(this.x, this.y, ((this.cx * units) / unitsTotal) | 0, this.cy);
|
||||
this.x += rect.cx;
|
||||
this.cx -= rect.cx;
|
||||
Component.assert(this.cx >= 0);
|
||||
}
|
||||
return rect;
|
||||
};
|
||||
|
||||
/**
|
||||
* drawWith(context, color)
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {Color|string} [color]
|
||||
*/
|
||||
Rectangle.prototype.drawWith = function(context, color)
|
||||
{
|
||||
if (!color) color = new Color();
|
||||
context.fillStyle = (typeof color == "string"? color : color.toString());
|
||||
context.fillRect(this.x, this.y, this.cx, this.cy);
|
||||
};
|
||||
|
||||
/**
|
||||
* setBinding(sHTMLType, sBinding, control)
|
||||
*
|
||||
|
|
@ -103,6 +223,7 @@ Panel.prototype.setBinding = function(sHTMLType, sBinding, control)
|
|||
if (this.cpu && this.cpu.setBinding(sHTMLType, sBinding, control)) return true;
|
||||
if (this.kbd && this.kbd.setBinding(sHTMLType, sBinding, control)) return true;
|
||||
if (DEBUGGER && this.dbg && this.dbg.setBinding(sHTMLType, sBinding, control)) return true;
|
||||
|
||||
if (!this.canvas && sHTMLType == "canvas") {
|
||||
var fPanel = false;
|
||||
if (BACKTRACK && sBinding == "btpanel") {
|
||||
|
|
@ -124,14 +245,12 @@ Panel.prototype.setBinding = function(sHTMLType, sBinding, control)
|
|||
this.canvasLiveMemory.width = Panel.LIVEMEMORY.WIDTH;
|
||||
this.canvasLiveMemory.height = Panel.LIVEMEMORY.HEIGHT;
|
||||
this.contextLiveMemory = this.canvasLiveMemory.getContext("2d");
|
||||
this.contextLiveMemory.font = Panel.LIVECANVAS.FONT.HEIGHT + "px " + Panel.LIVECANVAS.FONT.NAME;
|
||||
this.imageLiveMemory = this.contextLiveMemory.createImageData(this.canvasLiveMemory.width, this.canvasLiveMemory.height);
|
||||
|
||||
this.canvasLiveRegisters = window.document.createElement("canvas");
|
||||
this.canvasLiveRegisters.width = Panel.LIVEREGISTERS.WIDTH;
|
||||
this.canvasLiveRegisters.height = Panel.LIVEREGISTERS.HEIGHT;
|
||||
this.contextLiveRegisters = this.canvasLiveRegisters.getContext("2d");
|
||||
this.contextLiveRegisters.font = Panel.LIVECANVAS.FONT.HEIGHT + "px " + Panel.LIVECANVAS.FONT.NAME;
|
||||
|
||||
this.fRedraw = true;
|
||||
return true;
|
||||
|
|
@ -168,9 +287,7 @@ Panel.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
*/
|
||||
Panel.prototype.powerUp = function(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
Panel.init();
|
||||
}
|
||||
if (!fRepower) Panel.init();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -196,14 +313,49 @@ Panel.prototype.powerDown = function(fSave)
|
|||
Panel.prototype.updateAnimation = function()
|
||||
{
|
||||
if (this.fRedraw) {
|
||||
|
||||
this.initPen(10, Panel.LIVECANVAS.FONT.HEIGHT, this.canvasLiveMemory, this.contextLiveMemory, this.canvas.style.color);
|
||||
|
||||
if (this.fBackTrack) {
|
||||
if (MAXDEBUG) this.log("begin scanMemory()");
|
||||
if (DEBUG) this.log("begin scanMemory()");
|
||||
this.stats = this.bus.scanMemory(this.stats);
|
||||
this.findRegions();
|
||||
if (MAXDEBUG) this.log("end scanMemory(): total bytes: " + this.stats.cbTotal + ", total blocks: " + this.stats.cBlocks + ", total regions: " + this.stats.cRegions);
|
||||
/*
|
||||
* Update the Stats object with region information (cRegions and aRegions); return true if region
|
||||
* information has changed since the last call.
|
||||
*/
|
||||
if (this.findRegions()) {
|
||||
/*
|
||||
* For each region, I choose a slice of the LiveMemory canvas and record the corresponding rectangle
|
||||
* within an aRects array (parallel to the aRegions array) in the Stats object.
|
||||
*
|
||||
* I don't need a sophisticated Treemap algorithm, because at this level, the data is not hierarchical.
|
||||
* subDivide() makes a simple horizontal or vertical slicing decision based on the ratio of region blocks
|
||||
* to remaining blocks.
|
||||
*/
|
||||
var i;
|
||||
var rectAvail = new Rectangle(0, 0, this.canvasLiveMemory.width, this.canvasLiveMemory.height);
|
||||
this.stats.aRects = [];
|
||||
var cBlocksRemaining = this.stats.cBlocks;
|
||||
for (i = 0; i < this.stats.cRegions; i++) {
|
||||
var cBlocksRegion = (this.stats.aRegions[i] >> Bus.BLOCK.COUNT_SHIFT) & Bus.BLOCK.COUNT_MASK;
|
||||
this.stats.aRects.push(rectAvail.subDivide(cBlocksRegion, cBlocksRemaining, true));
|
||||
cBlocksRemaining -= cBlocksRegion;
|
||||
}
|
||||
this.assert(!cBlocksRemaining && (!rectAvail.cx || !rectAvail.cy));
|
||||
for (i = 0; i < this.stats.aRects.length; i++) {
|
||||
var nRegion = this.stats.aRegions[i];
|
||||
var type = (nRegion >> Bus.BLOCK.TYPE_SHIFT) & Bus.BLOCK.TYPE_MASK;
|
||||
var cBlocks = (nRegion >> Bus.BLOCK.COUNT_SHIFT) & Bus.BLOCK.COUNT_MASK;
|
||||
var rect = this.stats.aRects[i];
|
||||
rect.drawWith(this.contextLiveMemory, Memory.TYPE.COLORS[type]);
|
||||
this.centerPen(rect);
|
||||
this.centerText(Memory.TYPE.NAMES[type] + " (" + (((cBlocks * this.bus.blockSize) / 1024) | 0) + "Kb)");
|
||||
}
|
||||
}
|
||||
if (DEBUG) this.log("end scanMemory(): total bytes: " + this.stats.cbTotal + ", total blocks: " + this.stats.cBlocks + ", total regions: " + this.stats.cRegions);
|
||||
} else {
|
||||
this.drawText("This space intentionally left blank");
|
||||
}
|
||||
this.initPen(10, Panel.LIVECANVAS.FONT.HEIGHT, this.canvasLiveMemory, this.contextLiveMemory);
|
||||
this.drawText("This space intentionally left blank");
|
||||
this.context.drawImage(this.canvasLiveMemory, 0, 0, this.canvasLiveMemory.width, this.canvasLiveMemory.height, this.xMemory, this.yMemory, this.cxMemory, this.cyMemory);
|
||||
this.fRedraw = false;
|
||||
}
|
||||
|
|
@ -212,7 +364,7 @@ Panel.prototype.updateAnimation = function()
|
|||
/**
|
||||
* updateStatus()
|
||||
*
|
||||
* Update function for Control Panels containing DOM elements with low-frequency display requirements.
|
||||
* Update function for Control Panels containing DOM elements with low-frequencyxt display requirements.
|
||||
*
|
||||
* For the time being, the X86CPU component has its own updateStatus() handler, and displays all CPU registers itself.
|
||||
*
|
||||
|
|
@ -228,34 +380,41 @@ Panel.prototype.updateStatus = function()
|
|||
/**
|
||||
* findRegions()
|
||||
*
|
||||
* This takes the stats object produced by scanMemory() and adds the following:
|
||||
* This takes the Stats object produced by scanMemory() and adds the following:
|
||||
*
|
||||
* cRegions: number of contiguous memory regions
|
||||
* aRegions: array of aBlocks indexes (bits 0-15) combined with block counts (bits 16-31)
|
||||
* aRegions: array of aBlocks indexes (bits 0-14) combined with block counts (bits 16-27) and block types (bits 28-31)
|
||||
*
|
||||
* It calls addRegion() for each discrete region (set of contiguous blocks with the same type) that it finds.
|
||||
*
|
||||
* @this {Panel}
|
||||
* @return {boolean} true if current region checksum differed from previous checksum (ie, one or more regions changed)
|
||||
*/
|
||||
Panel.prototype.findRegions = function()
|
||||
{
|
||||
var checksum = 0;
|
||||
this.stats.cRegions = 0;
|
||||
if (!this.stats.aRegions) this.stats.aRegions = [];
|
||||
var typeRegion = -1, iBlockRegion = 0, addrRegion = 0, nBlockPrev = -1;
|
||||
for (var iBlock = 0; iBlock < this.stats.cBlocks; iBlock++) {
|
||||
var nBlock = this.stats.aBlocks[iBlock];
|
||||
var type = nBlock >>> Bus.BLOCK.TYPE_SHIFT;
|
||||
var nBlockCurr = (nBlock & Bus.BLOCK.MASK);
|
||||
var nBlockCurr = (nBlock & Bus.BLOCK.NUM_MASK);
|
||||
if (type != typeRegion || nBlockCurr != nBlockPrev + 1) {
|
||||
var cBlocks = iBlock - iBlockRegion;
|
||||
if (cBlocks) this.addRegion(addrRegion, iBlockRegion, cBlocks, typeRegion);
|
||||
if (cBlocks) {
|
||||
checksum += this.addRegion(addrRegion, iBlockRegion, cBlocks, typeRegion);
|
||||
}
|
||||
typeRegion = type;
|
||||
iBlockRegion = iBlock;
|
||||
addrRegion = (nBlock & Bus.BLOCK.MASK) << this.bus.blockShift;
|
||||
addrRegion = (nBlock & Bus.BLOCK.NUM_MASK) << this.bus.blockShift;
|
||||
}
|
||||
nBlockPrev = nBlockCurr;
|
||||
}
|
||||
this.addRegion(addrRegion, iBlockRegion, iBlock - iBlockRegion, typeRegion);
|
||||
checksum += this.addRegion(addrRegion, iBlockRegion, iBlock - iBlockRegion, typeRegion);
|
||||
var fChanged = (this.stats.checksumRegions != checksum);
|
||||
this.stats.checksumRegions = checksum;
|
||||
return fChanged;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -266,11 +425,13 @@ Panel.prototype.findRegions = function()
|
|||
* @param {number} iBlock
|
||||
* @param {number} cBlocks
|
||||
* @param {number} type
|
||||
* @return {number} region data added
|
||||
*/
|
||||
Panel.prototype.addRegion = function(addr, iBlock, cBlocks, type)
|
||||
{
|
||||
this.stats.aRegions[this.stats.cRegions++] = (iBlock | cBlocks << 16);
|
||||
if (MAXDEBUG) this.log("region " + this.stats.cRegions + " (addr " + str.toHex(addr) + ", type " + Memory.TYPE.NAMES[type] + ") contains " + cBlocks + " blocks");
|
||||
if (DEBUG) this.log("region " + this.stats.cRegions + " (addr " + str.toHex(addr) + ", type " + Memory.TYPE.NAMES[type] + ") contains " + cBlocks + " blocks");
|
||||
this.assert(iBlock <= Bus.BLOCK.NUM_MASK && cBlocks <= Bus.BLOCK.COUNT_MASK && type <= Bus.BLOCK.TYPE_MASK);
|
||||
return this.stats.aRegions[this.stats.cRegions++] = (iBlock | (cBlocks << Bus.BLOCK.COUNT_SHIFT) | (type << Bus.BLOCK.TYPE_SHIFT));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -287,7 +448,7 @@ Panel.prototype.updateRegisters = function()
|
|||
this.contextLiveRegisters.fillStyle = "black";
|
||||
this.contextLiveRegisters.fillRect(0, 0, this.canvasLiveRegisters.width, this.canvasLiveRegisters.height);
|
||||
|
||||
this.initPen(10, Panel.LIVECANVAS.FONT.HEIGHT, this.canvasLiveRegisters, this.contextLiveRegisters);
|
||||
this.initPen(10, Panel.LIVECANVAS.FONT.HEIGHT, this.canvasLiveRegisters, this.contextLiveRegisters, this.canvas.style.color);
|
||||
this.initCols(3);
|
||||
this.drawText("CPU");
|
||||
this.drawText("Target");
|
||||
|
|
@ -329,27 +490,59 @@ Panel.prototype.updateRegisters = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* initPen(xLeft, yTop, canvasText, contextText)
|
||||
* initPen(xLeft, yTop, canvas, context, sColor)
|
||||
*
|
||||
* @this {Panel}
|
||||
* @param {number} xLeft
|
||||
* @param {number} yTop
|
||||
* @param {Object} [canvasText]
|
||||
* @param {Object} [contextText]
|
||||
* @param {HTMLCanvasElement} [canvas]
|
||||
* @param {Object} [context]
|
||||
* @param {string} [sColor]
|
||||
*/
|
||||
Panel.prototype.initPen = function(xLeft, yTop, canvasText, contextText)
|
||||
Panel.prototype.initPen = function(xLeft, yTop, canvas, context, sColor)
|
||||
{
|
||||
this.xLeftMargin = this.xLeft = xLeft;
|
||||
this.yTop = yTop;
|
||||
if (canvasText) {
|
||||
this.canvasText = canvasText;
|
||||
this.heightText = this.heightDefault = yTop;
|
||||
this.fontText = this.fontDefault = this.heightText + "px " + Panel.LIVECANVAS.FONT.NAME;
|
||||
this.setPen(this.xLeftMargin = xLeft, yTop);
|
||||
if (canvas) {
|
||||
this.canvasText = canvas;
|
||||
}
|
||||
if (contextText) {
|
||||
this.contextText = contextText;
|
||||
this.contextText.fillStyle = this.canvas.style.color
|
||||
if (context) {
|
||||
this.contextText = context;
|
||||
this.colorText = sColor || "white";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* setPen(x, y)
|
||||
*
|
||||
* @this {Panel}
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
Panel.prototype.setPen = function(x, y)
|
||||
{
|
||||
this.xText = x;
|
||||
this.yText = y;
|
||||
};
|
||||
|
||||
/**
|
||||
* centerPen(rect)
|
||||
*
|
||||
* @this {Panel}
|
||||
* @param {Rectangle} rect
|
||||
*/
|
||||
Panel.prototype.centerPen = function(rect)
|
||||
{
|
||||
this.fontText = this.fontDefault;
|
||||
this.heightText = this.heightDefault;
|
||||
if (rect.cy < this.heightText) {
|
||||
this.heightText = rect.cy;
|
||||
this.fontText = this.heightText + "px " + Panel.LIVECANVAS.FONT.NAME;
|
||||
}
|
||||
this.setPen(rect.x + (rect.cx >> 1), rect.y + (rect.cy >> 1));
|
||||
};
|
||||
|
||||
/**
|
||||
* initCols(nCols)
|
||||
*
|
||||
|
|
@ -369,7 +562,7 @@ Panel.prototype.initCols = function(nCols)
|
|||
*/
|
||||
Panel.prototype.skipCols = function(nCols)
|
||||
{
|
||||
this.xLeft += this.cxColumn * nCols;
|
||||
this.xText += this.cxColumn * nCols;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -380,13 +573,14 @@ Panel.prototype.skipCols = function(nCols)
|
|||
*/
|
||||
Panel.prototype.skipLines = function(nLines)
|
||||
{
|
||||
this.xLeft = this.xLeftMargin;
|
||||
this.yTop += (Panel.LIVECANVAS.FONT.HEIGHT + 2) * (nLines || 1);
|
||||
this.xText = this.xLeftMargin;
|
||||
this.yText += (this.heightText + 2) * (nLines || 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* initNumberFormat(nBase, nDigits)
|
||||
*
|
||||
* @this {Panel}
|
||||
* @param {number} nBase
|
||||
* @param {number} nDigits
|
||||
*/
|
||||
|
|
@ -407,20 +601,46 @@ Panel.prototype.initNumberFormat = function(nBase, nDigits)
|
|||
*/
|
||||
Panel.prototype.drawText = function(sText, nValue, nColsSkip, nLinesSkip)
|
||||
{
|
||||
this.contextText.fillText(sText, this.xLeft, this.yTop);
|
||||
this.xLeft += this.cxColumn;
|
||||
this.contextText.font = this.fontText;
|
||||
this.contextText.fillStyle = this.colorText;
|
||||
this.contextText.fillText(sText, this.xText, this.yText);
|
||||
this.xText += this.cxColumn;
|
||||
if (nValue !== undefined) {
|
||||
var sValue = nValue.toString();
|
||||
if (this.nDefaultBase == 16) {
|
||||
sValue = "0x" + str.toHex(nValue, this.nDefaultDigits);
|
||||
}
|
||||
this.contextText.fillText(sValue, this.xLeft, this.yTop);
|
||||
this.xLeft += this.cxColumn;
|
||||
this.contextText.fillText(sValue, this.xText, this.yText);
|
||||
this.xText += this.cxColumn;
|
||||
}
|
||||
if (nColsSkip) this.skipCols(nColsSkip);
|
||||
if (nLinesSkip) this.skipLines(nLinesSkip);
|
||||
};
|
||||
|
||||
/**
|
||||
* centerText(sText)
|
||||
*
|
||||
* To center text within a given Rectangle:
|
||||
*
|
||||
* centerPen(rect)
|
||||
* centerText(sText)
|
||||
*
|
||||
* centerPen() sets xLeft and yTop to the center of the specified rectangle, and centerText() calculates
|
||||
* the width of the text, adjusting the horizontal centering by its width and the vertical centering by the
|
||||
* default font height. Then it call drawText().
|
||||
*
|
||||
* @this {Panel}
|
||||
* @param {string} sText
|
||||
*/
|
||||
Panel.prototype.centerText = function(sText)
|
||||
{
|
||||
this.contextText.font = this.fontText;
|
||||
var tm = this.contextText.measureText(sText);
|
||||
this.xText -= tm.width >> 1;
|
||||
this.yText += (this.heightText >> 1) - 1;
|
||||
this.drawText(sText);
|
||||
};
|
||||
|
||||
/**
|
||||
* Panel.init()
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue