Skip to content

Commit

Permalink
feat(web): lazy construction of OSK layers
Browse files Browse the repository at this point in the history
  • Loading branch information
jahorton committed Apr 19, 2024
1 parent c90e6a3 commit b231b4d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 22 deletions.
52 changes: 35 additions & 17 deletions web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { ActiveLayer, type DeviceSpec, Keyboard, LayoutLayer, ActiveLayout, ButtonClasses } from '@keymanapp/keyboard-processor';
import { type DeviceSpec, Keyboard, ActiveLayout, ButtonClasses } from '@keymanapp/keyboard-processor';

import { InputSample } from '@keymanapp/gesture-recognizer';

import { KeyElement } from '../keyElement.js';
import OSKLayer, { LayerLayoutParams } from './oskLayer.js';
import VisualKeyboard from '../visualKeyboard.js';
import OSKBaseKey from './oskBaseKey.js';
import { ParsedLengthStyle } from '../lengthStyle.js';

const NEAREST_KEY_TOUCH_MARGIN_PERCENT = 0.06;

export default class OSKLayerGroup {
public readonly element: HTMLDivElement;
public readonly layers: {[layerID: string]: OSKLayer} = {};
private readonly layers: {[layerID: string]: OSKLayer} = {};
public readonly spec: ActiveLayout;

// Currently stored to facilitate lazy layer construction.
private vkbd: VisualKeyboard;

// Exist as local copies of the VisualKeyboard values, updated via refreshLayout.
private computedWidth: number;
private computedHeight: number;
Expand All @@ -23,8 +25,9 @@ export default class OSKLayerGroup {
private _heightPadding: number;

public constructor(vkbd: VisualKeyboard, keyboard: Keyboard, formFactor: DeviceSpec.FormFactor) {
let layout = keyboard.layout(formFactor);
const layout = keyboard.layout(formFactor);
this.spec = layout;
this.vkbd = vkbd;

const lDiv = this.element = document.createElement('div');
const ls=lDiv.style;
Expand All @@ -48,23 +51,35 @@ export default class OSKLayerGroup {
ls.width = '100%';
ls.height = '100%';

// Create a separate OSK div for each OSK layer, only one of which will ever be visible
var n: number, i: number, j: number;
var layers: LayoutLayer[];
this.activeLayerId = 'default';
}

private buildLayer(layerId: string) {
const layout = this.spec;

layers=layout['layer'];
const layerSpec = layout.getLayer(layerId);
if(!layerSpec) {
return null;
}

for(n=0; n<layers.length; n++) {
let layer=layers[n] as ActiveLayer;
const layerObj = new OSKLayer(vkbd, layout, layer);
this.layers[layer.id] = layerObj;
const layer = new OSKLayer(this.vkbd, layout, layerSpec);
this.layers[layerId] = layer;

// Always make the 'default' layer visible by default.
layerObj.element.style.display = (layer.id == 'default' ? 'block' : 'none');
// Add layer to group
this.element.appendChild(layer.element);
}

// Add layer to group
lDiv.appendChild(layerObj.element);
public getLayer(id: string) {
let layer = this.layers[id];
if(!layer) {
layer = this.buildLayer(id);
if(layer) {
this.layers[id] = layer;
layer.element.style.display = 'none';
}
}

return layer;
}

public get activeLayer(): OSKLayer {
Expand All @@ -82,6 +97,9 @@ export default class OSKLayerGroup {
public set activeLayerId(id: string) {
this._activeLayerId = id;

// Trigger construction of the layer if it does not already exist.
this.getLayer(id);

for (let key of Object.keys(this.layers)) {
const layer = this.layers[key];
const layerElement = layer.element;
Expand Down Expand Up @@ -130,7 +148,7 @@ export default class OSKLayerGroup {
public blinkLayer(arg: OSKLayer | string) {
if(typeof arg === 'string') {
const layerId = arg;
arg = this.layers[layerId];
arg = this.getLayer(layerId);
if(!arg) {
throw new Error(`Layer id ${layerId} could not be found`);
}
Expand Down
2 changes: 1 addition & 1 deletion web/src/engine/osk/src/views/oskView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ export default abstract class OSKView
//
// Also, only change the layer ID itself if there is an actual corresponding layer
// in the OSK.
if(this.vkbd?.layerGroup.layers[newValue] && !this.vkbd?.layerLocked) {
if(this.vkbd?.layerGroup.getLayer(newValue) && !this.vkbd?.layerLocked) {
// triggers state-update + layer refresh automatically.
this.vkbd.layerId = newValue;
}
Expand Down
8 changes: 4 additions & 4 deletions web/src/engine/osk/src/visualKeyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke

set layerId(value: string) {
const changedLayer = value != this.layerId;
if(!this.layerGroup.layers[value]) {
if(!this.layerGroup.getLayer(value)) {
throw new Error(`Keyboard ${this.layoutKeyboard.id} does not have a layer with id ${value}`);
} else {
this.layerGroup.activeLayerId = value;
Expand Down Expand Up @@ -1058,7 +1058,7 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke
layerId = this.layerId;
}

const layer = this.layerGroup.layers[layerId];
const layer = this.layerGroup.getLayer(layerId);
if (!layer) {
return;
}
Expand Down Expand Up @@ -1291,13 +1291,13 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke
return allottedHeight;
}

const layers = this.layerGroup.layers;
const layers = this.layerGroup.spec.layer;
let oskHeight = 0;

// In case the keyboard's layers have differing row counts, we check them all for the maximum needed oskHeight.
for (const layerID in layers) {
const layer = layers[layerID];
let nRows = layer.rows.length;
let nRows = layer.row.length;
let rowHeight = Math.floor(allottedHeight / (nRows == 0 ? 1 : nRows));
let layerHeight = nRows * rowHeight;

Expand Down

0 comments on commit b231b4d

Please sign in to comment.