Files
RCalc/ui/app.slint
T
2026-08-01 18:05:10 +03:00

1170 lines
40 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export struct BitInfo {
value: bool,
index: int,
}
component BitCell inherits Rectangle {
callback toggled();
in property <bool> 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 <string> 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 <string> label;
in property <bool> enabled: true;
in property <length> 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 <string> label;
in property <bool> enabled: true;
in property <length> 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 <length> 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 <string> label;
in property <bool> 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 <string> label;
in property <string> value;
in property <bool> 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 <string> label;
in property <string> value;
in property <bool> 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 <string> label;
in property <bool> 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 {
in-out property <string> app-title: "Rcalc";
title: root.app-title;
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 <int> mode: 0;
in property <string> display-text: "0";
in property <string> expression-text: "";
in property <bool> has-memory: false;
// 0 = classic standard, 1 = formula
in property <int> std-panel: 0;
in property <string> hex-text: "0";
in property <string> dec-text: "0";
in property <string> oct-text: "0";
in property <string> bin-text: "0";
// 0=hex 1=dec 2=oct 3=bin
in property <int> active-base: 1;
in property <string> word-size-label: "QWORD";
in property <bool> show-bits: true;
in property <int> 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 <int> conv-panel: 0;
in property <int> conv-endian: 0; // 0=AB CD 1=CD AB 2=BA DC 3=DC BA
in property <int> conv-active: 0; // 0=float 1=word0 2=word1
in property <string> conv-float: "0";
in property <string> conv-word0: "0000";
in property <string> conv-word1: "0000";
in property <string> conv-bytes: "00 00 00 00";
in property <string> conv-ieee: "0x00000000";
in property <string> conv-error: "";
in property <int> ratio-width: 1; // 0=byte 1=word
in property <string> ratio-precision: "1e-6";
in property <string> ratio-num: "1";
in property <string> ratio-den: "1";
in property <string> ratio-frac: "1 / 1";
in property <string> ratio-approx: "1";
in property <string> ratio-error: "exact";
in property <string> ascii-char: "A";
in property <string> ascii-hex: "41";
in property <string> ascii-dec: "65";
in property <string> ascii-name: "'A'";
// CRC tab
in-out property <string> crc-input: "01 03 00 00 00 0A";
in property <string> crc-parsed: "";
in property <string> crc-count: "0";
in property <string> crc-rtu-bytes: "—";
in property <string> crc-rtu-word: "—";
in property <string> crc-rtu-frame: "—";
in property <string> crc-ascii-lrc: "—";
in property <string> crc-ascii-frame: "—";
in property <string> crc-error: "";
callback key-pressed(string);
callback crc-edited(string);
function press(id: string) {
root.key-pressed(id);
}
property <bool> hex-digits: root.mode == 1 && root.active-base == 0;
property <bool> allow-2: root.mode == 0 || root.active-base <= 2;
property <bool> allow-8: root.mode == 0 || root.active-base <= 1;
property <bool> 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: 30px;
ModeTab {
label: "Ordinary";
active: root.std-panel == 0;
clicked => { root.press("panel:std"); }
}
ModeTab {
label: "Formula";
active: root.std-panel == 1;
clicked => { root.press("panel:formula"); }
}
}
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 {
if root.std-panel == 0: FuncBtn { label: "%"; clicked => { root.press("%"); } }
if root.std-panel == 1: FuncBtn { label: "("; clicked => { root.press("("); } }
if root.std-panel == 0: FuncBtn { label: "CE"; clicked => { root.press("CE"); } }
if root.std-panel == 1: FuncBtn { label: ")"; clicked => { root.press(")"); } }
FuncBtn { label: "C"; clicked => { root.press("C"); } }
FuncBtn { label: "⌫"; clicked => { root.press("BS"); } }
}
Row {
FuncBtn { label: "1/x"; enabled: root.std-panel == 0; clicked => { root.press("1/x"); } }
FuncBtn { label: "x²"; enabled: root.std-panel == 0; clicked => { root.press("x2"); } }
FuncBtn { label: "√x"; enabled: root.std-panel == 0; 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
}
}
}