diff --git a/CHANGELOG.md b/CHANGELOG.md index 47fbdf83..91796d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add `--duration` flag to `eww open` - Add support for referring to monitor with `` - Add support for multiple matchers in `monitor` field +- Add `stack` widget (By: vladaviedov) ## [0.4.0] (04.09.2022) diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 07a081d3..fb2b1286 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -80,6 +80,7 @@ pub const BUILTIN_WIDGET_NAMES: &[&str] = &[ WIDGET_NAME_REVEALER, WIDGET_NAME_SCROLL, WIDGET_NAME_OVERLAY, + WIDGET_NAME_STACK, ]; //// widget definitions @@ -107,6 +108,7 @@ pub(super) fn widget_use_to_gtk_widget(bargs: &mut BuilderArgs) -> Result build_gtk_revealer(bargs)?.upcast(), WIDGET_NAME_SCROLL => build_gtk_scrolledwindow(bargs)?.upcast(), WIDGET_NAME_OVERLAY => build_gtk_overlay(bargs)?.upcast(), + WIDGET_NAME_STACK => build_gtk_stack(bargs)?.upcast(), _ => { return Err(DiagError(gen_diagnostic! { msg = format!("referenced unknown widget `{}`", bargs.widget_use.name), @@ -324,7 +326,7 @@ fn build_gtk_revealer(bargs: &mut BuilderArgs) -> Result { let gtk_widget = gtk::Revealer::new(); def_widget!(bargs, _g, gtk_widget, { // @prop transition - the name of the transition. Possible values: $transition - prop(transition: as_string = "crossfade") { gtk_widget.set_transition_type(parse_transition(&transition)?); }, + prop(transition: as_string = "crossfade") { gtk_widget.set_transition_type(parse_revealer_transition(&transition)?); }, // @prop reveal - sets if the child is revealed or not prop(reveal: as_bool) { gtk_widget.set_reveal_child(reveal); }, // @prop duration - the duration of the reveal transition. Default: "500ms" @@ -971,6 +973,44 @@ fn build_gtk_calendar(bargs: &mut BuilderArgs) -> Result { Ok(gtk_widget) } +const WIDGET_NAME_STACK: &str = "stack"; +/// @widget stack +/// @desc A widget that displays one of its children at a time +fn build_gtk_stack(bargs: &mut BuilderArgs) -> Result { + let gtk_widget = gtk::Stack::new(); + def_widget!(bargs, _g, gtk_widget, { + // @prop selected - index of child which should be shown + prop(selected: as_i32) { gtk_widget.set_visible_child_name(&selected.to_string()); }, + // @prop transition - the name of the transition. Possible values: $transition + prop(transition: as_string = "crossfade") { gtk_widget.set_transition_type(parse_stack_transition(&transition)?); }, + // @prop same-size - sets whether all children should be the same size + prop(same_size: as_bool = false) { gtk_widget.set_homogeneous(same_size); } + }); + + match bargs.widget_use.children.len().cmp(&1) { + Ordering::Less => { + Err(DiagError(gen_diagnostic!("stack must contain at least one element", bargs.widget_use.span)).into()) + } + Ordering::Greater | Ordering::Equal => { + let children = bargs.widget_use.children.iter().map(|child| { + build_gtk_widget( + bargs.scope_graph, + bargs.widget_defs.clone(), + bargs.calling_scope, + child.clone(), + bargs.custom_widget_invocation.clone(), + ) + }); + for (i, child) in children.enumerate() { + let child = child?; + gtk_widget.add_named(&child, &i.to_string()); + child.show(); + } + Ok(gtk_widget) + } + } +} + const WIDGET_NAME_TRANSFORM: &str = "transform"; /// @widget transform /// @desc A widget that applies transformations to its content. They are applied in the following @@ -1064,7 +1104,7 @@ fn parse_dragtype(o: &str) -> Result { } /// @var transition - "slideright", "slideleft", "slideup", "slidedown", "crossfade", "none" -fn parse_transition(t: &str) -> Result { +fn parse_revealer_transition(t: &str) -> Result { enum_parse! { "transition", t, "slideright" => gtk::RevealerTransitionType::SlideRight, "slideleft" => gtk::RevealerTransitionType::SlideLeft, @@ -1075,6 +1115,18 @@ fn parse_transition(t: &str) -> Result { } } +/// @var transition - "slideright", "slideleft", "slideup", "slidedown", "crossfade", "none" +fn parse_stack_transition(t: &str) -> Result { + enum_parse! { "transition", t, + "slideright" => gtk::StackTransitionType::SlideRight, + "slideleft" => gtk::StackTransitionType::SlideLeft, + "slideup" => gtk::StackTransitionType::SlideUp, + "slidedown" => gtk::StackTransitionType::SlideDown, + "fade" | "crossfade" => gtk::StackTransitionType::Crossfade, + "none" => gtk::StackTransitionType::None, + } +} + /// @var alignment - "fill", "baseline", "center", "start", "end" fn parse_align(o: &str) -> Result { enum_parse! { "alignment", o,