use std::sync::Arc; use warpui::elements::{ChildView, Flex, ParentElement, SavePosition}; use warpui::{Action, Element, TypedActionView, View, ViewContext, ViewHandle}; use crate::view_components::action_button::AdjoinedSide; use crate::view_components::compactible_action_button::RenderCompactibleActionButton; use crate::{ ui_components::icons::Icon, view_components::action_button::{ ActionButton, ButtonSize, KeystrokeSource, NakedTheme, PrimaryRightBiasedTheme, PrimaryTheme, }, view_components::compactible_action_button::CompactibleActionButton, }; /// A split button composed of a primary CompactibleActionButton and a trailing /// icon-only menu button (chevron-down). The menu button may be used as an anchor /// for a dropdown Menu via `with_menu`. #[derive(Clone)] #[allow(dead_code)] pub struct CompactibleSplitActionButton { primary_button: CompactibleActionButton, menu_button: ViewHandle, save_position_id: Option, } impl CompactibleSplitActionButton { /// Creates a split button: a primary CompactibleActionButton and an icon-only /// chevron menu button that inherits the same theme choice. #[allow(dead_code)] #[allow(clippy::too_many_arguments)] pub fn new( label: String, keybinding: Option, size: ButtonSize, action: A, menu_action: A, compact_icon: Icon, use_primary_theme: bool, save_position_id: Option, ctx: &mut ViewContext<'_, T>, ) -> Self where T: TypedActionView + View, A: Action + Clone + 'static, { let mut primary_button = CompactibleActionButton::new( label, keybinding, size, action, compact_icon, if use_primary_theme { Arc::new(PrimaryTheme) } else { Arc::new(NakedTheme) }, ctx, ); primary_button.set_adjoined_side(AdjoinedSide::Right, ctx); // The down-caret icon-only menu button. let menu_button = ctx.add_typed_action_view(|_ctx| { ActionButton::new_with_boxed_theme( "", if use_primary_theme { Arc::new(PrimaryRightBiasedTheme) } else { Arc::new(NakedTheme) }, ) .with_size(size) .with_icon(Icon::ChevronDown) .with_adjoined_side(AdjoinedSide::Left) .on_click(move |ctx| ctx.dispatch_typed_action(menu_action.clone())) }); Self { primary_button, menu_button, save_position_id, } } fn render_button(&self, is_expanded: bool) -> Box { let button = if is_expanded { self.primary_button.expanded_button() } else { self.primary_button.compact_button() }; let row = Flex::row() .with_child(ChildView::new(button).finish()) .with_child(ChildView::new(&self.menu_button).finish()); if let Some(save_position_id) = &self.save_position_id { SavePosition::new(row.finish(), save_position_id).finish() } else { row.finish() } } pub fn set_keybinding( &mut self, keybinding: Option, ctx: &mut ViewContext, ) { self.primary_button.set_keybinding(keybinding, ctx); } } impl RenderCompactibleActionButton for CompactibleSplitActionButton { fn render_expanded_button(&self) -> Box { self.render_button(true) } fn render_compact_button(&self) -> Box { self.render_button(false) } }