Skip to content
This repository was archived by the owner on Nov 7, 2026. It is now read-only.

Commit bbcc65d

Browse files
Web 0.13.1: Trennlinie Struktogramm/Programmieren immer ziehbar (#199)
Bei vier offenen Spalten (Lektionen, Struktogramm, Programmieren, mBot2 live) saß das Struktogramm an seiner Mindestbreite und die Trennlinie ließ sich kaum ziehen. Beim Ziehen geben jetzt erst die beiden Nachbarn, dann mBot2 live, dann Lernbereich und Dateien Breite ab. Gilt in beiden Reihenfolgen nach ⇄. Claude-Session: https://claude.ai/code/session_01Ugz28VccwbG33z7QF7w58X Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3bd59a5 commit bbcc65d

9 files changed

Lines changed: 1295 additions & 1244 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is loosely inspired by Keep a Changelog.
88

99
### Added
1010

11+
- **Web 0.13.1, divider between Struktogramm and Programmieren always draggable:** with four open columns (lessons, Struktogramm, Programmieren, „mBot2 live“) the diagram sat at its minimum width and the divider barely moved. Dragging it now first uses the space of the two columns next to it, then takes width from „mBot2 live“, then from the lessons and files columns (down to their minimum widths). Works in both orders after ⇄; all widths are remembered.
1112
- **Web 0.13.0, VisuBot simulation in the „mBot2 live“ window:** in the VisuBot world „Simulation starten“ no longer shows a second 3D world in the simulation column; the mBot2 of the simulation drives in the „mBot2 live“ window instead (title „🤖 Simulation“, world buttons and distance/line values there, its own ▶ rests until the simulation ends). The window opens by itself for the simulation and closes again afterwards if it was closed before; if it is closed during the simulation, the 3D world goes back to the simulation column. Controls, variables, console, sensor sliders and the real mBot2 stay in the simulation column.
1213
- **Web 0.12.12, misspelled data types:** a misspelled basic type at the start of a declaration (`booelan`, `Int`, `string`, `dobule`) is marked red in Programmieren with „Meintest du boolean?“ and ▶ does not start (like javac); the VisuObject debugger reports it with file and line. Valid types (`Boolean`, `Integer`) and own classes stay untouched. The simulation now runs declarations without a start value (`boolean fertig;`, `int a, b;`) and prints conditions like `System.out.println(b == true)` or `x > 3` as true/false (#195).
1314
- **Web 0.12.11, Scanner line suggested:** typing `Scanner` in Programmieren and VisuObject suggests the whole line `Scanner scanner = new Scanner(System.in);` (Tab/Enter, variable name selected to change it); if `import java.util.Scanner;` (or `java.util.*`) is missing, it is added at the top.

‎web/package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "visustruct-web",
33
"private": true,
4-
"version": "0.13.0",
4+
"version": "0.13.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

‎web/src/ui/app.ts‎

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ export class App {
398398
this.learnResizer(),
399399
this.editorRail(),
400400
root,
401-
this.panelResizer(root, 'editor-resizer', editorWidthKey, t('web_editor_resize'), () => (this.codeMain ? -1 : 1)),
401+
this.panelResizer(root, 'editor-resizer', editorWidthKey, t('web_editor_resize'), () => (this.codeMain ? -1 : 1), () => this.live.element),
402402
this.liveResizer(),
403403
this.live.element,
404404
this.liveRail(),
@@ -1730,11 +1730,32 @@ export class App {
17301730

17311731
/** Wie beim Lernbereich, nur am anderen Rand: Ziehen nach links macht den Code breiter. */
17321732
private liveResizer(): HTMLElement {
1733-
return this.panelResizer(this.live.element, 'live-resizer', liveWidthKey, t('web_live_resize'), -1)
1733+
return this.panelResizer(this.live.element, 'live-resizer', liveWidthKey, t('web_live_resize'), -1, () => this.root)
1734+
}
1735+
1736+
/**
1737+
* Struktogramm und Programmieren teilen sich den Platz, den die anderen Spalten übrig lassen. Ist der zu knapp,
1738+
* geben beim Ziehen an der Linie dazwischen erst „mBot2 live“, dann Lernbereich und Dateien Breite ab (bis zu ihrer
1739+
* Mindestbreite), sonst ließe sich die Aufteilung bei vier offenen Spalten kaum verändern.
1740+
*/
1741+
private yieldingPanels(): { panel: HTMLElement; key: string }[] {
1742+
return [
1743+
{ panel: this.preview.element, key: previewWidthKey },
1744+
{ panel: this.learn.element, key: learnWidthKey },
1745+
{ panel: this.files.element, key: filesWidthKey },
1746+
].filter(({ panel }) => panel.offsetParent !== null && panel.parentElement === this.live.element.parentElement)
17341747
}
17351748

17361749
/** `side`: 1 = Bereich liegt am Anfang der Zeile (links), -1 = am Ende (rechts); als Funktion, wenn ⇄ die Seite wechselt. */
1737-
private panelResizer(panel: HTMLElement, className: string, widthKey: string, title: string, side: 1 | -1 | (() => 1 | -1)): HTMLElement {
1750+
/** `partner`: die breitenvariable Spalte auf der anderen Seite der Linie; dann geben beim Ziehen auch weitere Spalten Platz ab. */
1751+
private panelResizer(
1752+
panel: HTMLElement,
1753+
className: string,
1754+
widthKey: string,
1755+
title: string,
1756+
side: 1 | -1 | (() => 1 | -1),
1757+
partner?: () => HTMLElement,
1758+
): HTMLElement {
17381759
const bar = h('div', { class: className, role: 'separator', 'aria-orientation': 'vertical', tabindex: '0', title })
17391760
// Höchstens so breit, dass die Spalte daneben noch 240 px behält; feste Breiten anderer Bereiche zählen mit.
17401761
const clamp = (width: number) => {
@@ -1765,13 +1786,15 @@ export class App {
17651786
const startWidth = panel.getBoundingClientRect().width
17661787
const s = sign()
17671788
this.shell.classList.add('resizing')
1768-
const move = (ev: PointerEvent) => apply(startWidth + s * (ev.clientX - startX), false)
1789+
const resize = partner ? this.pushResize(panel, widthKey, partner(), startWidth) : undefined
1790+
const drag = (ev: PointerEvent, remember: boolean) => (resize ?? apply)(startWidth + s * (ev.clientX - startX), remember)
1791+
const move = (ev: PointerEvent) => drag(ev, false)
17691792
const up = (ev: PointerEvent) => {
17701793
bar.removeEventListener('pointermove', move)
17711794
bar.removeEventListener('pointerup', up)
17721795
bar.removeEventListener('pointercancel', up)
17731796
this.shell.classList.remove('resizing')
1774-
apply(startWidth + s * (ev.clientX - startX), true)
1797+
drag(ev, true)
17751798
}
17761799
bar.addEventListener('pointermove', move)
17771800
bar.addEventListener('pointerup', up)
@@ -1787,6 +1810,33 @@ export class App {
17871810
return bar
17881811
}
17891812

1813+
/**
1814+
* Ziehen an der Linie zwischen Struktogramm und Programmieren: `panel` hat eine feste Breite, `partner` füllt den Rest.
1815+
* Reicht der Platz des Partners (oder von `panel`) nicht, schrumpfen die anderen Spalten; ihre Breite wird gemerkt.
1816+
*/
1817+
private pushResize(panel: HTMLElement, widthKey: string, partner: HTMLElement, startWidth: number): (width: number, remember: boolean) => void {
1818+
const minOf = (p: HTMLElement, fallback: number) => Math.max(parseFloat(getComputedStyle(p).minWidth) || 0, fallback)
1819+
const panelMin = minOf(panel, 200)
1820+
const slack = Math.max(0, partner.getBoundingClientRect().width - minOf(partner, 240))
1821+
const yielders = this.yieldingPanels().map((y) => ({ ...y, start: y.panel.getBoundingClientRect().width, min: minOf(y.panel, 200), changed: false }))
1822+
const spare = yielders.reduce((sum, y) => sum + Math.max(0, y.start - y.min), 0)
1823+
return (wanted, remember) => {
1824+
const width = Math.round(Math.max(panelMin, Math.min(wanted, startWidth + slack + spare)))
1825+
// Was weder `panel` noch der Partner aufnehmen kann, geben die anderen Spalten ab, die nächste zuerst.
1826+
let need = Math.max(0, width - startWidth - slack, panelMin - wanted)
1827+
for (const y of yielders) {
1828+
const give = Math.min(need, Math.max(0, y.start - y.min))
1829+
need -= give
1830+
y.changed ||= give > 0
1831+
if (!y.changed) continue
1832+
y.panel.style.width = `${Math.round(y.start - give)}px`
1833+
if (remember) storeValue(y.key, String(Math.round(y.start - give)))
1834+
}
1835+
panel.style.width = `${width}px`
1836+
if (remember) storeValue(widthKey, String(width))
1837+
}
1838+
}
1839+
17901840
private findSubprogram(name: string, current: Tab | undefined = this.tab): VSDocument | undefined {
17911841
const key = subprogramKey(name)
17921842
if (key === '') return undefined
Lines changed: 1229 additions & 1229 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)