Skip to main content

AppShell

Struct AppShell 

Source
pub struct AppShell { /* private fields */ }
Expand description

All width/height fields are stored as multiples of line_height so they are portable across TUI (cells) and GUI (pixels) backends. compute_layout() resolves them: dimension_native = field * lh.

Implementations§

Source§

impl AppShell

Source

pub fn new(panels: Vec<PanelDefinition>, default_sidebar_width: f32) -> Self

Source

pub fn with_bottom_items(self, items: Vec<PanelDefinition>) -> Self

Source

pub fn with_panel_icon(self, id: WidgetId, icon: Icon) -> Self

Attach a distinct Nerd-Font glyph + ASCII fallback pair to one activity-bar row, overriding the single-string PanelDefinition::icon that panel was registered with.

id may name a top panel or a bottom item; unknown ids are stored but never consulted, so registration order relative to Self::with_bottom_items / [Self::register_panel] does not matter. Calling this twice for the same id keeps the last pair.

Which half actually paints is the backend’s decision, driven by its nerd_fonts_enabled flag — glyph when the icon font is available, fallback otherwise. Panels that never call this get glyph == fallback == PanelDefinition::icon.

let shell = AppShell::new(
    vec![PanelDefinition {
        id: WidgetId::new("panel:explorer"),
        icon: "E".to_string(),
        tooltip: "Explorer".to_string(),
        title: "EXPLORER".to_string(),
    }],
    20.0,
)
.with_panel_icon(WidgetId::new("panel:explorer"), Icon::new("\u{f07c}", "E"));
assert_eq!(shell.build_activity_bar().top_items[0].icon.glyph, "\u{f07c}");
Source

pub fn with_min_width(self, min: f32) -> Self

Source

pub fn with_max_width(self, max: f32) -> Self

Source

pub fn with_activity_bar_width(self, width: f32) -> Self

Source

pub fn with_activity_bar_width_px(self, width_px: f32) -> Self

Pin the activity bar to a fixed pixel width, overriding the line-height-derived width from Self::with_activity_bar_width.

The row height GTK/macOS paint each activity item at (ACTIVITY_ROW_PX = 48.0) is already a fixed pixel constant, not a line_height multiple — so a with_activity_bar_width(2.4)-style call only produces a square 48×48 bar at whatever line_height happens to make 2.4 * lh == 48.0. Passing 48.0 here keeps the bar square regardless of the app’s editor font size.

None (the default) leaves the existing line_height-derived width in place — this call is additive, not a replacement.

Source

pub fn with_active_accent(self, color: Color) -> Self

Colour painted on the active top panel’s row in the built ActivityBar (its active_accent field) — e.g. a theme’s accent colour, so the activity bar shows an active-panel indicator line. AppShell has no Theme in scope itself; a host app sources the colour from its own theme and passes it here before the first Self::render. Unset (the default) paints no accent, matching the pre-existing behaviour.

Source

pub fn with_selection_bg(self, color: Color) -> Self

Colour painted behind the keyboard-selected row in the built ActivityBar (its selection_bg field) when Self::activity_keyboard_focused. Unset (the default) leaves each backend’s own reversed/brightened fallback fill in charge.

Source

pub fn with_position(self, position: ShellPosition) -> Self

Source

pub fn with_title_bar(self, height_lh: f32) -> Self

Reserve a title-bar row at construction time. See Self::set_title_bar_visible to show/hide the row at runtime (e.g. a toggleable menu bar) without rebuilding the AppShell.

Source

pub fn with_title_bar_min_px(self, min_px: f32) -> Self

Pin a fixed-pixel floor under the title bar’s line-height-derived height, overriding it only when the multiple would otherwise resolve smaller — mirroring Self::with_activity_bar_width_px’s pattern, but as a floor rather than a hard override, since unlike the activity bar’s fixed-size icons, title-bar chrome (menu labels, inline window controls) is expected to keep scaling with the editor font above the floor.

None (the default) leaves title_bar_height_lh * line_height in sole charge, unchanged from before this method existed. Set this when a host needs the band to never shrink under some real platform constraint it can’t otherwise express in line-height units — e.g. staying clear of macOS’s native traffic-light cluster even after a user shrinks settings.font_size at runtime

