feat(mobile): Figma-like hide-UI toggle — Cmd/Ctrl+\ hotkey + floating button, snapshot-exact chrome restore
Chrome visibility is now a runtime toggle on any device instead of being device-wired: mobile defaults to canvas-only, desktop to full UI, and the floating top-right button (or Figma's Cmd/Ctrl+\ chord — free in KiCad, only bare \ is bound) flips between them live. - chrome-visibility.ts: module-global store (default isMobileMode(), session-only) + pure hotkey matcher (rejects AltGr backslash + repeats) - WasmTool: capture-phase hotkey (stopped before the wx layer), floating toggle pill (matches the comment FAB design), useLayoutEffect apply with sync first call + retry; overlays follow the toggle, capability-gated on the kicad_editor bundle's kicadSetChrome export - boot.ts mobile opt now installs touch gestures only - kicadSetChrome: frame-keyed hide-time snapshot so restore re-shows ONLY what hide took away (blanket Show(true) surfaced KiCad's default-hidden Search/Properties/Net-Inspector panes); toolbars-only fallback otherwise - tests: chrome-toggle.spec.ts (desktop hide/restore + geometric restore-exactness ±3px), mobile toggle round-trip, 12 new unit tests, test:web:mobile npm script Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
dc7c60f723
commit
d44ba9bdfb
9 changed files with 558 additions and 66 deletions
|
|
@ -24,6 +24,7 @@
|
|||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/bind.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/app.h>
|
||||
|
|
@ -124,13 +125,34 @@ static bool kicadOpenFile( std::string path )
|
|||
}
|
||||
|
||||
|
||||
// Canvas-only mobile chrome toggle (features/mobile): hide/show every AUI pane
|
||||
// Canvas-only chrome toggle (features/mobile): hide/show every AUI pane
|
||||
// except the central draw canvas, plus the menubar and status bar, so the GAL
|
||||
// canvas fills the frame. Generic wxFrame/wxAui surface only (keeps this TU
|
||||
// header-light and serves both editor frames). Hidden bars release their space
|
||||
// because the wasm port's frame client-area math skips !IsShown() bars (native
|
||||
// parity, see wxwidgets/src/wasm/frame.cpp). Returns false until the editor
|
||||
// frame exists — main() builds it after runtime init — so JS polls this.
|
||||
|
||||
// Hide-time visibility snapshot. KiCad keeps several panes hidden by default
|
||||
// (Search, Properties, Net Inspector, …), so a blanket Show(true) on restore
|
||||
// would surface panes the user never had open — restore only what the hide
|
||||
// actually took away. Keyed to the frame so a snapshot never leaks onto a
|
||||
// different frame's wxAuiManager.
|
||||
static struct
|
||||
{
|
||||
wxFrame* frame = nullptr;
|
||||
bool valid = false;
|
||||
bool menuShown = false;
|
||||
bool statusShown = false;
|
||||
std::vector<wxString> paneNames;
|
||||
} s_chromeSnap;
|
||||
|
||||
static bool chromeSkipsPane( const wxAuiPaneInfo& aPane )
|
||||
{
|
||||
// keep the central editor canvas (named "DrawFrame" in both editors)
|
||||
return aPane.dock_direction == wxAUI_DOCK_CENTER || aPane.name == wxT( "DrawFrame" );
|
||||
}
|
||||
|
||||
static bool kicadSetChrome( bool aShow )
|
||||
{
|
||||
wxFrame* frame =
|
||||
|
|
@ -139,15 +161,50 @@ static bool kicadSetChrome( bool aShow )
|
|||
if( !frame )
|
||||
return false;
|
||||
|
||||
if( wxMenuBar* menuBar = frame->GetMenuBar() )
|
||||
menuBar->Show( aShow );
|
||||
wxMenuBar* menuBar = frame->GetMenuBar();
|
||||
wxStatusBar* statusBar = frame->GetStatusBar();
|
||||
wxAuiManager* mgr = wxAuiManager::GetManager( frame );
|
||||
|
||||
if( !aShow )
|
||||
{
|
||||
// A repeated hide keeps the original snapshot (idempotent).
|
||||
if( !s_chromeSnap.valid || s_chromeSnap.frame != frame )
|
||||
{
|
||||
s_chromeSnap.frame = frame;
|
||||
s_chromeSnap.menuShown = menuBar && menuBar->IsShown();
|
||||
s_chromeSnap.statusShown = statusBar && statusBar->IsShown();
|
||||
s_chromeSnap.paneNames.clear();
|
||||
|
||||
if( mgr )
|
||||
{
|
||||
wxAuiPaneInfoArray& panes = mgr->GetAllPanes();
|
||||
|
||||
for( size_t i = 0; i < panes.GetCount(); ++i )
|
||||
{
|
||||
wxAuiPaneInfo& pane = panes.Item( i );
|
||||
|
||||
if( !chromeSkipsPane( pane ) && pane.IsShown() )
|
||||
s_chromeSnap.paneNames.push_back( pane.name );
|
||||
}
|
||||
}
|
||||
|
||||
s_chromeSnap.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// A show with no snapshot (or one taken on a different frame) falls back
|
||||
// to revealing the standard chrome instead of obeying stale state.
|
||||
const bool haveSnap = s_chromeSnap.valid && s_chromeSnap.frame == frame;
|
||||
|
||||
if( menuBar )
|
||||
menuBar->Show( aShow && ( haveSnap ? s_chromeSnap.menuShown : true ) );
|
||||
|
||||
// Kept alive rather than detached: KiCad SetStatusText()s on every cursor
|
||||
// move, and wxFrameBase wxCHECKs a null status bar.
|
||||
if( wxStatusBar* statusBar = frame->GetStatusBar() )
|
||||
statusBar->Show( aShow );
|
||||
if( statusBar )
|
||||
statusBar->Show( aShow && ( haveSnap ? s_chromeSnap.statusShown : true ) );
|
||||
|
||||
if( wxAuiManager* mgr = wxAuiManager::GetManager( frame ) )
|
||||
if( mgr )
|
||||
{
|
||||
wxAuiPaneInfoArray& panes = mgr->GetAllPanes();
|
||||
|
||||
|
|
@ -155,16 +212,37 @@ static bool kicadSetChrome( bool aShow )
|
|||
{
|
||||
wxAuiPaneInfo& pane = panes.Item( i );
|
||||
|
||||
// keep the central editor canvas (named "DrawFrame" in both editors)
|
||||
if( pane.dock_direction == wxAUI_DOCK_CENTER || pane.name == wxT( "DrawFrame" ) )
|
||||
if( chromeSkipsPane( pane ) )
|
||||
continue;
|
||||
|
||||
pane.Show( aShow );
|
||||
if( !aShow )
|
||||
{
|
||||
pane.Show( false );
|
||||
}
|
||||
else if( haveSnap )
|
||||
{
|
||||
if( std::find( s_chromeSnap.paneNames.begin(), s_chromeSnap.paneNames.end(),
|
||||
pane.name )
|
||||
!= s_chromeSnap.paneNames.end() )
|
||||
{
|
||||
pane.Show( true );
|
||||
}
|
||||
}
|
||||
else if( pane.IsToolbar() )
|
||||
{
|
||||
// Show with no (or a stale, other-frame) snapshot: reveal the
|
||||
// toolbars only — blanket-showing plain panels would surface
|
||||
// the default-hidden ones.
|
||||
pane.Show( true );
|
||||
}
|
||||
}
|
||||
|
||||
mgr->Update();
|
||||
}
|
||||
|
||||
if( aShow )
|
||||
s_chromeSnap.valid = false;
|
||||
|
||||
frame->SendSizeEvent();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue