1
1
mirror of https://github.com/wez/wezterm.git synced 2024-10-26 15:52:29 +03:00

Add a State parameter to Ui that's passed to all widget calls

This commit is contained in:
Charlie Groves 2022-10-09 17:04:46 -04:00
parent f0e3512629
commit 39bdcc09e3

View File

@ -53,16 +53,16 @@ pub struct UpdateArgs<'a> {
/// Implementing the `Widget` trait allows for defining a potentially /// Implementing the `Widget` trait allows for defining a potentially
/// interactive component in a UI layout. /// interactive component in a UI layout.
pub trait Widget { pub trait Widget<State> {
/// Draw the widget to the RenderArgs::surface, and optionally /// Draw the widget to the RenderArgs::surface, and optionally
/// update RenderArgs::cursor to reflect the cursor position and /// update RenderArgs::cursor to reflect the cursor position and
/// display attributes. /// display attributes.
fn render(&mut self, args: &mut RenderArgs); fn render(&mut self, args: &mut RenderArgs, state: &mut State);
/// Override this to have your widget specify its layout constraints. /// Override this to have your widget specify its layout constraints.
/// You may wish to have your widget constructor receive a `Constraints` /// You may wish to have your widget constructor receive a `Constraints`
/// instance to make this more easily configurable in more generic widgets. /// instance to make this more easily configurable in more generic widgets.
fn get_size_constraints(&self) -> layout::Constraints { fn get_size_constraints(&self, _state: &State) -> layout::Constraints {
Default::default() Default::default()
} }
@ -70,7 +70,12 @@ pub trait Widget {
/// other widget events. /// other widget events.
/// Return `true` if your widget handled the event, or `false` to allow /// Return `true` if your widget handled the event, or `false` to allow
/// the event to propagate to the widget parent. /// the event to propagate to the widget parent.
fn process_event(&mut self, _event: &WidgetEvent, _args: &mut UpdateArgs) -> bool { fn process_event(
&mut self,
_event: &WidgetEvent,
_args: &mut UpdateArgs,
_state: &mut State,
) -> bool {
false false
} }
} }
@ -137,11 +142,11 @@ impl Default for WidgetId {
} }
} }
struct RenderData<'widget> { struct RenderData<'widget, State> {
surface: Surface, surface: Surface,
cursor: CursorShapeAndPosition, cursor: CursorShapeAndPosition,
coordinates: ParentRelativeCoords, coordinates: ParentRelativeCoords,
widget: Box<dyn Widget + 'widget>, widget: Box<dyn Widget<State> + 'widget>,
} }
#[derive(Default)] #[derive(Default)]
@ -178,20 +183,26 @@ impl Graph {
} }
/// Manages the widgets on the display /// Manages the widgets on the display
#[derive(Default)] pub struct Ui<'widget, State> {
pub struct Ui<'widget> {
graph: Graph, graph: Graph,
render: FnvHashMap<WidgetId, RenderData<'widget>>, render: FnvHashMap<WidgetId, RenderData<'widget, State>>,
input_queue: VecDeque<WidgetEvent>, input_queue: VecDeque<WidgetEvent>,
focused: Option<WidgetId>, focused: Option<WidgetId>,
state: State,
} }
impl<'widget> Ui<'widget> { impl<'widget, State> Ui<'widget, State> {
pub fn new() -> Self { pub fn new(state: State) -> Self {
Default::default() Self {
graph: Default::default(),
render: Default::default(),
input_queue: Default::default(),
focused: Default::default(),
state,
}
} }
pub fn add<W: Widget + 'widget>(&mut self, parent: Option<WidgetId>, w: W) -> WidgetId { pub fn add<W: Widget<State> + 'widget>(&mut self, parent: Option<WidgetId>, w: W) -> WidgetId {
let id = self.graph.add(parent); let id = self.graph.add(parent);
self.render.insert( self.render.insert(
@ -211,11 +222,11 @@ impl<'widget> Ui<'widget> {
id id
} }
pub fn set_root<W: Widget + 'widget>(&mut self, w: W) -> WidgetId { pub fn set_root<W: Widget<State> + 'widget>(&mut self, w: W) -> WidgetId {
self.add(None, w) self.add(None, w)
} }
pub fn add_child<W: Widget + 'widget>(&mut self, parent: WidgetId, w: W) -> WidgetId { pub fn add_child<W: Widget<State> + 'widget>(&mut self, parent: WidgetId, w: W) -> WidgetId {
self.add(Some(parent), w) self.add(Some(parent), w)
} }
@ -226,7 +237,9 @@ impl<'widget> Ui<'widget> {
cursor: &mut render_data.cursor, cursor: &mut render_data.cursor,
}; };
render_data.widget.process_event(event, &mut args) render_data
.widget
.process_event(event, &mut args, &mut self.state)
} }
fn deliver_event(&mut self, mut id: WidgetId, event: &WidgetEvent) { fn deliver_event(&mut self, mut id: WidgetId, event: &WidgetEvent) {
@ -368,7 +381,7 @@ impl<'widget> Ui<'widget> {
surface, surface,
is_focused: self.focused.map(|f| f == id).unwrap_or(false), is_focused: self.focused.map(|f| f == id).unwrap_or(false),
}; };
render_data.widget.render(&mut args); render_data.widget.render(&mut args, &mut self.state);
} }
screen.draw_from_screen( screen.draw_from_screen(
surface, surface,
@ -425,7 +438,9 @@ impl<'widget> Ui<'widget> {
layout: &mut layout::LayoutState, layout: &mut layout::LayoutState,
widget: WidgetId, widget: WidgetId,
) -> Result<()> { ) -> Result<()> {
let constraints = self.render[&widget].widget.get_size_constraints(); let constraints = self.render[&widget]
.widget
.get_size_constraints(&self.state);
let children = self.graph.children(widget).to_vec(); let children = self.graph.children(widget).to_vec();
layout.add_widget(widget, &constraints, &children); layout.add_widget(widget, &constraints, &children);
@ -520,15 +535,15 @@ mod test {
struct CursorHider {} struct CursorHider {}
impl Widget for CursorHider { impl Widget<()> for CursorHider {
fn render(&mut self, args: &mut RenderArgs) { fn render(&mut self, args: &mut RenderArgs, _state: &mut ()) {
args.cursor.visibility = CursorVisibility::Hidden; args.cursor.visibility = CursorVisibility::Hidden;
} }
} }
#[test] #[test]
fn hide_cursor() { fn hide_cursor() {
let mut ui = Ui::new(); let mut ui = Ui::new(());
ui.set_root(CursorHider {}); ui.set_root(CursorHider {});