Source

pub fn with_bottom_panel(self, height_lh: f32) -> Self

Source

pub fn with_bottom_panel_limits(self, min: f32, max: f32) -> Self

Source

pub fn with_bottom_bands(self, bands: Vec<BottomBand>) -> Self

Register the ordered list of independently-gated bottom bands. See BottomBand for the stacking order and how this interacts with Self::with_bottom_panel.

Replaces any previously-registered list. Vec::new() (the default) restores a single-drawer layout.

Source

pub fn with_command_line(self) -> Self

Source

pub fn with_status_bar(self) -> Self

Source

pub fn with_status_bar_height_px(self, height_px: f32) -> Self

Fix the status bar to height_px native units, overriding the line_height-derived height regardless of font size — VS Code’s status bar is a constant 22px. Call alongside Self::with_status_bar; has no visible effect unless that is also set.

Source

pub fn with_status_bar_under_main_column(self) -> Self

Opt into the activity bar and sidebar running the full height of the area below the title bar, with the status bar and command line carved from the main column only (main column’s x/width) rather than the full window width.

Off by default: the status bar and command line span the full window, and the activity bar/sidebar stop above them — unchanged from before this method existed. Turn this on when a host wants the activity bar’s bottom-pinned items to sit in the window’s bottom-left corner rather than above a full-width status bar.

Source

pub fn active_panel(&self) -> Option<&PanelDefinition>

The PanelDefinition that currently owns the sidebar: the active top panel, or a bottom item that was made the owner via Self::show_panel. This is the same definition Self::render titles the sidebar header from.

Source

pub fn active_panel_id(&self) -> Option<&WidgetId>

The id of Self::active_panel — a top panel’s id, or a bottom item’s id when that bottom item owns the sidebar.

Source

pub fn sidebar_visible(&self) -> bool

Source

pub fn sidebar_width(&self) -> f32

Source

pub fn position(&self) -> ShellPosition

Source

pub fn title_bar_visible(&self) -> bool

Whether the title-bar row is currently reserved. See Self::set_title_bar_visible for the runtime toggle and Self::with_title_bar for the construction-time builder.

Source

pub fn hovered_activity_idx(&self) -> Option<usize>

Source

pub fn activity_keyboard_focused(&self) -> bool

Returns true when the activity bar currently holds keyboard focus.

When true, build_activity_bar() sets is_keyboard_focused = true on the emitted ActivityBar, causing both the TUI and GTK backends to deliver key presses as UiEvent::ActivityBar(id, ActivityBarEvent::KeyPressed { … }) rather than raw UiEvent::KeyPressed. The consumer maps those key strings to the navigation methods below.

Source

pub fn set_activity_keyboard_focused(&mut self, focused: bool)

Focus or unfocus the activity bar. Pair with Self::activity_keyboard_focused and the navigation methods to implement keyboard nav in a ShellApp consumer.

Calling this does not reset the cursor — the cursor stays where it was so repeated focus/blur round-trips feel natural. To reset to the top item on focus, call set_activity_keyboard_focused(true) then activity_set_cursor(0).

Source

pub fn set_activity_cursor_visible(&mut self, visible: bool)

Show (or hide) the keyboard cursor highlight on the activity bar without enabling the key-event redirect that Self::set_activity_keyboard_focused triggers.

A ShellApp consumer that routes toolbar keys itself — through its own chord / key-action handlers inside ShellApp::handle, receiving plain UiEvent::KeyPressed events — calls this instead of set_activity_keyboard_focused(true) so the cursor paints but the TUI / GTK backends leave key events as KeyPressed rather than rewriting them to UiEvent::ActivityBar(…).

Source

pub fn set_active_accent(&mut self, color: Option<Color>)

Set (or clear, with None) the active-panel accent colour Self::build_activity_bar passes through as ActivityBar::active_accent. Runtime counterpart to Self::with_active_accent — call this after a theme switch instead of rebuilding the AppShell.

Source

pub fn set_selection_bg(&mut self, color: Option<Color>)

