201 lines
6.5 KiB
Text
201 lines
6.5 KiB
Text
|
# PFD DataEntryElement - Data Entry UI Element.
|
||
|
#
|
||
|
# Uses the FMS Knobs to enter a text value with a given length and character set.
|
||
|
#
|
||
|
# To use, there must be an element called [PageName][ElementName] which will
|
||
|
# be used for the complete string, and a set of [PageName][ElementName]{0...n}
|
||
|
# elements, each consisting of a single character for input.
|
||
|
#
|
||
|
var DataEntryElement =
|
||
|
{
|
||
|
new : func (pagename, svg, name, value, size, charSet, style=nil)
|
||
|
{
|
||
|
var obj = {
|
||
|
parents : [ DataEntryElement, PFD.UIElement ],
|
||
|
_name : pagename ~ name,
|
||
|
_size : size,
|
||
|
_charSet : charSet,
|
||
|
_dataEntryPos : -1,
|
||
|
_dataEntrySymbol : [],
|
||
|
_style : style,
|
||
|
};
|
||
|
|
||
|
if (style == nil) obj._style = PFD.DefaultStyle;
|
||
|
|
||
|
obj._symbol = svg.getElementById(obj._name);
|
||
|
assert(obj._symbol != nil, "Unable to find element" ~ obj._name);
|
||
|
obj.setValue(value);
|
||
|
|
||
|
for (var i = 0; i < size; i = i + 1) {
|
||
|
var nodeName = obj._name ~ i;
|
||
|
append(obj._dataEntrySymbol, svg.getElementById(nodeName));
|
||
|
assert(obj._dataEntrySymbol[i] != nil, "Unable to find element " ~ nodeName);
|
||
|
obj._dataEntrySymbol[i].setVisible(0);
|
||
|
}
|
||
|
|
||
|
# State and timer for flashing highlighting of elements
|
||
|
obj._highlighted = 0;
|
||
|
obj._highlightedChar = 0;
|
||
|
obj._flashTimer = nil;
|
||
|
obj._flashCharTimer = nil;
|
||
|
|
||
|
return obj;
|
||
|
},
|
||
|
|
||
|
getName : func() { return me._name; },
|
||
|
getValue : func() { return me._symbol.getText(); },
|
||
|
setValue : func(value) { me._symbol.setText(value); },
|
||
|
setVisible : func(vis) {
|
||
|
me._symbol.setVisible(vis);
|
||
|
|
||
|
# Only ever hide the character entry symbols, as they are displayed
|
||
|
# only when editing
|
||
|
if (vis == 0) {
|
||
|
for (var i = 0; i < me._size; i = i + 1) me._dataEntrySymbol[i].setVisible(0);
|
||
|
}
|
||
|
},
|
||
|
_flashElement : func() {
|
||
|
if (me._highlighted == 0) {
|
||
|
me._symbol.setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
|
||
|
me._symbol.setColorFill(me._style.HIGHLIGHT_COLOR);
|
||
|
me._symbol.setColor(me._style.HIGHLIGHT_TEXT_COLOR);
|
||
|
me._highlighted = 1;
|
||
|
} else {
|
||
|
me._symbol.setDrawMode(canvas.Text.TEXT);
|
||
|
me._symbol.setColor(me._style.NORMAL_TEXT_COLOR);
|
||
|
me._highlighted = 0;
|
||
|
}
|
||
|
},
|
||
|
highlightElement : func() {
|
||
|
me._flashElement();
|
||
|
me._flashTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashElement);
|
||
|
me._flashTimer.start();
|
||
|
},
|
||
|
unhighlightElement : func() {
|
||
|
if (me._flashTimer != nil) me._flashTimer.stop();
|
||
|
me._flashTimer = nil;
|
||
|
|
||
|
# Reset the highlight to a non-highlighted state.
|
||
|
me._highlighted = 1;
|
||
|
me._flashElement();
|
||
|
},
|
||
|
|
||
|
_flashCharElement : func() {
|
||
|
if (me._highlighted == 0) {
|
||
|
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX);
|
||
|
me._dataEntrySymbol[me._dataEntryPos].setColorFill(me._style.HIGHLIGHT_COLOR);
|
||
|
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.HIGHLIGHT_TEXT_COLOR);
|
||
|
me._highlightedChar = 1;
|
||
|
} else {
|
||
|
me._dataEntrySymbol[me._dataEntryPos].setDrawMode(canvas.Text.TEXT);
|
||
|
me._dataEntrySymbol[me._dataEntryPos].setColor(me._style.NORMAL_TEXT_COLOR);
|
||
|
me._highlightedChar = 0;
|
||
|
}
|
||
|
},
|
||
|
highlightCharElement : func() {
|
||
|
me._flashCharElement();
|
||
|
me._flashCharTimer = maketimer(me._style.CURSOR_BLINK_PERIOD, me, me._flashCharElement);
|
||
|
me._flashCharTimer.start();
|
||
|
},
|
||
|
unhighlightCharElement : func() {
|
||
|
if (me._flashCharTimer != nil) me._flashCharTimer.stop();
|
||
|
me._flashCharTimer = nil;
|
||
|
|
||
|
# Reset the highlight to a non-highlighted state.
|
||
|
me._highlightedChar = 1;
|
||
|
me._flashCharElement();
|
||
|
},
|
||
|
isEditable : func () { return 1; },
|
||
|
isInEdit : func() { return (me._dataEntryPos != -1); },
|
||
|
|
||
|
enterElement : func() {
|
||
|
# Handle pressing enter to confirm this element.
|
||
|
# - Hiding the per-character entry fields
|
||
|
# - concatenating the data that's been entered into a string
|
||
|
# - displaying the string in the (highlighted) top level element
|
||
|
#
|
||
|
# Also pass back the string to the caller.
|
||
|
|
||
|
var val = "";
|
||
|
|
||
|
for (var i = 0; i < me._size; i = i + 1) {
|
||
|
if (me._dataEntrySymbol[i].getText() != "_") {
|
||
|
val = val ~ me._dataEntrySymbol[i].getText();
|
||
|
}
|
||
|
me._dataEntrySymbol[i].setVisible(0);
|
||
|
}
|
||
|
|
||
|
me._symbol.setText(val);
|
||
|
me._symbol.setVisible(1);
|
||
|
me.highlightElement();
|
||
|
me._dataEntryPos = -1;
|
||
|
return val;
|
||
|
},
|
||
|
clearElement : func() {
|
||
|
# Cancel editing this element by
|
||
|
# - Hiding the per-character entry fields
|
||
|
# - Highlighting the top level element
|
||
|
|
||
|
for (var i = 0; i < me._size; i = i + 1) {
|
||
|
me._dataEntrySymbol[i].setVisible(0);
|
||
|
}
|
||
|
|
||
|
me._symbol.setVisible(1);
|
||
|
me.highlightElement();
|
||
|
me._dataEntryPos = -1;
|
||
|
},
|
||
|
incrSmall : func(value) {
|
||
|
# Change the value of this element, or start editing it if we're not already
|
||
|
# doing so.
|
||
|
|
||
|
if (me._dataEntryPos == -1) {
|
||
|
# Start editing by hiding the top level element, and displaying and
|
||
|
# resetting the character entry fields.
|
||
|
me._dataEntryPos = 0;
|
||
|
|
||
|
me._symbol.setVisible(0);
|
||
|
|
||
|
for (var i = 0; i < me._size; i = i + 1) {
|
||
|
me._dataEntrySymbol[i].setText("_");
|
||
|
me._dataEntrySymbol[i].setVisible(1);
|
||
|
}
|
||
|
|
||
|
# Highlight the first character element to indicate we're editing it
|
||
|
me.highlightCharElement();
|
||
|
} else {
|
||
|
var charSym = me._dataEntrySymbol[me._dataEntryPos];
|
||
|
var incr_or_decr = (value > 0) ? 1 : -1;
|
||
|
|
||
|
# Change the value of the data element
|
||
|
var val = charSym.getText();
|
||
|
|
||
|
if (val == "_") {
|
||
|
# Not previously set, so set to the first or last characterset entry
|
||
|
# depending on direction
|
||
|
if (incr_or_decr > 0) {
|
||
|
charSym.setText(chr(me._charSet[0]));
|
||
|
} else {
|
||
|
charSym.setText(chr(me._charSet[size(me._charSet) -1]));
|
||
|
}
|
||
|
} else {
|
||
|
var curIdx = find(val, me._charSet);
|
||
|
|
||
|
if (curIdx == -1) die("Failed to find character " ~ val ~ " in dataEntryElement " ~ element);
|
||
|
curIdx = math.mod(curIdx + incr_or_decr, size(me._charSet));
|
||
|
charSym.setText(chr(me._charSet[curIdx]));
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
incrLarge : func(value) {
|
||
|
# Change the cursor position within a data element
|
||
|
var incr_or_decr = (value > 0) ? 1 : -1;
|
||
|
|
||
|
if ((me._dataEntryPos == 0) and (incr_or_decr == -1)) return; # Don't scroll off the start
|
||
|
if ((me._dataEntryPos == me._size -1) and (incr_or_decr == 1)) return; # Don't scroll off the end
|
||
|
|
||
|
me.unhighlightCharElement();
|
||
|
me._dataEntryPos = me._dataEntryPos + incr_or_decr;
|
||
|
me.highlightCharElement();
|
||
|
},
|
||
|
};
|