sclass CollapsibleLeftPanel > MetaWithChangeListeners is Swingable { settableWithVar volatile S sidePanelName; JComponent sideComponent, mainComponent; JSplitPane splitPane; settableWithVar volatile bool expanded; SingleComponentPanel scp = singleComponentPanel(); *(bool *expanded, S *sidePanelName, JComponent *sideComponent, JComponent *mainComponent) { } void expand { if (scaffolding()) print("CollapsibleLeftPanel.expand"); setExpanded(true); } void collapse { setExpanded(false); } scaffolded void updateScp() swing { if (expanded) { splitPane().setRightComponent(jMinWidth0(mainComponent)); scp.set(splitPane()); } else { splitPane().setRightComponent(jMinWidth0(jpanel())); scp.set(westAndCenterWithMargin( sidePanelMargins(vstack(expandButton())), mainComponent)); } } JComponent expandButton() { ret jClickableImage_instantToolTip(#1103075, "Expand " + sidePanelName, r expand); } JComponent collapseButton() { ret jClickableImage_instantToolTip(#1103076, "Collapse " + sidePanelName, r collapse); } JComponent wrappedSideComponent() { ret sidePanelMargins(northAndCenterWithMargin( westAndCenterWithMargin(collapseButton(), liveValueLabel(varSidePanelName())), sideComponent )); } JSplitPane splitPane() { if (scaffolding()) print("splitPane " + splitPane); if (splitPane == null) { splitPane = jhsplit_minZero(0.25, wrappedSideComponent(), null); varExpanded().onChangeAndNow(r updateScp); } ret splitPane; } swappable JComponent sidePanelMargins(JComponent c) { ret c; } visualize { splitPane(); ret scp; } }