276 lines
6.6 KiB
JavaScript
276 lines
6.6 KiB
JavaScript
function UI(async, buttons, dom, screen, session) {
|
|
var lineWidth = 36;
|
|
var textSpeeds = {
|
|
slow: 100,
|
|
medium: 50,
|
|
fast: 20
|
|
};
|
|
var textSpeed = session.get('options').textSpeed;
|
|
|
|
return {
|
|
animation: animation,
|
|
ask: ask,
|
|
cinematic: cinematic,
|
|
frame: frame,
|
|
menu: menu,
|
|
text: text,
|
|
setLayout: setLayout,
|
|
setTextSpeed: setTextSpeed
|
|
};
|
|
|
|
function animation(frames) {
|
|
var frameCounter = 0;
|
|
var scheduled;
|
|
var step = function() {
|
|
if(frameCounter < frames.length) {
|
|
scheduled = null;
|
|
frames[frameCounter].action();
|
|
if(frames[frameCounter].delay != undefined) {
|
|
scheduled = setTimeout(step, frames[frameCounter].delay);
|
|
}
|
|
frameCounter++
|
|
}
|
|
};
|
|
return {
|
|
run: step,
|
|
pause: function() { if(scheduled != undefined) { clearTimeout(scheduled); } }
|
|
};
|
|
}
|
|
|
|
function cinematic(frames, controls) {
|
|
var remote = animation(frames);
|
|
var mapping = {};
|
|
var escaper = function(f) {
|
|
return function() {
|
|
buttons.pop();
|
|
remote.pause();
|
|
f();
|
|
};
|
|
}
|
|
for(var key in controls) {
|
|
mapping[key] = escaper(controls[key]);
|
|
}
|
|
return function(f) {
|
|
buttons.push(mapping);
|
|
remote.run();
|
|
f();
|
|
};
|
|
}
|
|
|
|
function close(elem) {
|
|
buttons.pop();
|
|
screen.clear(elem);
|
|
}
|
|
|
|
function frame(id) {
|
|
screen.clear();
|
|
screen.frame(id);
|
|
}
|
|
|
|
function menu(config) {
|
|
var cursor = config.selected || 0;
|
|
config.direction = config.direction || 'vertical';
|
|
var m = screen.menu(config);
|
|
var sync = function() { screen.select(cursor); };
|
|
var back = function() {
|
|
cursor = (config.entries.length + cursor - 1) % config.entries.length;
|
|
sync();
|
|
};
|
|
var forth = function() {
|
|
cursor = (cursor + 1) % config.entries.length;
|
|
sync();
|
|
};
|
|
var mapping = {
|
|
A: function() {
|
|
var entry = config.entries[cursor];
|
|
if(entry.close) {
|
|
close(m);
|
|
}
|
|
if(entry.action != undefined) {
|
|
entry.action(m);
|
|
}
|
|
}
|
|
};
|
|
mapping[config.direction == 'vertical' ? 'Up' : 'Left'] = back;
|
|
mapping[config.direction == 'vertical' ? 'Down' : 'Right'] = forth;
|
|
if(config.cancel != undefined) {
|
|
mapping['B'] = function() { close(m); config.cancel(); }
|
|
}
|
|
buttons.push(mapping);
|
|
}
|
|
|
|
function ask(config) {
|
|
var menuConfig = {
|
|
cancel: config.cancel,
|
|
direction: config.direction,
|
|
entries: [],
|
|
name: config.name,
|
|
selected: config.selected
|
|
};
|
|
var apply = function(f, val) { return function() { return f(val); }; };
|
|
return function(f) {
|
|
for(var i = 0; i < config.entries.length; i++) {
|
|
var entry;
|
|
if(config.entries[i].label != undefined) {
|
|
entry = {label: config.entries[i].label, action: apply(f, config.entries[i].value), close: true};
|
|
} else if(config.entries[i].picto != undefined) {
|
|
entry = {picto: config.entries[i].picto, action: apply(f, config.entries[i].value), close: true};
|
|
} else {
|
|
entry = {label: '___', action: promptValue(config.entries[i].size, f)};
|
|
}
|
|
menuConfig.entries.push(entry);
|
|
}
|
|
menu(menuConfig);
|
|
};
|
|
}
|
|
|
|
function promptValue(size, f) {
|
|
return function(m) {
|
|
var input = screen.input(size);
|
|
input.focus();
|
|
buttons.push({});
|
|
input.addEventListener('keydown', function(event) {
|
|
switch(event.key) {
|
|
case 'Escape': close(input); break;
|
|
case 'Enter':
|
|
var value = input.value;
|
|
close(input);
|
|
close(m);
|
|
return f(value);
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
function textScreen(message) {
|
|
var characters = message.split('');
|
|
var frames = [];
|
|
var ready = false;
|
|
var append = function(c) { return function() { screen.appendText(c); }; };
|
|
for(var i = 0; i < characters.length; i++) {
|
|
frames.push(
|
|
{action: append(characters[i]), delay: textSpeeds[textSpeed]}
|
|
);
|
|
}
|
|
frames.push({action: function() { ready = true; screen.markAsRead(); }, delay: null});
|
|
var remote = animation(frames);
|
|
return function(f) {
|
|
buttons.push({
|
|
'A': function() {
|
|
if(ready) {
|
|
buttons.pop();
|
|
f();
|
|
} else {
|
|
remote.pause();
|
|
screen.text(message);
|
|
ready = true;
|
|
}
|
|
}
|
|
});
|
|
screen.text('');
|
|
remote.run();
|
|
};
|
|
}
|
|
|
|
function text(message) {
|
|
var words = message.split(' ');
|
|
var i = 0;
|
|
var line = '';
|
|
var screen = null;
|
|
var screens = [];
|
|
var width = 0;
|
|
while (i < words.length) {
|
|
if(width == 0) {
|
|
line = words[i];
|
|
width += line.length;
|
|
i++;
|
|
} else {
|
|
if(width + words[i].length + 1 <= lineWidth) {
|
|
line += ' ' + words[i];
|
|
width += 1 + words[i].length;
|
|
i++;
|
|
} else {
|
|
if(screen === null) {
|
|
screen = line;
|
|
} else {
|
|
screens.push(screen + ' ' + line);
|
|
screen = null;
|
|
}
|
|
line = '';
|
|
width = 0;
|
|
}
|
|
}
|
|
}
|
|
screens.push(screen === null ? line : screen + ' ' + line);
|
|
return async.sequence.apply(null,
|
|
screens.map(function(s) { return textScreen(s); })
|
|
);
|
|
}
|
|
|
|
function keyPromptLabel(key, button) {
|
|
return button + " : " + (key != undefined ? "[" + key + "]" : "???");
|
|
}
|
|
|
|
function setLayout() {
|
|
var layout = session.get('options').layout
|
|
var buttonsMenu = {
|
|
cancel: function() {},
|
|
entries: [],
|
|
name: "layout"
|
|
};
|
|
for(var key in layout) {
|
|
buttonsMenu.entries[buttons.code(layout[key])] = {
|
|
label: keyPromptLabel(key, layout[key]),
|
|
action: setKey(layout[key])
|
|
};
|
|
}
|
|
menu(buttonsMenu);
|
|
}
|
|
|
|
function setKey(button) {
|
|
return function(f) {
|
|
buttons.push({});
|
|
var elem = dom.make('div', {
|
|
class: ['framed', 'center'],
|
|
textContent: "Press the key you wanna map to " + button
|
|
});
|
|
screen.currentMenu().getElementsByClassName('selected')[0].textContent = keyPromptLabel(null, button);
|
|
var promptKey = function(event) {
|
|
var assignment = buttons.assign(event.key, button);
|
|
session.update({options: {layout: assignment.layoutDiff}});
|
|
screen.clear(elem);
|
|
screen.currentMenu().getElementsByClassName('selected')[0].textContent = keyPromptLabel(event.key, button);
|
|
document.removeEventListener('keydown', promptKey);
|
|
buttons.pop();
|
|
if(assignment.button != undefined) {
|
|
screen.select(buttons.code(assignment.button));
|
|
return setKey(assignment.button)(function () {
|
|
screen.select(buttons.code(button));
|
|
});
|
|
}
|
|
return f();
|
|
};
|
|
screen.show(elem);
|
|
document.addEventListener('keydown', promptKey);
|
|
}
|
|
}
|
|
|
|
function setTextSpeed(choices) {
|
|
var config = {
|
|
entries: [],
|
|
cancel: choices.cancel,
|
|
name: choices.name
|
|
};
|
|
for(var i = 0; i < choices.entries.length; i++) {
|
|
config.entries[i] = choices.entries[i];
|
|
if(choices.entries[i].value == textSpeed) {
|
|
config.selected = i;
|
|
}
|
|
}
|
|
ask(config)(function(value) {
|
|
session.update({options: {textSpeed: value}});
|
|
textSpeed = value;
|
|
});
|
|
}
|
|
}
|