cv-dialog-sdk
Version:
Catavolt Dialog Javascript API
1,396 lines (1,395 loc) • 48.4 kB
JavaScript
import { Log } from '../util/index';
/*
IMPORTANT!
Note #1: Dependency cycles - These classes must be in a single file (module) because of commonjs and circular dependency issues.
Note #2 Dependent ordering - Important! : Because of typescript's 'extends' function, order matters in this file! super classes must be first!
*/
// Skipped in initial port: BarChart, BarcodeScanner, BarOrientation, Defaults, GaugeChart
const XML_CELL = 'Cell';
const XML_FORM = 'Form';
const XML_GRID = 'Grid';
const XML_PAGE = 'Page';
const XML_BUTTON = 'Button';
const XML_CHECKBOX = 'CheckBox';
const XML_DATE_PICKER = 'DatePicker';
const XML_IMAGE = 'Image';
const XML_LABEL = 'Label';
const XML_SIGNATURE_CAPTURE = 'SignatureCapture';
const XML_TEXT_AREA = 'TextArea';
const XML_TEXT_FIELD = 'TextField';
const XML_TIME_PICKER = 'TimePicker';
const XML_VALUE_PICKER = 'ValuePicker';
const XML_CHILDREN = 'Children';
const XML_ALLOW_ANNOTATIONS = 'AllowAnnotations';
const XML_ALLOW_PICKER = 'AllowPicker';
const XML_ALLOW_PICK_OPTIONS = 'AllowPickOptions';
const XML_ALPHA = 'Alpha';
const XML_ASPECT_MODE = 'AspectMode';
const XML_BACKGROUND_COLOR = 'BackgroundColor';
const XML_BINDING = 'Binding';
const XML_BLUE = 'Blue';
const XML_BOLD = 'Bold';
const XML_BORDER_COLOR = 'BorderColor';
const XML_BORDER_WIDTHS = 'BorderWidths';
const XML_BOTTOM = 'Bottom';
const XML_CAP_INSETS = 'CapInsets';
const XML_CAPTURE_BOUNDS = 'CaptureBounds';
const XML_CHECKED_COLOR = 'CheckedColor';
const XML_COLUMN = 'Column';
const XML_ENABLED_IN_READ_MODE = 'EnabledInReadMode';
const XML_ENTRY_SEQ = 'EntrySeq';
const XML_GREEN = 'Green';
const XML_FILL_PARENT = 'FillParent';
const XML_HEIGHT = 'Height';
const XML_ID = 'Id';
const XML_ITALIC = 'Italic';
const XML_LAYOUT = 'Layout';
const XML_LEFT = 'Left';
const XML_LINE_COLOR = 'LineColor';
const XML_LINE_WIDTH = 'LineWidth';
const XML_NUMBER_OF_LINES = 'NumberOfLines';
const XML_ORIGIN = 'Origin';
const XML_PADDING = 'Padding';
const XML_RADIO_GROUP = 'RadioGroup';
const XML_RED = 'Red';
const XML_REFRESH_TIMER = 'RefreshTimer';
const XML_RESIZE_MODE = 'ResizeMode';
const XML_RIGHT = 'Right';
const XML_ROW = 'Row';
const XML_SIZE = 'Size';
const XML_TEXT = 'Text';
const XML_TEXT_ALIGNMENT = 'TextAlignment';
const XML_TEXT_COLOR = 'TextColor';
const XML_TOP = 'Top';
const XML_UNCHECKED_COLOR = 'UncheckedColor';
const XML_UNDERLINE = 'Underline';
const XML_UOM = 'UOM';
const XML_URL = 'URL';
const XML_WIDTH = 'Width';
const XML_X = 'X';
const XML_Y = 'Y';
export class TextAttributes {
constructor() {
this.bold = false;
this.italic = false;
this.underline = false;
this.numberOfLines = 1;
}
}
/**
* *********************************
*/
let GenID = 1; // Generate a unique number if need be for IDs
export class Spec {
constructor(node) {
this.nodeChildDict = {};
if (node) {
PrintUtil.forEachChildNode(node, (n) => {
this.nodeChildDict[n.nodeName] = n;
});
}
}
}
export class Component extends Spec {
constructor(parentContainer, node, overrideLayout) {
super(node);
this._parentContainer = parentContainer;
if (node) {
PrintUtil.ifChild(this.nodeChildDict[XML_BACKGROUND_COLOR], (n) => {
this._backgroundColor = new Color(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_BINDING], (n) => {
this._binding = new Binding(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ID], (n) => {
this._id = PrintUtil.singleChildText(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_LAYOUT], (n) => {
this._layout = new Layout(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_PADDING], (n) => {
this._padding = new Edges(n);
});
if (!this.id) {
this._id = 'GenID-' + GenID++;
}
}
}
initComponentWith(overrideLayout) {
if (overrideLayout) {
this._layout = overrideLayout;
}
if (!this.id) {
this._id = 'Generated-' + GenID++;
}
}
get backgroundColor() {
return this._backgroundColor;
}
get binding() {
return this._binding;
}
get id() {
return this._id;
}
get layout() {
return this._layout;
}
get padding() {
return this._padding;
}
get actualHeights() {
return this._actualHeights;
}
get actualWidths() {
return this._actualWidths;
}
get actualX() {
return this._actualX;
}
get actualY() {
return this._actualY;
}
get height() {
return this._height;
}
get parentContainer() {
return this._parentContainer;
}
get textAttributes() {
return this._textAttributes;
}
get width() {
return this._width;
}
get x() {
return this._x;
}
get y() {
return this._y;
}
}
export class Container extends Component {
constructor(parentContainer, node, overrideContainerWidth) {
super(parentContainer, node);
this._children = [];
if (this.nodeChildDict[XML_CHILDREN]) {
PrintUtil.forEachChildNode(this.nodeChildDict[XML_CHILDREN], (n) => {
const c = ComponentFactory.fromNode(n, this);
if (c) {
this._children.push(c);
}
});
}
}
get children() {
return this._children;
}
get containerWidth() {
if (!this._containerWidth) {
this.calcAndAssignContainerWidth(this.parentContainer);
}
return this._containerWidth;
}
assignChildren(c) {
this._children = c;
}
assignContainerWidth(width) {
this._containerWidth = width;
}
assignParentWidth(parentWidth) {
this.assignContainerWidth(this.layout.sumOfWidths(parentWidth));
}
calcAndAssignContainerWidth(parentContainer) {
// Overriden by Form and Cell for altered behavior
const parentWidth = parentContainer.containerWidth;
if (this.layout == null) {
throw Error('Bogus');
}
this.assignContainerWidth(this.layout.sumOfWidths(parentWidth));
}
initContainerWith(overrideLayout, overideChildren) {
this.initComponentWith(overrideLayout);
if (overideChildren) {
this.assignChildren(overideChildren);
}
}
}
export class PrintProperty extends Spec {
constructor(node) {
super(node);
}
}
/**
* *********************************
*/
export var AspectMode;
(function (AspectMode) {
AspectMode[AspectMode["None"] = 0] = "None";
AspectMode[AspectMode["Fit"] = 1] = "Fit";
AspectMode[AspectMode["Fill"] = 2] = "Fill";
})(AspectMode || (AspectMode = {}));
export var BindingType;
(function (BindingType) {
BindingType[BindingType["Data"] = 0] = "Data";
BindingType[BindingType["Meta"] = 1] = "Meta";
})(BindingType || (BindingType = {}));
export var FormMode;
(function (FormMode) {
FormMode[FormMode["Display"] = 0] = "Display";
FormMode[FormMode["Edit"] = 1] = "Edit";
})(FormMode || (FormMode = {}));
export var ResizeMode;
(function (ResizeMode) {
ResizeMode[ResizeMode["Stretch"] = 0] = "Stretch";
ResizeMode[ResizeMode["Tile"] = 1] = "Tile";
})(ResizeMode || (ResizeMode = {}));
export var RichNumUsage;
(function (RichNumUsage) {
RichNumUsage[RichNumUsage["Undefined"] = 0] = "Undefined";
RichNumUsage[RichNumUsage["Absolute"] = 1] = "Absolute";
RichNumUsage[RichNumUsage["FillParent"] = 2] = "FillParent";
RichNumUsage[RichNumUsage["PercentOfParent"] = 3] = "PercentOfParent";
})(RichNumUsage || (RichNumUsage = {}));
export var RichNumUsageRef;
(function (RichNumUsageRef) {
RichNumUsageRef[RichNumUsageRef["Undefined"] = 0] = "Undefined";
RichNumUsageRef[RichNumUsageRef["Absolute"] = 1] = "Absolute";
RichNumUsageRef[RichNumUsageRef["FillParent"] = 2] = "FillParent";
RichNumUsageRef[RichNumUsageRef["HorizontalCenter"] = 3] = "HorizontalCenter";
RichNumUsageRef[RichNumUsageRef["HorizontalLeft"] = 4] = "HorizontalLeft";
RichNumUsageRef[RichNumUsageRef["HorizontalRight"] = 5] = "HorizontalRight";
RichNumUsageRef[RichNumUsageRef["PercentOfParent"] = 6] = "PercentOfParent";
RichNumUsageRef[RichNumUsageRef["Remainder"] = 7] = "Remainder";
RichNumUsageRef[RichNumUsageRef["VerticalBottom"] = 8] = "VerticalBottom";
RichNumUsageRef[RichNumUsageRef["VerticalCenter"] = 9] = "VerticalCenter";
RichNumUsageRef[RichNumUsageRef["VerticalTop"] = 10] = "VerticalTop";
})(RichNumUsageRef || (RichNumUsageRef = {})); // Just for reference
export var TextAlignmentUsage;
(function (TextAlignmentUsage) {
TextAlignmentUsage[TextAlignmentUsage["Left"] = 0] = "Left";
TextAlignmentUsage[TextAlignmentUsage["Center"] = 1] = "Center";
TextAlignmentUsage[TextAlignmentUsage["Right"] = 2] = "Right";
})(TextAlignmentUsage || (TextAlignmentUsage = {}));
export var ValuePlacement;
(function (ValuePlacement) {
ValuePlacement[ValuePlacement["absolute"] = 0] = "absolute";
ValuePlacement[ValuePlacement["none"] = 1] = "none";
})(ValuePlacement || (ValuePlacement = {}));
export var ValueType;
(function (ValueType) {
ValueType[ValueType["Undefined"] = 0] = "Undefined";
ValueType[ValueType["Boolean"] = 1] = "Boolean";
ValueType[ValueType["Date"] = 2] = "Date";
ValueType[ValueType["DateTime"] = 3] = "DateTime";
ValueType[ValueType["Decimal"] = 4] = "Decimal";
ValueType[ValueType["Float"] = 5] = "Float";
ValueType[ValueType["Integer"] = 6] = "Integer";
ValueType[ValueType["LargeBinary"] = 7] = "LargeBinary";
ValueType[ValueType["LargeString"] = 8] = "LargeString";
ValueType[ValueType["String"] = 9] = "String";
ValueType[ValueType["Time"] = 10] = "Time";
})(ValueType || (ValueType = {}));
export class Binding extends PrintProperty {
constructor(node) {
super(node);
this._type = BindingType.Data;
this._path = PrintUtil.singleChildText(node);
}
get constantValue() {
// Constants are of the form propName[c], where c is the constant
let w = null;
if (this.hasConstant) {
const left = this.path.indexOf('[');
const right = this.path.indexOf(']');
w = this.path.substr(left + 1, right - left - 1);
}
return w;
}
get hasAction() {
return this.path.indexOf('catavolt:action') > -1;
}
get hasConstant() {
// Constants are of the form propName[c], where c is the constant
const left = this.path.indexOf('[');
const right = this.path.indexOf(']');
return left > -1 && right > -1 && right - left > 0;
}
get path() {
return this._path;
}
get propertyName() {
let w = null;
if (this.hasConstant) {
// Constants are of the form propName[c], where c is the constant
// The binding still refrences a property name.
w = this.path.substr(0, this.path.indexOf('['));
}
else if (this.hasAction) {
// No property for an action
}
else {
w = this.path;
}
return w;
}
get type() {
return this._type;
}
}
export class Button extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
PrintUtil.ifChild(this.nodeChildDict[XML_ASPECT_MODE], (n) => {
this._aspectMode = PrintUtil.enumValue(n, AspectMode);
});
PrintUtil.ifChild(this.nodeChildDict[XML_CAP_INSETS], (n) => {
this._capInsets = new Edges(node);
});
PrintUtil.ifChild(this.nodeChildDict[XML_RESIZE_MODE], (n) => {
this._resizeMode = PrintUtil.enumValue(n, ResizeMode);
});
PrintUtil.ifChild(this.nodeChildDict[XML_URL], (n) => {
this._urlString = PrintUtil.singleChildText(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ENABLED_IN_READ_MODE], (n) => {
this._enabledInReadMode = PrintUtil.singleChildBoolean(n);
});
}
get aspectMode() {
return this._aspectMode;
}
get capInsets() {
return this._capInsets;
}
get resizeMode() {
return this._resizeMode;
}
get urlString() {
return this._urlString;
}
get enableInReadMode() {
return this._enabledInReadMode;
}
}
export class CaptureBounds extends PrintProperty {
constructor(node) {
super(node);
PrintUtil.ifChild(this.nodeChildDict[XML_HEIGHT], (n) => {
this._height = PrintUtil.singleChildRichNum(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_WIDTH], (n) => {
this._width = PrintUtil.singleChildRichNum(n);
});
}
get height() {
return this._height;
}
get width() {
return this._width;
}
}
export class PrintCell extends Container {
constructor(parentContainer, node) {
super(parentContainer, node);
this._grid = parentContainer;
PrintUtil.ifChild(this.nodeChildDict[XML_BORDER_COLOR], (n) => {
this._borderColor = new Color(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_BORDER_WIDTHS], (n) => {
this._borderWidths = new Edges(n);
});
}
get borderColor() {
return this._borderColor;
}
get borderWidths() {
return this._borderWidths;
}
get cellHeight() {
return this._grid.layout.heights[this.layout.row].value;
}
get cellWidth() {
return this._grid.layout.widths[this.layout.column].resolveWithFill(this._grid.containerWidth);
}
get componentChildren() {
const answer = [];
this.children.map(c => {
if (!(c instanceof Grid)) {
answer.push(c);
}
});
return answer;
}
get gridChildren() {
const answer = [];
this.children.map(c => {
if (c instanceof Grid) {
answer.push(c);
}
});
return answer;
}
initCellWith(overrideLayout, overrideChildren) {
let ol = overrideLayout;
if (!this.layout && !overrideLayout) {
ol = new Layout(null, NaN, NaN, NaN, NaN, 0, 0);
}
this.initContainerWith(ol, overrideChildren);
if (!this.borderWidths) {
this._borderWidths = new Edges();
this._borderWidths.initEdgesWith(0, 0, 0, 0);
}
}
calcAndAssignContainerWidth(parentContainer) {
if (parentContainer.layout == null) {
throw Error('bogus');
}
const cw = parentContainer.layout.widths[this.layout.column].resolveWithFill(parentContainer.containerWidth);
this.assignContainerWidth(cw);
}
}
export class Checkbox extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
PrintUtil.ifChild(this.nodeChildDict[XML_CHECKED_COLOR], (n) => {
this._checkedColor = new Color(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_LINE_COLOR], (n) => {
this._lineColor = new Color(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_LINE_WIDTH], (n) => {
this._lineWidth = PrintUtil.singleChildFloat(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_RADIO_GROUP], (n) => {
this._radioGroup = PrintUtil.singleChildText(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_UNCHECKED_COLOR], (n) => {
this._uncheckedColor = new Color(n);
});
}
get checkedColor() {
return this._checkedColor;
}
get entrySeq() {
return this._entrySeq;
}
get lineColor() {
return this._lineColor;
}
get lineWidth() {
return this._lineWidth;
}
get radioGroup() {
return this._radioGroup;
}
get uncheckedColor() {
return this._uncheckedColor;
}
}
export class Color extends Spec {
static WHITE() {
const c = new Color(null);
c._red = 255;
c._green = 255;
c._blue = 255;
c._alpha = 255;
return c;
}
static BLACK() {
const c = new Color(null);
c._red = 0;
c._green = 0;
c._blue = 0;
c._alpha = 255;
return c;
}
constructor(node, red, green, blue, alpha) {
super(node);
PrintUtil.ifChild(this.nodeChildDict[XML_RED], (n) => {
this._red = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_BLUE], (n) => {
this._blue = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_GREEN], (n) => {
this._green = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ALPHA], (n) => {
this._alpha = PrintUtil.singleChildFloat(n);
});
if (red !== undefined) {
this._red = red;
}
if (green !== undefined) {
this._green = green;
}
if (blue !== undefined) {
this._blue = blue;
}
if (alpha !== undefined) {
this._alpha = alpha;
}
}
get alpha() {
return this._alpha;
}
get red() {
return this._red;
}
get green() {
return this._green;
}
get blue() {
return this._blue;
}
}
export class DatePicker extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.importTextAttributes(this.nodeChildDict, this.textAttributes);
}
getTextAttributes() {
return this.textAttributes;
}
get entrySeq() {
return this._entrySeq;
}
}
export class Edges extends Spec {
constructor(node) {
super(node);
if (node) {
PrintUtil.ifChild(this.nodeChildDict[XML_TOP], (n) => {
this._top = PrintUtil.singleChildFloat(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_LEFT], (n) => {
this._left = PrintUtil.singleChildFloat(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_BOTTOM], (n) => {
this._bottom = PrintUtil.singleChildFloat(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_RIGHT], (n) => {
this._right = PrintUtil.singleChildFloat(n);
});
}
}
initEdgesWith(top, left, bottom, right) {
this._top = top;
this._left = left;
this._bottom = bottom;
this._right = right;
}
get top() {
return this._top;
}
get left() {
return this._left;
}
get bottom() {
return this._bottom;
}
get right() {
return this._right;
}
}
export class PrintForm extends Container {
static fromXMLString(xmlString) {
const xml = new DOMParser().parseFromString(xmlString, 'text/xml');
return new PrintForm(xml.childNodes[0]);
}
constructor(node) {
if (node) {
// Because super fluffs children, we need to pre-get the Layout to know this Form's width
PrintUtil.forEachChildNode(node, (n) => {
if (n.nodeName == 'Layout') {
const tempLayout = new Layout(n);
this.assignContainerWidth(tempLayout.singleWidthNum());
}
});
}
// node.childNodes.
super(null, node);
// NOTE: Some forms have no pages, other forms have pages. A page always contains exactly
// one 1x1 grid positioned at 0,0 and is the size of the form.
// Doctor up the children such that there are always Pages. If no pages exist, then
// create a Page and a Grid and add these children as the content.
if (this.children && this.children.length && this.children[0] instanceof Grid) {
const p = new Page(this);
const g = new Grid(p);
const c = new PrintCell(g);
c.initCellWith(new Layout(null, 0, 0, 0, 0, 0, 0), this.children);
g.initGridWith(new Layout(null, 0, 0, this.layout.singleWidthNum(), this.layout.singleHeightNum()), [c]);
p.initPageWith(g);
this.assignChildren([p]);
}
}
get hideControlFraming() {
return this._hideControlFraming;
}
get hideSaveCancelButtons() {
return this._hideSaveCancelButtons;
}
get pageChildren() {
return this.children;
}
get settings() {
return this._settings;
}
calcAndAssignContainerWidth(parentContainer) {
this.assignContainerWidth(this.layout.singleWidthNum());
}
}
export class Grid extends Container {
constructor(parentContainer, node) {
super(parentContainer, node);
}
get gridLines() {
if (!this._gridLines) {
this._gridLines = [];
let hasHLines = false;
let hasVLines = false;
const cols = this.layout.widths.length;
const rows = this.layout.heights.length;
const vLines = new Array(rows * cols + rows); // Distinct vertical lines
const hLines = new Array(rows * cols + cols); // Distinct horizointal lines
let colStart = 0;
for (let c = 0; c < cols; c++) {
let rowStart = 0;
const colWidth = this.layout.widths[c].resolveWithFill(this.parentContainer.containerWidth);
for (let r = 0; r < rows; r++) {
const rowHeight = this.layout.heights[r].resolveWithFill(this.parentContainer.containerWidth);
// Vertical lines
let lineWidth = 0;
if (c == 0) {
// Left most vertical
lineWidth = this.cellChildren[r][c].borderWidths.left;
}
else {
// Middle verticals
lineWidth = Math.max(this.cellChildren[r][c - 1].borderWidths.right, this.cellChildren[r][c].borderWidths.left);
}
if (lineWidth) {
vLines[c * rows + r] = new GridLine(new Point(colStart, rowStart), new Point(colStart, rowStart + rowHeight), lineWidth);
hasVLines = true;
}
if (c == cols - 1) {
// Right most vertical
lineWidth = this.cellChildren[r][c].borderWidths.right;
if (lineWidth) {
// Place these appropriately so the combining logic can work.
vLines[cols * rows + r] = new GridLine(new Point(colStart + colWidth, rowStart), new Point(colStart + colWidth, rowStart + rowHeight), lineWidth);
hasVLines = true;
}
}
// Horizontal lines
lineWidth = 0;
if (r == 0) {
// Top most horizontal
lineWidth = this.cellChildren[r][c].borderWidths.top;
}
else {
// Middle horizontals
lineWidth = Math.max(this.cellChildren[r - 1][c].borderWidths.bottom, this.cellChildren[r][c].borderWidths.top);
}
if (lineWidth) {
hLines[r * cols + c] = new GridLine(new Point(colStart, rowStart), new Point(colStart + colWidth, rowStart), lineWidth);
hasHLines = true;
}
if (r == rows - 1) {
// Bottom most horizontal
lineWidth = this.cellChildren[r][c].borderWidths.bottom;
if (lineWidth) {
// Place these appropriately so the combining logic can work.
hLines[cols * rows + c] = new GridLine(new Point(colStart, rowStart + rowHeight), new Point(colStart + colWidth, rowStart + rowHeight), lineWidth);
hasHLines = true;
}
}
rowStart += rowHeight;
}
colStart += colWidth;
}
// Combine adjacent lines
let lastX = NaN;
let lastEndY = NaN;
let lastLineWidth = NaN;
let lastPush = this._gridLines.length - 1;
if (hasVLines) {
for (const gl of vLines) {
if (gl) {
if (isNaN(lastEndY)) {
lastEndY = gl.end.y;
lastX = gl.end.x;
lastLineWidth = gl.lineWidth;
this._gridLines.push(gl);
lastPush++;
}
else if (gl.start.y == lastEndY && gl.start.x == lastX && gl.lineWidth == lastLineWidth) {
// This line and the previous can be combined
lastEndY = gl.end.y;
this._gridLines[lastPush].end = gl.end;
}
else {
this._gridLines.push(gl);
lastPush++;
lastEndY = gl.end.y;
lastX = gl.end.x;
lastLineWidth = gl.lineWidth;
}
}
}
}
if (hasHLines) {
let lastEndX = NaN;
let lastY = NaN;
lastLineWidth = NaN;
lastPush = this._gridLines.length - 1;
for (const gl of hLines) {
if (gl) {
if (isNaN(lastEndX)) {
lastEndX = gl.end.x;
lastY = gl.end.y;
lastLineWidth = gl.lineWidth;
this._gridLines.push(gl);
lastPush++;
}
else if (gl.start.x == lastEndX && gl.start.y == lastY && gl.lineWidth == lastLineWidth) {
// This line and the previous can be combined
lastEndX = gl.end.x;
this._gridLines[lastPush].end = gl.end;
}
else {
this._gridLines.push(gl);
lastPush++;
lastEndX = gl.end.x;
lastY = gl.end.y;
lastLineWidth = gl.lineWidth;
}
}
}
}
}
return this._gridLines;
}
initCells() {
// Structure the cells so that they can be retrieved
this._cellChildren = new Array(this.layout.heights.length);
for (let i = 0; i < this.layout.heights.length; i++) {
this._cellChildren[i] = new Array(this.layout.widths.length);
}
this.children.map((c) => {
this._cellChildren[c.layout.row][c.layout.column] = c;
});
}
get cellChildren() {
if (this._cellChildren == null) {
this.initCells();
}
return this._cellChildren;
}
initGridWith(overrideLayout, overrideChildren) {
super.initContainerWith(overrideLayout, overrideChildren);
this.initCells();
}
}
export class GridLine {
constructor(start, end, lineWidth) {
this.start = start;
this.end = end;
this.lineWidth = lineWidth;
}
}
export class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
export class Image extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
PrintUtil.ifChild(this.nodeChildDict[XML_ALLOW_ANNOTATIONS], (n) => {
this._allowAnnotations = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ALLOW_PICKER], (n) => {
this._allowPicker = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ALLOW_PICK_OPTIONS], (n) => {
this._allowPickOptions = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ASPECT_MODE], (n) => {
this._aspectMode = PrintUtil.enumValue(n, AspectMode);
});
PrintUtil.ifChild(this.nodeChildDict[XML_CAP_INSETS], (n) => {
this._capInsets = new Edges(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_RESIZE_MODE], (n) => {
this._resizeMode = PrintUtil.enumValue(n, ResizeMode);
});
PrintUtil.ifChild(this.nodeChildDict[XML_URL], (n) => {
this._urlString = PrintUtil.singleChildText(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_CAPTURE_BOUNDS], (n) => {
this._captureBounds = new CaptureBounds(n);
});
}
get allowAnnotations() {
return this._allowAnnotations;
}
get allowPicker() {
return this._allowPicker;
}
get allowPickOptions() {
return this._allowPickOptions;
}
get aspectMode() {
return this._aspectMode;
}
get capInsets() {
return this._capInsets;
}
get resizeMode() {
return this._resizeMode;
}
get urlString() {
return this._urlString;
}
get capatureBounds() {
return this._captureBounds;
}
}
export class Label extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.importTextAttributes(this.nodeChildDict, this._textAttributes);
PrintUtil.ifChild(this.nodeChildDict[XML_TEXT], (n) => {
this._text = PrintUtil.singleChildText(n);
});
}
get text() {
return this._text;
}
}
export class Layout extends Spec {
constructor(node, x, y, width, height, row, col) {
super(node);
if (node) {
PrintUtil.ifChild(this.nodeChildDict[XML_UOM], (n) => {
this._uom = PrintUtil.singleChildText(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_COLUMN], (n) => {
this._column = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_ROW], (n) => {
this._row = PrintUtil.singleChildInt(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_SIZE], (n) => {
this._heights = PrintUtil.arrayOfRichNums(n, 'Height');
this._widths = PrintUtil.arrayOfRichNums(n, 'Width');
});
PrintUtil.ifChild(this.nodeChildDict[XML_FILL_PARENT], (n) => {
this._heights = [new RichNum(NaN, RichNumUsage.FillParent)];
this._widths = [new RichNum(NaN, RichNumUsage.FillParent)];
});
PrintUtil.ifChild(this.nodeChildDict[XML_ORIGIN], (n) => {
PrintUtil.forEachChildNode(n, (n2) => {
switch (n2.nodeName) {
case 'X':
this._x = PrintUtil.singleChildFloat(n2);
break;
case 'Y':
this._y = PrintUtil.singleChildFloat(n2);
break;
}
});
});
}
else {
this._x = x;
this._y = y;
this._widths = [new RichNum(width)];
this._heights = [new RichNum(height)];
this._column = col;
this._row = row;
}
}
get uom() {
return this._uom;
}
get heights() {
return this._heights;
}
get widths() {
return this._widths;
}
get x() {
return this._x;
}
get y() {
return this._y;
}
get column() {
return this._column;
}
get row() {
return this._row;
}
singleHeightNum() {
const rn = this.singleHeightRichNum();
if (!rn.isNumber) {
throw Error('Expecting number on height layout');
}
return rn.value;
}
singleHeightRichNum() {
if (!this.heights) {
throw Error('No height values on Layout');
}
else if (this.heights.length != 1) {
throw Error('Expecting exactly 1 height, but found: ' + this.heights.length);
}
else {
return this.heights[0];
}
}
singleWidthNum() {
const rn = this.singleWidthRichNum();
if (!rn.isNumber) {
throw Error('Expecting number on width layout');
}
return rn.value;
}
singleWidthRichNum() {
if (!this.widths) {
throw Error('No width values on Layout');
}
else if (this.widths.length != 1) {
throw Error('Expecting exactly 1 width, but found: ' + this.widths.length);
}
else {
return this.widths[0];
}
}
sumOfHeights() {
let answer = 0.0;
if (!this.heights) {
throw Error('No height values on Layout');
}
this.heights.map((rn) => {
if (!rn) {
throw Error('Unsupported ricn num usage on layout.heights');
}
if (!rn.isNumber) {
throw Error('Expecting number on layout.heights');
}
answer += rn.value;
});
return answer;
}
sumOfWidths(parentSize) {
let answer = 0.0;
if (!this.widths) {
throw Error('No width values on Layout');
}
this.widths.map((rn) => {
if (!rn) {
throw Error('Unsupported ricn num usage on layout.widths');
}
if (rn.isFillParent) {
if (this.widths.length != 1) {
throw Error('More than one value being summed and FillParentWidth used: layout.widths');
}
answer = parentSize;
}
else if (rn.isPercentOfParent) {
answer += parentSize * rn.valueOfPercent;
}
else if (rn.isNumber) {
answer += rn.value;
}
else {
throw Error('Unknown RichNum usage on layout.widths');
}
});
return answer;
}
}
export class Page extends Container {
constructor(parentContainer, node) {
super(parentContainer, node);
}
get gridChildren() {
return this.children;
}
initPageWith(grid) {
this.initContainerWith(null, [grid]);
}
calcAndAssignContainerWidth(parentContainer) {
this.assignContainerWidth(parentContainer.containerWidth);
}
}
export class Settings extends Spec {
constructor(node) {
super(node);
PrintUtil.ifChild(this.nodeChildDict[XML_REFRESH_TIMER], (n) => {
this._refreshTimer = PrintUtil.singleChildInt(n);
});
}
get refreshTimer() {
return this._refreshTimer;
}
}
export class RichNum {
constructor(_value, _usage = RichNumUsage.Absolute) {
this._value = _value;
this._usage = _usage;
}
get value() {
if (!this.isNumber) {
throw Error('RichNum is not a raw number.');
}
return this._value;
}
get valueOfPercent() {
if (!this.isPercentOfParent) {
throw Error('PercentOfParent requested for wrong usage.');
}
return this._value * 0.01;
}
get isNumber() {
return this._usage == RichNumUsage.Absolute;
}
get isFillParent() {
return this._usage == RichNumUsage.FillParent;
}
get isPercentOfParent() {
return this._usage == RichNumUsage.PercentOfParent;
}
resolveWithFill(n) {
let answer;
if (this.isNumber) {
answer = this._value;
}
else if (this.isFillParent) {
answer = n;
}
else if (this.isPercentOfParent) {
answer = this.valueOfPercent * n;
}
else {
throw Error('Unknown RichNum usage on resolveWithFill');
}
return answer;
}
}
RichNum.ZERO = new RichNum(0);
export class SignatureCapture extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
PrintUtil.ifChild(this.nodeChildDict[XML_CAPTURE_BOUNDS], (n) => {
this._captureBounds = new CaptureBounds(n);
});
PrintUtil.ifChild(this.nodeChildDict[XML_LINE_COLOR], (n) => {
this._lineColor = new Color(n);
});
}
get captureBounds() {
return this._captureBounds;
}
get lineColor() {
return this._lineColor;
}
}
export class TextAlignment {
constructor(_usage) {
this._usage = _usage;
}
get isCenter() {
return this._usage == TextAlignmentUsage.Center;
}
get isLeft() {
return this._usage == TextAlignmentUsage.Left;
}
get isRight() {
return this._usage == TextAlignmentUsage.Right;
}
}
export class TextArea extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.importTextAttributes(this.nodeChildDict, this._textAttributes);
}
get entrySeq() {
return this._entrySeq;
}
}
export class TextField extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.importTextAttributes(this.nodeChildDict, this._textAttributes);
}
get entrySeq() {
return this._entrySeq;
}
}
export class TimePicker extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.importTextAttributes(this.nodeChildDict, this._textAttributes);
}
get entrySeq() {
return this._entrySeq;
}
}
export class ValuePicker extends Component {
constructor(parentContainer, node) {
super(parentContainer, node);
this._textAttributes = new TextAttributes();
PrintUtil.ifChild(this.nodeChildDict[XML_ENTRY_SEQ], (n) => {
this._entrySeq = PrintUtil.singleChildInt(n);
});
PrintUtil.importTextAttributes(this.nodeChildDict, this._textAttributes);
}
get entrySeq() {
return this._entrySeq;
}
}
// export class RichNum {
// constructor(node:Node, public value?:number, public usage:RichNumUsage=RichNumUsage.Absolute) {
// if (node) {
//
// } else {
// // Values held by constructor line
// }
// }
//
// }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class ComponentFactory {
static fromNode(node, parentContainer) {
let answer = null;
switch (node.nodeName) {
case XML_BUTTON:
answer = new Button(parentContainer, node);
break;
case XML_CHECKBOX:
answer = new Checkbox(parentContainer, node);
break;
case XML_DATE_PICKER:
answer = new DatePicker(parentContainer, node);
break;
case XML_IMAGE:
answer = new Image(parentContainer, node);
break;
case XML_LABEL:
answer = new Label(parentContainer, node);
break;
case XML_SIGNATURE_CAPTURE:
answer = new SignatureCapture(parentContainer, node);
break;
case XML_TEXT_AREA:
answer = new TextArea(parentContainer, node);
break;
case XML_TEXT_FIELD:
answer = new TextField(parentContainer, node);
break;
case XML_TIME_PICKER:
answer = new TimePicker(parentContainer, node);
break;
case XML_VALUE_PICKER:
answer = new ValuePicker(parentContainer, node);
break;
case XML_CELL:
answer = new PrintCell(parentContainer, node);
break;
case XML_FORM:
answer = new PrintForm(node);
break;
case XML_GRID:
answer = new Grid(parentContainer, node);
break;
case XML_PAGE:
answer = new Page(parentContainer, node);
break;
}
return answer;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class PrintUtil {
static arrayOfRichNums(node, name) {
const answer = [];
PrintUtil.forEachChildNode(node, (n) => {
if (n.nodeName == name) {
answer.push(PrintUtil.singleChildRichNum(n));
}
});
return answer;
}
static enumValue(node, e) {
const answer = null;
const sv = PrintUtil.singleChildText(node);
let nv;
if (sv) {
nv = e[sv];
}
return nv;
}
static forEachChildNode(node, f) {
for (let i = 0; i < node.childNodes.length; i++) {
f(node.childNodes[i]);
}
}
static ifChild(node, f) {
if (node) {
f(node);
}
}
static importTextAttributes(nodeChildDict, textAttributes) {
PrintUtil.ifChild(nodeChildDict[XML_BOLD], (n) => {
textAttributes.bold = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(nodeChildDict[XML_ITALIC], (n) => {
textAttributes.italic = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(nodeChildDict[XML_UNDERLINE], (n) => {
textAttributes.underline = PrintUtil.singleChildBoolean(n);
});
PrintUtil.ifChild(nodeChildDict[XML_TEXT_ALIGNMENT], (n) => {
textAttributes.textAlignment = new TextAlignment(PrintUtil.singleChildTextAlignmentUsage(n));
});
PrintUtil.ifChild(nodeChildDict[XML_TEXT_COLOR], (n) => {
textAttributes.textColor = new Color(n);
});
PrintUtil.ifChild(nodeChildDict[XML_NUMBER_OF_LINES], (n) => {
textAttributes.numberOfLines = PrintUtil.singleChildInt(n);
});
}
static singleChildBoolean(node) {
const text = PrintUtil.singleChildText(node);
if (text) {
return text.toLocaleLowerCase() == 'true';
}
else {
return false;
}
}
static singleChildInt(node) {
let answer;
if (node.childNodes.length != 1) {
Log.error('XML error with ' + node.nodeName + '. Expected exactly one child node.');
}
else if (node.childNodes[0].nodeName != '#text') {
Log.error('XML error with ' + node.nodeName + '. Expected numeric node.');
}
else {
answer = parseInt(node.childNodes[0].textContent);
}
return answer;
}
static singleChildFloat(node) {
let answer;
if (node.childNodes.length != 1) {
Log.error('XML error with ' + node.nodeName + '. Expected exactly one child node.');
}
else if (node.childNodes[0].nodeName != '#text') {
Log.error('XML error with ' + node.nodeName + '. Expected numeric node.');
}
else {
answer = parseFloat(node.childNodes[0].textContent);
}
return answer;
}
static singleChildRichNum(node) {
// Either there is a FillParent entry with surrounding white space, or a single text entry
let answer;
for (let i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeName == RichNumUsage[RichNumUsage.PercentOfParent].toString()) {
const v = this.singleChildFloat(node.childNodes[i]);
answer = new RichNum(v, RichNumUsage.PercentOfParent);
break;
}
else if (node.childNodes[i].nodeName == RichNumUsage[RichNumUsage.FillParent].toString()) {
answer = new RichNum(NaN, RichNumUsage.FillParent);
break;
}
else if (node.childNodes[i].nodeName == '#text') {
const v = parseFloat(node.childNodes[i].textContent.trim());
if (!isNaN(v)) {
answer = new RichNum(v);
}
// Don't break, keep looking for FillParent
}
}
return answer;
}
static singleChildText(node) {
let text = null;
if (node.childNodes.length != 1) {
text = 'ExpectedExactlyOneNode';
Log.error('XML error with ' + node.nodeName + '. Expected exactly one child node.');
}
else if (node.childNodes[0].nodeName != '#text') {
text = 'ExpectedNodeText';
Log.error('XML error with ' + node.nodeName + '. Expected text node.');
}
else {
text = node.childNodes[0].textContent;
}
return text;
}
static singleChildTextAlignmentUsage(node) {
// Either there is a FillParent entry with surrounding white space, or a single text entry
let answer = TextAlignmentUsage.Left;
if (node.childNodes.length != 1) {
Log.error('XML error with ' + node.nodeName + '. Expected exactly one child node.');
}
else if (node.childNodes[0].nodeName != '#text') {
Log.error('XML error with ' + node.nodeName + '. Expected text node.');
}
else {
const a = node.childNodes[0].textContent;
if (a == TextAlignmentUsage[TextAlignmentUsage.Center].toString()) {
answer = TextAlignmentUsage.Center;
}
else if (a == TextAlignmentUsage[TextAlignmentUsage.Left].toString()) {
answer = TextAlignmentUsage.Left;
}
else if (a == TextAlignmentUsage[TextAlignmentUsage.Right].toString()) {
answer = TextAlignmentUsage.Right;
}
else {
Log.error('XML error with ' + node.nodeName + '. Unknown TextAlignment: ' + a);
}
}
return answer;
}
}
/**
* *********************************
*/
/**
* *********************************
*/