var row = rows[0];
var candidateLength = rows[0].childElementCount;
for (var i = 1; i < rows.length; i++) {
- if (rows[i].childElementCount > candidateLength) {
+ if (rows[i].childElementCount > candidateLength &&
+ rows[i].align == RowAlignment.STRETCH) {
row = rows[i];
candidateLength = rows[i].childElementCount;
}
// Sum of all keys in the current row.
var keyWeightSumX = 0;
- for (var i=0; i< allKeys.length; i++) {
+ for (var i = 0; i < allKeys.length; i++) {
keyWeightSumX += allKeys[i].weight;
}
var totalWeightX = keyWeightSumX + interspaceWeightSumX +
keyset.weightLeft + keyset.weightRight;
- var totalWeightY = (DEFAULT_KEY_WEIGHT_Y * rows.length) +
- (pitchWeightY * (rows.length - 1)) +
- keyset.weightTop +
- keyset.weightBottom;
-
+ var totalWeightY = (pitchWeightY * (rows.length - 1)) +
+ keyset.weightTop +
+ keyset.weightBottom;
+ for (var i = 0; i < rows.length; i++) {
+ totalWeightY += rows[i].weight;
+ }
// Calculate width and height of the window.
var bounds = exports.getKeyboardBounds();
- var width;
- var height;
- var pixelPerWeight;
- if (totalWeightX/bounds.width < totalWeightY/bounds.height) {
- height = bounds.height;
- pixelPerWeight = bounds.height/totalWeightY;
- width = Math.floor(pixelPerWeight * totalWeightX)
- }
- else {
- width = bounds.width;
- pixelPerWeight = bounds.width/totalWeightX;
- height = Math.floor(pixelPerWeight * totalWeightY);
+ var width = bounds.width;
+ var height = bounds.height;
+ var pixelPerWeightX = bounds.width/totalWeightX;
+ var pixelPerWeightY = bounds.height/totalWeightY;
+
+ if (keyset.align == LayoutAlignment.CENTER) {
+ if (totalWeightX/bounds.width < totalWeightY/bounds.height) {
+ pixelPerWeightY = bounds.height/totalWeightY;
+ pixelPerWeightX = pixelPerWeightY;
+ width = Math.floor(pixelPerWeightX * totalWeightX)
+ } else {
+ pixelPerWeightX = bounds.width/totalWeightX;
+ pixelPerWeightY = pixelPerWeightX;
+ height = Math.floor(pixelPerWeightY * totalWeightY);
+ }
}
// Calculate pitch.
- this.pitchX = Math.floor(pitchWeightX * pixelPerWeight);
- this.pitchY = Math.floor(pitchWeightY * pixelPerWeight);
+ this.pitchX = Math.floor(pitchWeightX * pixelPerWeightX);
+ this.pitchY = Math.floor(pitchWeightY * pixelPerWeightY);
// Convert weight to pixels on x axis.
- this.keyWidth = Math.floor(DEFAULT_KEY_WEIGHT_X * pixelPerWeight);
- var offsetLeft = Math.floor(keyset.weightLeft * pixelPerWeight);
- var offsetRight = Math.floor(keyset.weightRight * pixelPerWeight);
+ this.keyWidth = Math.floor(DEFAULT_KEY_WEIGHT_X * pixelPerWeightX);
+ var offsetLeft = Math.floor(keyset.weightLeft * pixelPerWeightX);
+ var offsetRight = Math.floor(keyset.weightRight * pixelPerWeightX);
this.availableWidth = width - offsetLeft - offsetRight;
// Calculates weight to pixels on the y axis.
- this.keyHeight = Math.floor(DEFAULT_KEY_WEIGHT_Y * pixelPerWeight);
- var offsetTop = Math.floor(keyset.weightTop * pixelPerWeight);
- var offsetBottom = Math.floor(keyset.weightBottom * pixelPerWeight);
+ this.keyHeight = Math.floor(DEFAULT_KEY_WEIGHT_Y * pixelPerWeightY);
+ var offsetTop = Math.floor(keyset.weightTop * pixelPerWeightY);
+ var offsetBottom = Math.floor(keyset.weightBottom * pixelPerWeightY);
this.availableHeight = height - offsetTop - offsetBottom;
var dX = bounds.width - width;
function getKeyboardBounds_() {
return {
"width": window.innerWidth,
- "height": window.innerHeight
+ "height": window.innerHeight,
};
}
/**
* Callback function for when the window is resized.
*/
var onResize = function() {
- var bounds = exports.getKeyboardBounds();
- var height = (bounds.width > ASPECT_RATIO * bounds.height) ?
- bounds.height : Math.floor(bounds.width / ASPECT_RATIO);
var keyboard = $('keyboard');
- keyboard.style.fontSize = (height / FONT_SIZE_RATIO / ROW_LENGTH) + 'px';
keyboard.stale = true;
var keyset = keyboard.activeKeyset;
if (keyset)
function updateKey(key, width, height, left, top) {
key.style.position = 'absolute';
key.style.width = width + 'px';
- key.style.height = (height - KEY_PADDING_TOP) + 'px';
+ key.style.height = (height - KEY_PADDING_TOP - KEY_PADDING_BOTTOM) + 'px';
key.style.left = left + 'px';
key.style.top = (top + KEY_PADDING_TOP) + 'px';
}
/**
* Redistributes the total width amongst the keys in the range provided.
* @param {Array.<kb-key>} allKeys Ordered list of keys to stretch.
- * @param {number} pitch The space between two keys.
+ * @param {AlignmentOptions} params Options for aligning the keyset.
* @param {number} xOffset The x-coordinate of the key who's index is start.
* @param {number} width The total extraneous width to distribute.
* @param {number} keyHeight The height of each key.
* @param {number} yOffset The y-coordinate of the top edge of the row.
*/
- function redistribute(allKeys, pitch, xOffset, width, keyHeight, yOffset) {
- var weight = 0;
+ function redistribute(allKeys, params, xOffset, width, keyHeight, yOffset) {
+ var availableWidth = width - (allKeys.length - 1) * params.pitchX;
+ var stretchWeight = 0;
+ var nStretch = 0;
for (var i = 0; i < allKeys.length; i++) {
- weight += allKeys[i].weight;
+ var key = allKeys[i];
+ if (key.stretch) {
+ stretchWeight += key.weight;
+ nStretch++;
+ } else if (key.weight == DEFAULT_KEY_WEIGHT_X) {
+ availableWidth -= params.keyWidth;
+ } else {
+ availableWidth -=
+ Math.floor(key.weight/DEFAULT_KEY_WEIGHT_X * params.keyWidth);
+ }
}
- var availableWidth = width - (allKeys.length - 1) * pitch;
- var pixelsPerWeight = width / weight;
+ if (stretchWeight <= 0)
+ console.error("Cannot stretch row without a stretchable key");
+ // Rounding error to distribute.
+ var pixelsPerWeight = availableWidth / stretchWeight;
for (var i = 0; i < allKeys.length; i++) {
- var keyWidth = Math.floor(allKeys[i].weight * pixelsPerWeight);
- if (i == allKeys.length -1) {
- keyWidth = availableWidth;
+ var key = allKeys[i];
+ var keyWidth = params.keyWidth;
+ if (key.weight != DEFAULT_KEY_WEIGHT_X) {
+ keyWidth =
+ Math.floor(key.weight/DEFAULT_KEY_WEIGHT_X * params.keyWidth);
}
- updateKey(allKeys[i], keyWidth, keyHeight, xOffset, yOffset)
- availableWidth -= keyWidth;
- xOffset += keyWidth + pitch;
+ if (key.stretch) {
+ nStretch--;
+ if (nStretch > 0) {
+ keyWidth = Math.floor(key.weight * pixelsPerWeight);
+ availableWidth -= keyWidth;
+ } else {
+ keyWidth = availableWidth;
+ }
+ }
+ updateKey(key, keyWidth, keyHeight, xOffset, yOffset)
+ xOffset += keyWidth + params.pitchX;
}
}
* it. A precondition is that all keys in this row can be stretched as needed.
* @param {!kb-row} row The current row to be aligned.
* @param {!kb-row} prevRow The row above the current row.
- * @param {!AlignmentOptions} params The parameters used to align the keyset.
+ * @param {!AlignmentOptions} params Options for aligning the keyset.
+ * @param {number} keyHeight The height of the keys in this row.
* @param {number} heightOffset The height offset caused by the rows above.
*/
- function realignSpacebarRow(row, prevRow, params, heightOffset) {
+ function realignSpacebarRow(row, prevRow, params, keyHeight, heightOffset) {
var allKeys = row.children;
var stretchWeightBeforeSpace = 0;
var stretchBefore = 0;
var leftWidth = leftEdge - params.offsetLeft - params.pitchX;
var leftKeys = allKeys.array().slice(0, spaceIndex);
redistribute(leftKeys,
- params.pitchX,
+ params,
params.offsetLeft,
leftWidth,
- params.keyHeight,
+ keyHeight,
yOffset);
// Fix right side.
var rightEdge = parseFloat(rightKey.style.left) +
var spacebarWidth = rightEdge - leftEdge;
updateKey(allKeys[spaceIndex],
spacebarWidth,
- params.keyHeight,
+ keyHeight,
leftEdge,
yOffset);
var rightWidth =
params.availableWidth - (rightEdge - params.offsetLeft + params.pitchX);
var rightKeys = allKeys.array().slice(spaceIndex + 1);
redistribute(rightKeys,
- params.pitchX,
+ params,
rightEdge + params.pitchX,//xOffset.
rightWidth,
- params.keyHeight,
+ keyHeight,
yOffset);
}
* Realigns a given row based on the parameters provided.
* @param {!kb-row} row The row to realign.
* @param {!AlignmentOptions} params The parameters used to align the keyset.
+ * @param {number} The height of the keys.
* @param {number} heightOffset The offset caused by rows above it.
*/
- function realignRow(row, params, heightOffset) {
+ function realignRow(row, params, keyHeight, heightOffset) {
var all = row.children;
- var stretch = [];
+ var nStretch = 0;
var stretchWeightSum = 0;
var allSum = 0;
-
+ // Keeps track of where to distribute pixels caused by round off errors.
+ var deltaWidth = [];
for (var i = 0; i < all.length; i++) {
+ deltaWidth.push(0)
var key = all[i];
if (key.weight == DEFAULT_KEY_WEIGHT_X){
allSum += params.keyWidth;
- continue;
- }
- stretch.push(key)
- var width =
+ } else {
+ var width =
Math.floor((params.keyWidth/DEFAULT_KEY_WEIGHT_X) * key.weight);
- allSum += width;
+ allSum += width;
+ }
+ if (!key.stretch)
+ continue;
+ nStretch++;
stretchWeightSum += key.weight;
}
- var nStretch = stretch.length;
var nRegular = all.length - nStretch;
// Extra space.
var extra = params.availableWidth -
allSum -
(params.pitchX * (all.length -1));
var xOffset = params.offsetLeft;
+
var alignment = row.align;
switch (alignment) {
case RowAlignment.STRETCH:
var extraPerWeight = extra/stretchWeightSum;
- for (var i = 0; i < stretch.length; i++) {
- var bonus = Math.floor(stretch[i].weight * extraPerWeight);
- extra -= bonus;
- // All left-over pixels assigned to right most key.
- if (i == (stretch.length - 1))
- stretch[i].setAttribute('bonus', bonus + extra);
- else
- stretch[i].setAttribute('bonus', bonus);
+ for (var i = 0; i < all.length; i++) {
+ if (!all[i].stretch)
+ continue;
+ var delta = Math.floor(all[i].weight * extraPerWeight);
+ extra -= delta;
+ deltaWidth[i] = delta;
+ // All left-over pixels assigned to right most stretchable key.
+ nStretch--;
+ if (nStretch == 0)
+ deltaWidth[i] += extra;
}
break;
case RowAlignment.CENTER:
xOffset += Math.floor(extra/2)
break;
- case RowAlignment.JUSTIFY:
+ case RowAlignment.RIGHT:
xOffset += extra;
break;
default:
for (var i = 0; i < all.length; i++) {
var key = all[i];
var width = params.keyWidth;
- if (key.weight != DEFAULT_KEY_WEIGHT_X) {
+ if (key.weight != DEFAULT_KEY_WEIGHT_X)
width = Math.floor((params.keyWidth/DEFAULT_KEY_WEIGHT_X) * key.weight)
- var bonus = key.getAttribute('bonus')
- if (bonus)
- width += parseInt(bonus)
- }
- updateKey(key, width, params.keyHeight, left, yOffset)
+ width += deltaWidth[i];
+ updateKey(key, width, keyHeight, left, yOffset)
left += (width + params.pitchX);
}
}
*/
function realignKeyset(keyset, params) {
var rows = keyset.querySelectorAll('kb-row').array();
+ keyset.style.fontSize = (params.availableHeight /
+ FONT_SIZE_RATIO / rows.length) + 'px';
+
var heightOffset = 0;
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
+ var rowHeight =
+ Math.floor(params.keyHeight * (row.weight/DEFAULT_KEY_WEIGHT_Y))
if (row.querySelector('.space') && (i > 1)) {
- realignSpacebarRow(row, rows[i-1], params, heightOffset)
+ realignSpacebarRow(row, rows[i-1], params, rowHeight, heightOffset)
} else {
- realignRow(row, params, heightOffset);
+ realignRow(row, params, rowHeight, heightOffset);
}
- heightOffset += (params.keyHeight + params.pitchY);
+ heightOffset += (rowHeight + params.pitchY);
}
}
window.addEventListener('realign', requestRealign);