spiegel-keyman/web/source/osk/oskBaseKey.ts

164 lines
5.5 KiB
TypeScript

/// <reference path="oskKey.ts" />
namespace com.keyman.osk {
let Codes = com.keyman.text.Codes;
export class OSKBaseKey extends OSKKey {
private capLabel: HTMLDivElement;
public readonly row: OSKRow;
constructor(spec: OSKKeySpec, layer: string, row: OSKRow) {
super(spec, layer);
this.row = row;
}
getId(): string {
// Define each key element id by layer id and key id (duplicate possible for SHIFT - does it matter?)
return this.spec.elementID;
}
getCoreId(): string {
return this.spec.coreID;
}
getBaseId(): string {
return this.spec.baseKeyID;
}
// Produces a small reference label for the corresponding physical key on a US keyboard.
private generateKeyCapLabel(): HTMLDivElement {
// Create the default key cap labels (letter keys, etc.)
var x = Codes.keyCodes[this.spec.baseKeyID];
switch(x) {
// Converts the keyman key id code for common symbol keys into its representative ASCII code.
// K_COLON -> K_BKQUOTE
case 186: x=59; break;
case 187: x=61; break;
case 188: x=44; break;
case 189: x=45; break;
case 190: x=46; break;
case 191: x=47; break;
case 192: x=96; break;
// K_LBRKT -> K_QUOTE
case 219: x=91; break;
case 220: x=92; break;
case 221: x=93; break;
case 222: x=39; break;
default:
// No other symbol character represents a base key on the standard QWERTY English layout.
if(x < 48 || x > 90) {
x=0;
}
}
let q = document.createElement('div');
q.className='kmw-key-label';
if(x > 0) {
q.innerText=String.fromCharCode(x);
} else {
// Keyman-only virtual keys have no corresponding physical key.
// So, no text for the key-cap.
}
return q;
}
private processSubkeys(btn: KeyElement, vkbd: VisualKeyboard) {
// Add reference to subkey array if defined
var bsn: number, bsk=btn['subKeys'] = this.spec['sk'];
// Transform any special keys into their PUA representations.
for(bsn=0; bsn<bsk.length; bsn++) {
if(bsk[bsn]['sp'] == '1' || bsk[bsn]['sp'] == '2') {
var oldText=bsk[bsn]['text'];
bsk[bsn]['text']=this.renameSpecialKey(oldText, vkbd);
}
// If a subkey doesn't have a defined layer property, copy it from the base key's layer by default.
if(!bsk[bsn].layer) {
bsk[bsn].layer = btn.key.layer
}
}
// If a subkey array is defined, add an icon
var skIcon = document.createElement('div');
skIcon.className='kmw-key-popup-icon';
//kDiv.appendChild(skIcon);
btn.appendChild(skIcon);
}
construct(vkbd: VisualKeyboard): HTMLDivElement {
let spec = this.spec;
let kDiv = document.createElement('div');
kDiv.className='kmw-key-square';
let btnEle = document.createElement('div');
let btn = this.btn = link(btnEle, new KeyData(this, spec['id']));
// Set button class
this.setButtonClass();
// Add the (US English) keycap label for layouts requesting display of underlying keys
let keyCap = this.capLabel = this.generateKeyCapLabel();
btn.appendChild(keyCap);
// Define each key element id by layer id and key id (duplicate possible for SHIFT - does it matter?)
btn.id=this.getId();
// Make sure the key text is the element's first child - processSubkeys()
// will add an extra element if subkeys exist, which can interfere with
// keyboard/language name display on the space bar!
btn.appendChild(this.label = this.generateKeyText(vkbd));
// Handle subkey-related tasks.
if(typeof(spec['sk']) != 'undefined' && spec['sk'] != null) {
this.processSubkeys(btn, vkbd);
} else {
btn['subKeys']=null;
}
// Add text to button and button to placeholder div
kDiv.appendChild(btn);
// The 'return value' of this process.
return this.square = kDiv;
}
public refreshLayout(vkbd: VisualKeyboard) {
let key = this.spec as keyboards.ActiveKey;
this.square.style.width = vkbd.layoutWidth.scaledBy(key.proportionalWidth).styleString;
this.square.style.marginLeft = vkbd.layoutWidth.scaledBy(key.proportionalPad).styleString;
this.btn.style.width = vkbd.usesFixedWidthScaling ? this.square.style.width : '100%';
if(vkbd.usesFixedHeightScaling) {
// Matches its row's height.
this.square.style.height = vkbd.internalHeight.scaledBy(this.row.heightFraction).styleString;
} else {
this.square.style.height = '100%'; // use the full row height
}
super.refreshLayout(vkbd);
let util = com.keyman.singleton.util;
const device = vkbd.device;
const resizeLabels = (device.OS == utils.OperatingSystem.iOS &&
device.formFactor == utils.FormFactor.Phone
&& util.landscapeView());
// Rescale keycap labels on iPhone (iOS 7)
if(resizeLabels && this.capLabel) {
this.capLabel.style.fontSize = '6px';
}
}
public get displaysKeyCap(): boolean {
return this.capLabel && this.capLabel.style.display == 'block';
}
public set displaysKeyCap(flag: boolean) {
if(!this.capLabel) {
throw new Error("Key element not yet constructed; cannot display key cap");
}
this.capLabel.style.display = flag ? 'block' : 'none';
}
}
}