# 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(); }, };