Set (or clear, with None) the keyboard-selection highlight colour Self::build_activity_bar passes through as ActivityBar::selection_bg. Runtime counterpart to Self::with_selection_bg.

Source

pub fn activity_select_next(&mut self)

Move the keyboard cursor to the next item in the logical sequence (top panels first, then bottom items). Saturates at the last item — does not wrap to the top.

Source

pub fn activity_select_prev(&mut self)

Move the keyboard cursor to the previous item. Saturates at index 0 — does not wrap to the bottom.

Source

pub fn activity_set_cursor(&mut self, idx: usize)

Set the keyboard cursor to an explicit index in the logical sequence. Out-of-range values are clamped to the valid range [0, total-1]. Has no effect when the panel + bottom-item lists are both empty.

Source

pub fn activity_selected_id(&self) -> Option<&WidgetId>

Returns the WidgetId of the item currently under the keyboard cursor, or None if there are no items at all.

The logical sequence is top panels (0..panels.len()) followed by bottom items (panels.len()..).

Source

pub fn activity_activate_selected(&mut self) -> Option<AppShellEvent>

Activate the item currently under the keyboard cursor and return the resulting AppShellEvent, or None if there are no items.

Equivalent to clicking the cursor item: top-panel items trigger the same toggle / switch logic as a mouse click, bottom items emit AppShellEvent::BottomItemClicked. Does not clear keyboard focus — the consumer decides whether to do that.

Source

pub fn show_panel(&mut self, panel_id: &WidgetId)

Make panel_id the sidebar’s owner and reveal the sidebar.

Accepts either a top panel’s id or a bottom item’s id (one registered via Self::with_bottom_items / Self::add_bottom_item). In the latter case the bottom item becomes the sidebar header’s title source (see Self::active_panel/Self::active_panel_id) until show_panel is called again with a different id. A bottom item’s own click (Self::handle_activity_click’s BottomItemClicked branch) never calls this itself, so an app opts in explicitly from its BottomItemClicked handler.

A no-op if panel_id matches neither a top panel nor a bottom item.

Source

pub fn hide_sidebar(&mut self)

Source

pub fn toggle_sidebar(&mut self)

Source

pub fn set_title_bar_visible(&mut self, visible: bool)

Runtime toggle for whether the title-bar row is reserved.

Unlike Self::with_title_bar — a construction-time builder that permanently commits to reserving the row for the lifetime of the AppShell — this can be flipped at any point after construction without rebuilding the shell. compute_layout re-derives every downstream bound (activity bar, sidebar, main content, bottom panel, …) from area and current state on every render/layout/handle call, so toggling this and calling any of those next is sufficient — no other field needs to change in lockstep, and no fixed offset is cached anywhere that would go stale.

A menu bar painted into the title-bar row that the user can show/hide at runtime requires this: always reserving the row costs a row even while the menu is hidden; never reserving it makes a shown menu overwrite the activity bar’s first row. Toggling this from the app’s own visibility state avoids both.

If Self::with_title_bar was never called, toggling visible for the first time reserves the default height (title_bar_height_lh, 1.5 line-heights). The configured height is otherwise preserved across visible → hidden → visible round-trips — hiding does not forget it.

Source

pub fn set_sidebar_width(&mut self, width: f32)

Source

pub fn bottom_panel_visible(&self) -> bool

Source

pub fn bottom_panel_height(&self) -> f32

Source

pub fn show_bottom_panel(&mut self)

Source

pub fn hide_bottom_panel(&mut self)

Source

pub fn toggle_bottom_panel(&mut self)

Source

pub fn set_bottom_panel_height(&mut self, height: f32)

Source

pub fn bottom_bands(&self) -> &[BottomBand]

The currently-registered bottom bands, in bottom-up stacking order (see BottomBand). Includes bands with visible == false — use Self::bottom_band_bounds to see which ones actually occupied space in the last computed layout.

Source

pub fn bottom_band_bounds(&self) -> Vec<(WidgetId, Rect)>

Resolved bounds for every currently-visible BottomBand, from the most recent Self::layout or Self::render call, in the same bottom-up order bottom_bands was given (index 0 = flush against the bottom edge of the main content column). Bands with visible == false have no entry — they occupy no space that frame. Empty if layout/render was never called, or if Self::with_bottom_bands was never used.

