Skip to main content

InteractiveWidget

Trait InteractiveWidget 

Source
pub trait InteractiveWidget<Id> {
    type State;

    // Required methods
    fn sense(&self) -> Sense;
    fn render(
        &self,
        surface: &mut Surface<'_>,
        state: &mut Self::State,
        response: Response<Id>,
    );
}
Expand description

A widget that renders itself styled by an already-resolved Response, with the Sense it needs fixed by the widget rather than chosen at the call site.

A composite widget like Button, Scrollbar, List, or Tabs needs to know what happened to it this frame (hovered, pressed, clicked, dragged) to pick its style and resolve its own hit-testing, but never calls Interaction::interact itself: doing so would let it register the wrong rect, or let a call site register it with a Sense its presentation doesn’t match (a click handler drawn without ever showing a hover state, say). sense fixes what the widget needs so a call site can’t get that pairing wrong, and render takes the resulting Response as a plain argument rather than calling interact itself: the widget never receives an Interaction, and has no Id type parameter, so it can’t call interact with the wrong rect because it has nothing to call interact on.

type State covers widgets with no state (Button, Tabs: ()), a scroll position (Scrollbar: ScrollState), or a selection/scroll index (List: ListState), the same Widget/StatefulWidget split applied to interactive widgets rather than a separate InteractiveStatefulWidget trait.

Has no generic method, so dyn InteractiveWidget<Id, State = ()> is object-safe, e.g. a Vec<Box<dyn InteractiveWidget<Id, State = ()>>> of heterogeneous stateless widgets. Id is the trait’s own type parameter (not a generic method) precisely so that stays true.

§Examples

use retroglyph_core::color::Style;
use retroglyph_core::grid::{Grid, Rect};
use retroglyph_ui::{InteractiveWidget, Response, Sense, Surface};

struct Marker(char);

impl<Id> InteractiveWidget<Id> for Marker {
    type State = ();

    fn sense(&self) -> Sense {
        Sense::click()
    }

    fn render(&self, surface: &mut Surface<'_>, _state: &mut Self::State, response: Response<Id>) {
        let style = if response.hovered() { Style::new().bg(retroglyph_core::color::Color::RED) } else { Style::new() };
        surface.put((0, 0), self.0, style);
    }
}

Required Associated Types§

Source

type State

State that outlives one render call, e.g. a selection index or scroll offset. () for widgets that have none.

Required Methods§

Source

fn sense(&self) -> Sense

What this widget needs from the pointer and keyboard, fixed by the widget: a call site cannot register it with a Sense its presentation doesn’t match.

Source

fn render( &self, surface: &mut Surface<'_>, state: &mut Self::State, response: Response<Id>, )

Draw into surface, styled by response, which the caller already resolved (via Interaction::interact) for surface.area() and sense.

Implementors§