export struct BitInfo { value: bool, index: int, } component BitCell inherits Rectangle { callback toggled(); in property on; width: 14px; height: 16px; border-radius: 2px; background: touch.has-hover ? #3a4550 : transparent; Text { text: root.on ? "1" : "0"; color: root.on ? #60cdff : #6a6a6a; font-size: 10px; font-weight: 700; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { clicked => { root.toggled(); } } } component BitLine inherits Rectangle { callback toggle-bit(int); in property <[BitInfo]> cells; height: 28px; background: transparent; VerticalLayout { spacing: 0px; HorizontalLayout { padding-left: 2px; padding-right: 2px; height: 10px; Text { text: root.cells.length > 0 ? "\{root.cells[0].index}" : ""; color: #808080; font-size: 9px; horizontal-alignment: left; vertical-alignment: center; } Text { text: root.cells.length > 0 ? "\{root.cells[root.cells.length - 1].index}" : ""; color: #808080; font-size: 9px; horizontal-alignment: right; vertical-alignment: center; } } HorizontalLayout { spacing: 0px; padding-left: 2px; alignment: start; for c[i] in root.cells: HorizontalLayout { spacing: 0px; if i > 0 && mod(i, 4) == 0: Rectangle { width: 6px; height: 1px; } BitCell { on: c.value; toggled => { root.toggle-bit(c.index); } } } } } } component MemBtn inherits Rectangle { callback clicked(); in property label; height: 32px; background: touch.has-hover ? #323232 : transparent; border-radius: 4px; Text { text: root.label; color: #c8c8c8; font-size: 13px; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { clicked => { root.clicked(); } } } component FuncBtn inherits Rectangle { callback clicked(); in property label; in property enabled: true; in property min-h: 42px; background: !root.enabled ? #2a2a2a : (touch.has-hover ? #464646 : #323232); border-radius: 4px; min-height: root.min-h; opacity: root.enabled ? 1.0 : 0.45; Text { text: root.label; color: white; font-size: 14px; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { enabled: root.enabled; clicked => { root.clicked(); } } } component DigitBtn inherits Rectangle { callback clicked(); in property label; in property enabled: true; in property min-h: 42px; background: !root.enabled ? #2a2a2a : (touch.has-hover ? #505050 : #3b3b3b); border-radius: 4px; min-height: root.min-h; opacity: root.enabled ? 1.0 : 0.4; Text { text: root.label; color: white; font-size: 16px; font-weight: 600; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { enabled: root.enabled; clicked => { root.clicked(); } } } component EqBtn inherits Rectangle { callback clicked(); in property min-h: 42px; background: touch.has-hover ? #78d7ff : #60cdff; border-radius: 4px; min-height: root.min-h; Text { text: "="; color: #141414; font-size: 18px; font-weight: 700; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { clicked => { root.clicked(); } } } component ModeTab inherits Rectangle { callback clicked(); in property label; in property active; height: 30px; border-radius: 4px; background: root.active ? #3b3b3b : (touch.has-hover ? #2c2c2c : transparent); Text { text: root.label; color: root.active ? #60cdff : #c8c8c8; font-size: 13px; font-weight: root.active ? 700 : 500; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { clicked => { root.clicked(); } } } component BaseRow inherits Rectangle { callback clicked(); in property label; in property value; in property active; height: 24px; border-radius: 4px; background: root.active ? #2f3a42 : (touch.has-hover ? #2a2a2a : transparent); HorizontalLayout { padding-left: 8px; padding-right: 8px; spacing: 12px; Text { text: root.label; color: root.active ? #60cdff : #9a9a9a; font-size: 12px; font-weight: 700; width: 36px; vertical-alignment: center; } Text { text: root.value; color: white; font-size: 13px; font-family: "Cascadia Mono, Consolas, monospace"; horizontal-alignment: left; vertical-alignment: center; overflow: elide; } } touch := TouchArea { clicked => { root.clicked(); } } } component FieldRow inherits Rectangle { callback clicked(); in property label; in property value; in property active; height: 40px; border-radius: 4px; background: root.active ? #2f3a42 : (touch.has-hover ? #2a2a2a : #262626); border-width: root.active ? 1px : 0; border-color: #60cdff; HorizontalLayout { padding-left: 10px; padding-right: 10px; spacing: 12px; Text { text: root.label; color: root.active ? #60cdff : #9a9a9a; font-size: 12px; font-weight: 700; width: 64px; vertical-alignment: center; } Text { text: root.value; color: white; font-size: 20px; font-weight: 600; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; horizontal-alignment: right; vertical-alignment: center; overflow: elide; } } touch := TouchArea { clicked => { root.clicked(); } } } component EndianChip inherits Rectangle { callback clicked(); in property label; in property active; height: 30px; border-radius: 4px; background: root.active ? #3b3b3b : (touch.has-hover ? #2c2c2c : #262626); border-width: root.active ? 1px : 0; border-color: #60cdff; Text { text: root.label; color: root.active ? #60cdff : #c8c8c8; font-size: 12px; font-weight: root.active ? 700 : 500; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; horizontal-alignment: center; vertical-alignment: center; } touch := TouchArea { clicked => { root.clicked(); } } } export component AppWindow inherits Window { title: "rcalc"; icon: @image-url("../assets/icon-256.png"); preferred-width: 420px; preferred-height: 640px; min-width: 380px; min-height: 520px; background: #202020; // 0 = standard, 1 = programmer, 2 = convert, 3 = crc in-out property mode: 0; in property display-text: "0"; in property expression-text: ""; in property has-memory: false; in property hex-text: "0"; in property dec-text: "0"; in property oct-text: "0"; in property bin-text: "0"; // 0=hex 1=dec 2=oct 3=bin in property active-base: 1; in property word-size-label: "QWORD"; in property show-bits: true; in property bit-row-count: 0; in property <[BitInfo]> bit-row0; in property <[BitInfo]> bit-row1; in property <[BitInfo]> bit-row2; in property <[BitInfo]> bit-row3; // Convert tab // 0=words 1=ratio in property conv-panel: 0; in property conv-endian: 0; // 0=AB CD 1=CD AB 2=BA DC 3=DC BA in property conv-active: 0; // 0=float 1=word0 2=word1 in property conv-float: "0"; in property conv-word0: "0000"; in property conv-word1: "0000"; in property conv-bytes: "00 00 00 00"; in property conv-ieee: "0x00000000"; in property conv-error: ""; in property ratio-width: 1; // 0=byte 1=word in property ratio-precision: "1e-6"; in property ratio-num: "1"; in property ratio-den: "1"; in property ratio-frac: "1 / 1"; in property ratio-approx: "1"; in property ratio-error: "exact"; in property ascii-char: "A"; in property ascii-hex: "41"; in property ascii-dec: "65"; in property ascii-name: "'A'"; // CRC tab in-out property crc-input: "01 03 00 00 00 0A"; in property crc-parsed: ""; in property crc-count: "0"; in property crc-rtu-bytes: "—"; in property crc-rtu-word: "—"; in property crc-rtu-frame: "—"; in property crc-ascii-lrc: "—"; in property crc-ascii-frame: "—"; in property crc-error: ""; callback key-pressed(string); callback crc-edited(string); function press(id: string) { root.key-pressed(id); } property hex-digits: root.mode == 1 && root.active-base == 0; property allow-2: root.mode == 0 || root.active-base <= 2; property allow-8: root.mode == 0 || root.active-base <= 1; property allow-a: root.mode == 1 && root.active-base == 0; VerticalLayout { padding: 12px; spacing: 6px; HorizontalLayout { spacing: 6px; height: 30px; ModeTab { label: "Standard"; active: root.mode == 0; clicked => { root.press("mode:std"); } } ModeTab { label: "Programmer"; active: root.mode == 1; clicked => { root.press("mode:prog"); } } ModeTab { label: "Convert"; active: root.mode == 2; clicked => { root.press("mode:conv"); } } ModeTab { label: "CRC"; active: root.mode == 3; clicked => { root.press("mode:crc"); } } } if root.mode == 0 || root.mode == 1: HorizontalLayout { height: 18px; Text { text: root.has-memory && root.mode == 0 ? "M" : ""; color: #b4b4b4; font-size: 12px; horizontal-alignment: left; vertical-alignment: center; width: 16px; } Text { text: root.mode == 1 ? root.word-size-label : ""; color: #60cdff; font-size: 11px; vertical-alignment: center; } Text { text: root.expression-text; color: #aaaaaa; font-size: 13px; horizontal-alignment: right; vertical-alignment: center; } } if root.mode == 0 || root.mode == 1: Text { text: root.display-text; color: white; font-size: root.mode == 1 ? 28px : 34px; font-weight: 700; horizontal-alignment: right; vertical-alignment: center; height: root.mode == 1 ? 40px : 48px; overflow: elide; } if root.mode == 3: VerticalLayout { spacing: 10px; Text { text: "Hex bytes (space-separated)"; color: #9a9a9a; font-size: 12px; } Rectangle { height: 44px; border-radius: 4px; background: #2a2a2a; border-width: 1px; border-color: crc-input.has-focus ? #60cdff : #3a3a3a; crc-input := TextInput { x: 10px; width: parent.width - 20px; height: 100%; color: white; font-size: 15px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; single-line: true; text <=> root.crc-input; edited => { root.crc-edited(self.text); } } } Text { text: "example: 01 03 00 00 00 0A"; color: #666666; font-size: 11px; } if root.crc-error != "": Text { text: root.crc-error; color: #ff8a80; font-size: 12px; } HorizontalLayout { height: 18px; Text { text: "Parsed"; color: #9a9a9a; font-size: 11px; width: 70px; } Text { text: root.crc-parsed; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; overflow: elide; } } HorizontalLayout { height: 18px; Text { text: "Length"; color: #9a9a9a; font-size: 11px; width: 70px; } Text { text: root.crc-count + " bytes"; color: #c8c8c8; font-size: 12px; } } Rectangle { height: 1px; background: #333333; } Text { text: "Modbus RTU (CRC-16)"; color: #60cdff; font-size: 13px; font-weight: 700; } HorizontalLayout { height: 22px; Text { text: "CRC"; color: #9a9a9a; font-size: 12px; width: 70px; vertical-alignment: center; } Text { text: root.crc-rtu-bytes + " (" + root.crc-rtu-word + ")"; color: white; font-size: 16px; font-weight: 700; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; vertical-alignment: center; } } Text { text: "lo hi — append after PDU"; color: #666666; font-size: 11px; } HorizontalLayout { height: 18px; Text { text: "Frame"; color: #9a9a9a; font-size: 11px; width: 70px; } Text { text: root.crc-rtu-frame; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; overflow: elide; } } Rectangle { height: 1px; background: #333333; } Text { text: "Modbus ASCII (LRC)"; color: #60cdff; font-size: 13px; font-weight: 700; } HorizontalLayout { height: 22px; Text { text: "LRC"; color: #9a9a9a; font-size: 12px; width: 70px; vertical-alignment: center; } Text { text: root.crc-ascii-lrc; color: white; font-size: 16px; font-weight: 700; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; vertical-alignment: center; } } HorizontalLayout { height: 18px; Text { text: "Frame"; color: #9a9a9a; font-size: 11px; width: 70px; } Text { text: root.crc-ascii-frame; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; overflow: elide; } } Rectangle { height: 8px; background: transparent; } HorizontalLayout { spacing: 6px; height: 36px; FuncBtn { min-h: 36px; label: "Clear"; clicked => { root.crc-input = ""; root.crc-edited(""); } } FuncBtn { min-h: 36px; label: "Example"; clicked => { root.crc-input = "01 03 00 00 00 0A"; root.crc-edited(root.crc-input); } } } } if root.mode == 2: VerticalLayout { spacing: 8px; HorizontalLayout { spacing: 6px; height: 30px; ModeTab { label: "Words"; active: root.conv-panel == 0; clicked => { root.press("panel:words"); } } ModeTab { label: "Ratio"; active: root.conv-panel == 1; clicked => { root.press("panel:ratio"); } } ModeTab { label: "ASCII"; active: root.conv-panel == 2; clicked => { root.press("panel:ascii"); } } } if root.conv-panel == 0: VerticalLayout { spacing: 8px; Text { text: "Endian (byte / word order)"; color: #9a9a9a; font-size: 12px; } HorizontalLayout { spacing: 6px; height: 30px; EndianChip { label: "AB CD"; active: root.conv-endian == 0; clicked => { root.press("endian:0"); } } EndianChip { label: "CD AB"; active: root.conv-endian == 1; clicked => { root.press("endian:1"); } } EndianChip { label: "BA DC"; active: root.conv-endian == 2; clicked => { root.press("endian:2"); } } EndianChip { label: "DC BA"; active: root.conv-endian == 3; clicked => { root.press("endian:3"); } } } FieldRow { label: "Float32"; value: root.conv-float; active: root.conv-active == 0; clicked => { root.press("conv:float"); } } FieldRow { label: "Word 0"; value: root.conv-word0; active: root.conv-active == 1; clicked => { root.press("conv:w0"); } } FieldRow { label: "Word 1"; value: root.conv-word1; active: root.conv-active == 2; clicked => { root.press("conv:w1"); } } HorizontalLayout { height: 18px; Text { text: "Wire"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.conv-bytes; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } HorizontalLayout { height: 18px; Text { text: "IEEE"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.conv-ieee; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } } if root.conv-panel == 1: VerticalLayout { spacing: 8px; Text { text: "Electronic gear: float → num / den"; color: #9a9a9a; font-size: 12px; } HorizontalLayout { spacing: 6px; height: 30px; EndianChip { label: "Byte (≤255)"; active: root.ratio-width == 0; clicked => { root.press("rwidth:byte"); } } EndianChip { label: "Word (≤65535)"; active: root.ratio-width == 1; clicked => { root.press("rwidth:word"); } } } HorizontalLayout { spacing: 6px; height: 30px; Text { text: "Precision"; color: #9a9a9a; font-size: 12px; vertical-alignment: center; width: 70px; } EndianChip { label: root.ratio-precision; active: true; clicked => { root.press("rprec"); } } Text { text: "rel. error (tap to cycle)"; color: #666666; font-size: 11px; vertical-alignment: center; } } FieldRow { label: "Float32"; value: root.conv-float; active: true; clicked => { root.press("conv:float"); } } FieldRow { label: "Num"; value: root.ratio-num; active: false; clicked => { } } FieldRow { label: "Den"; value: root.ratio-den; active: false; clicked => { } } HorizontalLayout { height: 18px; Text { text: "Frac"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.ratio-frac; color: #60cdff; font-size: 13px; font-weight: 700; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } HorizontalLayout { height: 18px; Text { text: "≈"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.ratio-approx; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } HorizontalLayout { height: 18px; Text { text: "Err"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.ratio-error; color: #c8c8c8; font-size: 12px; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } } if root.conv-panel == 2: VerticalLayout { spacing: 8px; Text { text: "ASCII / Latin-1 · Char ↔ Hex ↔ Dec"; color: #9a9a9a; font-size: 12px; } FieldRow { label: "Char"; value: root.ascii-char; active: root.conv-active == 0; clicked => { root.press("ascii:char"); } } FieldRow { label: "Hex"; value: root.ascii-hex; active: root.conv-active == 1; clicked => { root.press("ascii:hex"); } } FieldRow { label: "Dec"; value: root.ascii-dec; active: root.conv-active == 2; clicked => { root.press("ascii:dec"); } } HorizontalLayout { height: 20px; Text { text: "Name"; color: #9a9a9a; font-size: 11px; width: 40px; } Text { text: root.ascii-name; color: #60cdff; font-size: 13px; font-weight: 700; font-family: "Cascadia Mono, Consolas, DejaVu Sans Mono, monospace"; } } Text { text: "Char: type on keyboard · Hex/Dec: keypad"; color: #666666; font-size: 11px; } } if root.conv-error != "": Text { text: root.conv-error; color: #ff8a80; font-size: 12px; } GridLayout { spacing: 5px; Row { FuncBtn { label: "CE"; clicked => { root.press("CE"); } } FuncBtn { label: "C"; clicked => { root.press("clear"); } } FuncBtn { label: "⌫"; clicked => { root.press("BS"); } } FuncBtn { label: "±"; enabled: root.conv-panel == 1 || (root.conv-panel == 0 && root.conv-active == 0); clicked => { root.press("neg"); } } } Row { DigitBtn { label: "A"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("A"); } } DigitBtn { label: "B"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("B"); } } DigitBtn { label: "C"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("C"); } } DigitBtn { label: "D"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("D"); } } } Row { DigitBtn { label: "E"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("E"); } } DigitBtn { label: "F"; enabled: (root.conv-panel == 0 && root.conv-active != 0) || (root.conv-panel == 2 && root.conv-active != 2); clicked => { root.press("F"); } } DigitBtn { label: "."; enabled: root.conv-panel == 1 || (root.conv-panel == 0 && root.conv-active == 0); clicked => { root.press("."); } } FuncBtn { label: "e"; enabled: root.conv-panel == 1 || (root.conv-panel == 0 && root.conv-active == 0); clicked => { root.press("e"); } } } Row { DigitBtn { label: "7"; clicked => { root.press("7"); } } DigitBtn { label: "8"; clicked => { root.press("8"); } } DigitBtn { label: "9"; clicked => { root.press("9"); } } DigitBtn { label: "4"; clicked => { root.press("4"); } } } Row { DigitBtn { label: "5"; clicked => { root.press("5"); } } DigitBtn { label: "6"; clicked => { root.press("6"); } } DigitBtn { label: "1"; clicked => { root.press("1"); } } DigitBtn { label: "2"; clicked => { root.press("2"); } } } Row { DigitBtn { label: "3"; clicked => { root.press("3"); } } DigitBtn { label: "0"; clicked => { root.press("0"); } } FuncBtn { label: "Spc"; enabled: root.conv-panel == 2 && root.conv-active == 0; clicked => { root.press(" "); } } Rectangle { background: transparent; } } } } if root.mode == 1: VerticalLayout { spacing: 2px; BaseRow { label: "HEX"; value: root.hex-text; active: root.active-base == 0; clicked => { root.press("base:hex"); } } BaseRow { label: "DEC"; value: root.dec-text; active: root.active-base == 1; clicked => { root.press("base:dec"); } } BaseRow { label: "OCT"; value: root.oct-text; active: root.active-base == 2; clicked => { root.press("base:oct"); } } BaseRow { label: "BIN"; value: root.bin-text; active: root.active-base == 3; clicked => { root.press("base:bin"); } } } if root.mode == 1 && root.show-bits: VerticalLayout { spacing: 2px; padding-top: 4px; padding-bottom: 4px; if root.bit-row-count > 0: BitLine { cells: root.bit-row0; toggle-bit(idx) => { root.press("bit:\{idx}"); } } if root.bit-row-count > 1: BitLine { cells: root.bit-row1; toggle-bit(idx) => { root.press("bit:\{idx}"); } } if root.bit-row-count > 2: BitLine { cells: root.bit-row2; toggle-bit(idx) => { root.press("bit:\{idx}"); } } if root.bit-row-count > 3: BitLine { cells: root.bit-row3; toggle-bit(idx) => { root.press("bit:\{idx}"); } } } if root.mode == 0: HorizontalLayout { spacing: 6px; height: 32px; MemBtn { label: "MC"; clicked => { root.press("MC"); } } MemBtn { label: "MR"; clicked => { root.press("MR"); } } MemBtn { label: "M+"; clicked => { root.press("M+"); } } MemBtn { label: "M-"; clicked => { root.press("M-"); } } MemBtn { label: "MS"; clicked => { root.press("MS"); } } } if root.mode == 0: GridLayout { spacing: 6px; Row { FuncBtn { label: "%"; clicked => { root.press("%"); } } FuncBtn { label: "CE"; clicked => { root.press("CE"); } } FuncBtn { label: "C"; clicked => { root.press("C"); } } FuncBtn { label: "⌫"; clicked => { root.press("BS"); } } } Row { FuncBtn { label: "1/x"; clicked => { root.press("1/x"); } } FuncBtn { label: "x²"; clicked => { root.press("x2"); } } FuncBtn { label: "√x"; clicked => { root.press("sqrt"); } } FuncBtn { label: "÷"; clicked => { root.press("/"); } } } Row { DigitBtn { label: "7"; clicked => { root.press("7"); } } DigitBtn { label: "8"; clicked => { root.press("8"); } } DigitBtn { label: "9"; clicked => { root.press("9"); } } FuncBtn { label: "×"; clicked => { root.press("*"); } } } Row { DigitBtn { label: "4"; clicked => { root.press("4"); } } DigitBtn { label: "5"; clicked => { root.press("5"); } } DigitBtn { label: "6"; clicked => { root.press("6"); } } FuncBtn { label: "−"; clicked => { root.press("-"); } } } Row { DigitBtn { label: "1"; clicked => { root.press("1"); } } DigitBtn { label: "2"; clicked => { root.press("2"); } } DigitBtn { label: "3"; clicked => { root.press("3"); } } FuncBtn { label: "+"; clicked => { root.press("+"); } } } Row { DigitBtn { label: "±"; clicked => { root.press("neg"); } } DigitBtn { label: "0"; clicked => { root.press("0"); } } DigitBtn { label: "."; clicked => { root.press("."); } } EqBtn { clicked => { root.press("="); } } } } if root.mode == 1: GridLayout { spacing: 4px; Row { FuncBtn { min-h: 34px; label: root.word-size-label; clicked => { root.press("word"); } } FuncBtn { min-h: 34px; label: "CE"; clicked => { root.press("CE"); } } FuncBtn { min-h: 34px; label: "C"; clicked => { root.press("clear"); } } FuncBtn { min-h: 34px; label: "⌫"; clicked => { root.press("BS"); } } } Row { FuncBtn { min-h: 34px; label: "AND"; clicked => { root.press("AND"); } } FuncBtn { min-h: 34px; label: "OR"; clicked => { root.press("OR"); } } FuncBtn { min-h: 34px; label: "NOT"; clicked => { root.press("NOT"); } } FuncBtn { min-h: 34px; label: "NAND"; clicked => { root.press("NAND"); } } } Row { FuncBtn { min-h: 34px; label: "NOR"; clicked => { root.press("NOR"); } } FuncBtn { min-h: 34px; label: "XOR"; clicked => { root.press("XOR"); } } FuncBtn { min-h: 34px; label: "Lsh"; clicked => { root.press("Lsh"); } } FuncBtn { min-h: 34px; label: "Rsh"; clicked => { root.press("Rsh"); } } } Row { DigitBtn { min-h: 34px; label: "A"; enabled: root.allow-a; clicked => { root.press("A"); } } DigitBtn { min-h: 34px; label: "B"; enabled: root.allow-a; clicked => { root.press("B"); } } DigitBtn { min-h: 34px; label: "C"; enabled: root.allow-a; clicked => { root.press("C"); } } FuncBtn { min-h: 34px; label: "÷"; clicked => { root.press("/"); } } } Row { DigitBtn { min-h: 34px; label: "D"; enabled: root.allow-a; clicked => { root.press("D"); } } DigitBtn { min-h: 34px; label: "E"; enabled: root.allow-a; clicked => { root.press("E"); } } DigitBtn { min-h: 34px; label: "F"; enabled: root.allow-a; clicked => { root.press("F"); } } FuncBtn { min-h: 34px; label: "×"; clicked => { root.press("*"); } } } Row { DigitBtn { min-h: 34px; label: "7"; enabled: root.allow-2; clicked => { root.press("7"); } } DigitBtn { min-h: 34px; label: "8"; enabled: root.allow-8; clicked => { root.press("8"); } } DigitBtn { min-h: 34px; label: "9"; enabled: root.allow-8; clicked => { root.press("9"); } } FuncBtn { min-h: 34px; label: "−"; clicked => { root.press("-"); } } } Row { DigitBtn { min-h: 34px; label: "4"; enabled: root.allow-2; clicked => { root.press("4"); } } DigitBtn { min-h: 34px; label: "5"; enabled: root.allow-2; clicked => { root.press("5"); } } DigitBtn { min-h: 34px; label: "6"; enabled: root.allow-2; clicked => { root.press("6"); } } FuncBtn { min-h: 34px; label: "+"; clicked => { root.press("+"); } } } Row { DigitBtn { min-h: 34px; label: "1"; clicked => { root.press("1"); } } DigitBtn { min-h: 34px; label: "2"; enabled: root.active-base != 3; clicked => { root.press("2"); } } DigitBtn { min-h: 34px; label: "3"; enabled: root.allow-2; clicked => { root.press("3"); } } FuncBtn { min-h: 34px; label: "%"; clicked => { root.press("%"); } } } Row { DigitBtn { min-h: 34px; label: "±"; clicked => { root.press("neg"); } } DigitBtn { min-h: 34px; label: "0"; clicked => { root.press("0"); } } FuncBtn { min-h: 34px; label: root.show-bits ? "Bits●" : "Bits"; clicked => { root.press("bits"); } } EqBtn { min-h: 34px; clicked => { root.press("="); } } } } } forward-focus: key-handler; key-handler := FocusScope { key-pressed(event) => { if (root.mode == 3) { return reject; } if (event.text == Key.Return) { root.press("="); return accept; } if (event.text == Key.Backspace) { root.press("BS"); return accept; } if (event.text == Key.Escape) { root.press(root.mode == 0 ? "C" : "clear"); return accept; } if (event.text == Key.Delete) { root.press("CE"); return accept; } if (event.text != "") { root.press(event.text); return accept; } reject } } }