Not a field on AppShellLayout — see that struct’s doc for why.

Source

pub fn bottom_band(&self, id: &WidgetId) -> Option<&BottomBand>

Look up one registered band by id.

Source

pub fn set_bottom_band_visible(&mut self, id: &WidgetId, visible: bool) -> bool

Flip one band’s presence at runtime (e.g. a quickfix list that opens/closes independently of every other bottom band). Returns false if no band with id was registered via Self::with_bottom_bands.

Source

pub fn set_bottom_band_height(&mut self, id: &WidgetId, height_lh: f32) -> bool

Resize one band at runtime. Returns false if no band with id was registered via Self::with_bottom_bands. Unlike the legacy single bottom panel, bands have no configurable min/max — callers own their own clamping (the toolbars/lists vimcode stacks here generally have a fixed content-driven height, not a user drag).

Source

pub fn panels(&self) -> &[PanelDefinition]

Source

pub fn bottom_items(&self) -> &[PanelDefinition]

Source

pub fn add_panel(&mut self, def: PanelDefinition) -> bool

Register a panel at runtime. Returns false if a panel with the same ID already exists (no-op in that case). If this is the first panel, it becomes the active panel.

Source

pub fn remove_panel(&mut self, id: &WidgetId) -> bool

Unregister a panel by ID. Returns true if found and removed. Adjusts active_panel to keep the same panel selected (or clears it if the active panel was the one removed). Also adjusts activity_cursor analogously so keyboard navigation remains consistent after a dynamic removal.

Source

pub fn add_bottom_item(&mut self, def: PanelDefinition) -> bool

Register a bottom-pinned activity bar item at runtime.

Source

pub fn remove_bottom_item(&mut self, id: &WidgetId) -> bool

Unregister a bottom item by ID. Adjusts activity_cursor so keyboard navigation remains consistent after a dynamic removal (mirrors remove_panel’s treatment of active_panel). Also adjusts sidebar_bottom_owner the same way remove_panel adjusts active_panel: shifted down if it pointed past the removed item, cleared (falling back to whatever active_panel names) if it pointed at the removed item itself.

Source

pub fn layout(&self, area: Rect, line_height: f32) -> AppShellLayout

Compute layout bounds without drawing. Use when only hit-testing is needed (e.g. in handle).

Takes line_height rather than a &dyn Backend so callers that only know the line height (external consumers, tests) can still call it. It mirrors Backend::snap_height’s own threshold — identity above one line height (a real pixel metric), .round() at or below it (TUI’s cell grid, whose chrome_line_height is architecturally always exactly 1.0) — so this path always agrees with Self::render/Self::handle, which pass backend.snap_height directly, for the same area/line_height on the same backend.

Source

pub fn build_activity_bar(&self) -> ActivityBar

Build the ActivityBar primitive from current panel state.

When Self::activity_keyboard_focused is true:

  • ActivityBar::is_keyboard_focused is set to true, causing both the TUI and GTK backends to route key events as UiEvent::ActivityBar(id, ActivityBarEvent::KeyPressed { … }).
  • The item at Self::activity_cursor (in the top-then-bottom logical sequence) has is_keyboard_selected = true, painting the selection ring on that icon.

ActivityBar::active_accent/selection_bg carry whatever colours were last set via Self::with_active_accent/Self::set_active_accent and Self::with_selection_bg/Self::set_selection_bg — None (no accent/highlight painted) until a host app opts in.

Source

pub fn render(&self, backend: &mut dyn Backend, area: Rect) -> AppShellLayout

Render shell chrome and return layout bounds for consumer content.

Draws: activity bar, sidebar header, resize divider. Consumer draws: sidebar panel content, main content area.

Source

pub fn handle( &mut self, event: &UiEvent, backend: &dyn Backend, area: Rect, ) -> AppShellEvent

Process a UiEvent and return a semantic AppShellEvent.

Call this before the consumer’s own event handling. If the result is not AppShellEvent::Ignored, the consumer should redraw.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more