feat: add swap action and HP48-style stack editing

This commit is contained in:
2026-05-15 20:19:39 +02:00
parent f679b0d952
commit 40e1043a03
2 changed files with 21 additions and 9 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# State # State
- Core engine: `src/rpn-calculator.js` - Core engine: `src/rpn-calculator.js`
- Active demo: `samples/calc-02/` responsive HP48GX layout driven by portrait/landscape text mockups; display-adjacent button row stays in 4 columns - Active demo: `samples/calc-02/` responsive HP48GX layout with HP48-like X-line editing; display-adjacent button row stays in 4 columns
- Mode button shows the current angle mode only; selecting a mode uses a popup menu - Mode button shows the current angle mode only; selecting a mode uses a popup menu
- Public API: `push`, `pop`, `clear`, `swap`, `remove`, `edit`, `isValidIndex`, `input`, `command`, `getOperationsByCategory`, `getConstants` - Public API: `push`, `pop`, `clear`, `swap`, `remove`, `edit`, `isValidIndex`, `input`, `command`, `getOperationsByCategory`, `getConstants`
- Config: `maxSize`, `base`, `angleMode`, `enabledCommands` - Config: `maxSize`, `base`, `angleMode`, `enabledCommands`
+20 -8
View File
@@ -86,8 +86,7 @@ function normalizeStack() {
} }
function getStackLine(indexFromTop) { function getStackLine(indexFromTop) {
const index = calc.stack.length - 1 - indexFromTop; return indexFromTop >= 0 && indexFromTop < calc.stack.length ? calc.stack[indexFromTop] : '';
return index >= 0 ? calc.stack[index] : '';
} }
function render() { function render() {
@@ -95,10 +94,11 @@ function render() {
const isPortrait = window.matchMedia('(orientation: portrait)').matches || window.innerWidth <= 860; const isPortrait = window.matchMedia('(orientation: portrait)').matches || window.innerWidth <= 860;
calculatorEl?.classList.toggle('portrait', isPortrait); calculatorEl?.classList.toggle('portrait', isPortrait);
calculatorEl?.classList.toggle('landscape', !isPortrait); calculatorEl?.classList.toggle('landscape', !isPortrait);
stackEls.T.textContent = calc.formatNumber(getStackLine(3)) || ''; const editingValue = calc.isEditing ? calc.inputValue : '';
stackEls.Z.textContent = calc.formatNumber(getStackLine(2)) || ''; stackEls.X.textContent = calc.isEditing ? editingValue : (calc.formatNumber(getStackLine(0)) || '');
stackEls.Y.textContent = calc.formatNumber(getStackLine(1)) || ''; stackEls.Y.textContent = calc.isEditing ? (calc.formatNumber(getStackLine(0)) || '') : (calc.formatNumber(getStackLine(1)) || '');
stackEls.X.textContent = calc.formatNumber(getStackLine(0)) || (calc.isEditing ? calc.inputValue : ''); stackEls.Z.textContent = calc.isEditing ? (calc.formatNumber(getStackLine(1)) || '') : (calc.formatNumber(getStackLine(2)) || '');
stackEls.T.textContent = calc.isEditing ? (calc.formatNumber(getStackLine(2)) || '') : (calc.formatNumber(getStackLine(3)) || '');
modeButton.textContent = calc.angleMode; modeButton.textContent = calc.angleMode;
} }
@@ -129,7 +129,11 @@ function inputToX(value) {
function execute(name) { function execute(name) {
try { try {
if (name === 'enter') { if (name === 'enter') {
pushEditingValueIfNeeded(); if (calc.isEditing) {
pushEditingValueIfNeeded();
} else if (calc.isValidIndex(0)) {
calc.push(calc.stack[0]);
}
} else if (name === 'clear') { } else if (name === 'clear') {
calc.clear(); calc.clear();
calc.inputValue = ''; calc.inputValue = '';
@@ -143,6 +147,11 @@ function execute(name) {
} else { } else {
calc.remove(0); calc.remove(0);
} }
} else if (name === 'swap') {
pushEditingValueIfNeeded();
if (calc.isValidIndex(1)) {
calc.swap(0, 1);
}
} else if (name === 'neg') { } else if (name === 'neg') {
if (calc.isEditing) { if (calc.isEditing) {
calc.inputValue = calc.inputValue.startsWith('-') ? calc.inputValue.slice(1) : `-${calc.inputValue}`; calc.inputValue = calc.inputValue.startsWith('-') ? calc.inputValue.slice(1) : `-${calc.inputValue}`;
@@ -349,7 +358,10 @@ leftButton.addEventListener('click', () => {});
downButton.addEventListener('click', () => {}); downButton.addEventListener('click', () => {});
rightButton.addEventListener('click', () => {}); rightButton.addEventListener('click', () => {
execute('swap');
});
window.addEventListener('keydown', handleKeyboard); window.addEventListener('keydown', handleKeyboard);
window.addEventListener('load', focusInput); window.addEventListener('load', focusInput);