|
@@ -210,8 +210,23 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------ 按键
|
|
// ------------------------------------------------------------------ 按键
|
|
|
|
|
|
|
|
- void _press(_Key k) {
|
|
|
|
|
|
|
+ /// ⇧ 层是否开着。按一次只生效一次(跟计算器上的 shift 一样)。
|
|
|
|
|
+ bool _shift = false;
|
|
|
|
|
+
|
|
|
|
|
+ void _press(_Key raw) {
|
|
|
|
|
+ // shift 键本身:切一下层,不往表达式里写东西
|
|
|
|
|
+ if (raw.act == _Act.shift) {
|
|
|
|
|
+ setState(() => _shift = !_shift);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 开着 shift 且这个键有 shift 层:按 shift 层那个动作,然后复位
|
|
|
|
|
+ final k = (_shift && raw.shifted != null) ? raw.shifted! : raw;
|
|
|
|
|
+ if (_shift) setState(() => _shift = false);
|
|
|
|
|
+
|
|
|
switch (k.act) {
|
|
switch (k.act) {
|
|
|
|
|
+ case _Act.shift:
|
|
|
|
|
+ return; // 上面已经处理过,这里只是让 switch 穷尽
|
|
|
|
|
+
|
|
|
case _Act.char:
|
|
case _Act.char:
|
|
|
if (k.mergeDigit) {
|
|
if (k.mergeDigit) {
|
|
|
// 数字键并入左边那个数字字面量,`42` 才是一个数而不是两个节点
|
|
// 数字键并入左边那个数字字面量,`42` 才是一个数而不是两个节点
|
|
@@ -445,20 +460,30 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
final rows = <List<_Key>>[
|
|
final rows = <List<_Key>>[
|
|
|
// 1 大运算符
|
|
// 1 大运算符
|
|
|
[
|
|
[
|
|
|
- _Key('∫', _Act.bigOp, payload: 'Integrate', prefill: ['x']),
|
|
|
|
|
|
|
+ _Key('∫', _Act.bigOp, payload: 'Integrate', prefill: ['x'],
|
|
|
|
|
+ shifted: _Key('∏', _Act.bigOp,
|
|
|
|
|
+ payload: 'Product', prefill: ['n', '1', 'Infinity'])),
|
|
|
_Key('Σ', _Act.bigOp,
|
|
_Key('Σ', _Act.bigOp,
|
|
|
payload: 'Sum', prefill: ['n', '1', 'Infinity']),
|
|
payload: 'Sum', prefill: ['n', '1', 'Infinity']),
|
|
|
_Key('d/dx', _Act.fnPrefixed, payload: 'D', prefill: ['', 'x']),
|
|
_Key('d/dx', _Act.fnPrefixed, payload: 'D', prefill: ['', 'x']),
|
|
|
_Key('lim', _Act.bigOp, payload: 'Limit', prefill: ['x', '0']),
|
|
_Key('lim', _Act.bigOp, payload: 'Limit', prefill: ['x', '0']),
|
|
|
- _Key('solve', _Act.fnPrefixed, payload: 'Solve', prefill: ['', 'x']),
|
|
|
|
|
|
|
+ _Key('solve', _Act.fnPrefixed, payload: 'Solve',
|
|
|
|
|
+ prefill: ['', 'x'],
|
|
|
|
|
+ shifted: _Key('nsolve', _Act.fnPrefixed, payload: 'NSolve',
|
|
|
|
|
+ prefill: ['', 'x'])),
|
|
|
],
|
|
],
|
|
|
// 2 常用函数
|
|
// 2 常用函数
|
|
|
[
|
|
[
|
|
|
- _Key('sin', _Act.fn, payload: 'Sin'),
|
|
|
|
|
- _Key('cos', _Act.fn, payload: 'Cos'),
|
|
|
|
|
- _Key('tan', _Act.fn, payload: 'Tan'),
|
|
|
|
|
- _Key('ln', _Act.fn, payload: 'Log'),
|
|
|
|
|
- _Key('√', _Act.sqrt),
|
|
|
|
|
|
|
+ _Key('sin', _Act.fn, payload: 'Sin',
|
|
|
|
|
+ shifted: _Key('asin', _Act.fn, payload: 'ArcSin')),
|
|
|
|
|
+ _Key('cos', _Act.fn, payload: 'Cos',
|
|
|
|
|
+ shifted: _Key('acos', _Act.fn, payload: 'ArcCos')),
|
|
|
|
|
+ _Key('tan', _Act.fn, payload: 'Tan',
|
|
|
|
|
+ shifted: _Key('atan', _Act.fn, payload: 'ArcTan')),
|
|
|
|
|
+ _Key('ln', _Act.fn, payload: 'Log',
|
|
|
|
|
+ shifted: _Key('lg', _Act.fn, payload: 'Log10')),
|
|
|
|
|
+ _Key('√', _Act.sqrt,
|
|
|
|
|
+ shifted: _Key('|x|', _Act.fn, payload: 'Abs')),
|
|
|
],
|
|
],
|
|
|
// 3 变量
|
|
// 3 变量
|
|
|
[
|
|
[
|
|
@@ -484,8 +509,12 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
_Key('7', _Act.char, payload: '7', mergeDigit: true),
|
|
_Key('7', _Act.char, payload: '7', mergeDigit: true),
|
|
|
_Key('8', _Act.char, payload: '8', mergeDigit: true),
|
|
_Key('8', _Act.char, payload: '8', mergeDigit: true),
|
|
|
_Key('9', _Act.char, payload: '9', mergeDigit: true),
|
|
_Key('9', _Act.char, payload: '9', mergeDigit: true),
|
|
|
- _Key('(', _Act.group),
|
|
|
|
|
- _Key('!', _Act.postfix),
|
|
|
|
|
|
|
+ _Key('(', _Act.group,
|
|
|
|
|
+ shifted: _Key('P', _Act.fnPrefixed,
|
|
|
|
|
+ payload: 'FactorialPower', prefill: ['', ''])),
|
|
|
|
|
+ _Key('!', _Act.postfix,
|
|
|
|
|
+ shifted: _Key('C', _Act.fnPrefixed,
|
|
|
|
|
+ payload: 'Binomial', prefill: ['', ''])),
|
|
|
],
|
|
],
|
|
|
[
|
|
[
|
|
|
_Key('4', _Act.char, payload: '4', mergeDigit: true),
|
|
_Key('4', _Act.char, payload: '4', mergeDigit: true),
|
|
@@ -511,6 +540,8 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
_Key('e', _Act.char, payload: 'E', tint: true, display: 'e'),
|
|
_Key('e', _Act.char, payload: 'E', tint: true, display: 'e'),
|
|
|
],
|
|
],
|
|
|
[
|
|
[
|
|
|
|
|
+ // ⇧ 开着的时候这个键是深色的 —— 一眼能看出"现在是 shift 层"
|
|
|
|
|
+ _Key('⇧', _Act.shift, tint: true, primary: _shift),
|
|
|
_Key('⌫', _Act.back, tint: true),
|
|
_Key('⌫', _Act.back, tint: true),
|
|
|
_Key('CLR', _Act.clear, tint: true),
|
|
_Key('CLR', _Act.clear, tint: true),
|
|
|
// 虚数单位。送进 Symja 的是 I,编辑框里显示小写 i
|
|
// 虚数单位。送进 Symja 的是 I,编辑框里显示小写 i
|
|
@@ -549,7 +580,10 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Widget _keyButton(_Key k) {
|
|
|
|
|
|
|
+ Widget _keyButton(_Key raw) {
|
|
|
|
|
+ // shift 开着就整体换成 shift 层:有 shift 层的键显示备用功能,
|
|
|
|
|
+ // 没有的保持原样。这样"按一下看看有什么"就能发现 shift 层。
|
|
|
|
|
+ final k = (_shift && raw.shifted != null) ? raw.shifted! : raw;
|
|
|
final scheme = Theme.of(context).colorScheme;
|
|
final scheme = Theme.of(context).colorScheme;
|
|
|
// E-Ink 下按键的底色是白的(配色压成了白底黑字),跟背景一个颜色就看不见了,
|
|
// E-Ink 下按键的底色是白的(配色压成了白底黑字),跟背景一个颜色就看不见了,
|
|
|
// 所以改成**描边**区分:功能键/提交键一圈黑,数字键一圈浅灰。
|
|
// 所以改成**描边**区分:功能键/提交键一圈黑,数字键一圈浅灰。
|
|
@@ -604,6 +638,7 @@ class _CalculatorPageState extends State<CalculatorPage> {
|
|
|
|
|
|
|
|
enum _Act {
|
|
enum _Act {
|
|
|
char,
|
|
char,
|
|
|
|
|
+ shift,
|
|
|
fn,
|
|
fn,
|
|
|
fnPrefixed,
|
|
fnPrefixed,
|
|
|
bigOp,
|
|
bigOp,
|
|
@@ -642,6 +677,12 @@ class _Key {
|
|
|
final bool tint;
|
|
final bool tint;
|
|
|
final bool primary;
|
|
final bool primary;
|
|
|
|
|
|
|
|
|
|
+ /// 按了 ⇧ 之后这个键变成什么。null = 这个键没有 shift 层。
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// 用"整个备用键"而不是几个零散字段:shift 前后的动作类型本来就可能不同
|
|
|
|
|
+ /// (`√` 是 sqrt、shift 之后是普通函数 `Abs`),嵌套一个 _Key 最省事。
|
|
|
|
|
+ final _Key? shifted;
|
|
|
|
|
+
|
|
|
const _Key(
|
|
const _Key(
|
|
|
this.label,
|
|
this.label,
|
|
|
this.act, {
|
|
this.act, {
|
|
@@ -652,6 +693,7 @@ class _Key {
|
|
|
this.mathVar = false,
|
|
this.mathVar = false,
|
|
|
this.tint = false,
|
|
this.tint = false,
|
|
|
this.primary = false,
|
|
this.primary = false,
|
|
|
|
|
+ this.shifted,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|