use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ToolbarIconId(pub String);
impl ToolbarIconId {
pub fn new(name: &str) -> Self {
Self(name.to_string())
}
pub fn name(&self) -> &str {
&self.0
}
}
impl From<&str> for ToolbarIconId {
fn from(s: &str) -> Self {
Self::new(s)
}
}
impl From<String> for ToolbarIconId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Clone, Debug)]
pub enum ToolbarItemDef {
Button {
id: &'static str,
icon: Option<ToolbarIconId>,
text: Option<String>,
active: bool,
disabled: bool,
min_width: f64,
tooltip: Option<&'static str>,
},
IconButton {
id: &'static str,
icon: ToolbarIconId,
active: bool,
disabled: bool,
tooltip: Option<&'static str>,
},
Dropdown {
id: &'static str,
icon: Option<ToolbarIconId>,
text: Option<String>,
active: bool,
show_chevron: bool,
items: Vec<DropdownItemDef>,
quick_select: bool,
grid_columns: Option<u8>,
min_width: f64,
tooltip: Option<&'static str>,
},
Separator,
Spacer,
}
impl ToolbarItemDef {
pub fn button(id: &'static str) -> Self {
Self::Button {
id,
icon: None,
text: None,
active: false,
disabled: false,
min_width: 0.0,
tooltip: None,
}
}
pub fn icon_button(id: &'static str, icon: impl Into<ToolbarIconId>) -> Self {
Self::IconButton {
id,
icon: icon.into(),
active: false,
disabled: false,
tooltip: None,
}
}
pub fn dropdown(id: &'static str, items: Vec<DropdownItemDef>) -> Self {
Self::Dropdown {
id,
icon: None,
text: None,
active: false,
show_chevron: true,
items,
quick_select: false,
grid_columns: None,
min_width: 0.0,
tooltip: None,
}
}
pub fn quick_select(id: &'static str, items: Vec<DropdownItemDef>) -> Self {
Self::Dropdown {
id,
icon: None,
text: None,
active: false,
show_chevron: false,
items,
quick_select: true,
grid_columns: None,
min_width: 0.0,
tooltip: None,
}
}
pub fn with_icon(mut self, icon: impl Into<ToolbarIconId>) -> Self {
match &mut self {
Self::Button { icon: ref mut i, .. } => *i = Some(icon.into()),
Self::Dropdown { icon: ref mut i, .. } => *i = Some(icon.into()),
_ => {}
}
self
}
pub fn with_text(mut self, text: impl Into<String>) -> Self {
match &mut self {
Self::Button { text: ref mut t, .. } => *t = Some(text.into()),
Self::Dropdown { text: ref mut t, .. } => *t = Some(text.into()),
_ => {}
}
self
}
pub fn with_active(mut self, active: bool) -> Self {
match &mut self {
Self::Button { active: ref mut a, .. } => *a = active,
Self::IconButton { active: ref mut a, .. } => *a = active,
Self::Dropdown { active: ref mut a, .. } => *a = active,
_ => {}
}
self
}
pub fn with_min_width(mut self, w: f64) -> Self {
match &mut self {
Self::Button { min_width: ref mut mw, .. } => *mw = w,
Self::Dropdown { min_width: ref mut mw, .. } => *mw = w,
_ => {}
}
self
}
pub fn with_tooltip(mut self, text: &'static str) -> Self {
match &mut self {
Self::Button { tooltip: ref mut t, .. } => *t = Some(text),
Self::IconButton { tooltip: ref mut t, .. } => *t = Some(text),
Self::Dropdown { tooltip: ref mut t, .. } => *t = Some(text),
_ => {}
}
self
}
pub fn tooltip(&self) -> Option<&'static str> {
match self {
Self::Button { tooltip, .. } => *tooltip,
Self::IconButton { tooltip, .. } => *tooltip,
Self::Dropdown { tooltip, .. } => *tooltip,
_ => None,
}
}
pub fn id(&self) -> &str {
match self {
Self::Button { id, .. } => id,
Self::IconButton { id, .. } => id,
Self::Dropdown { id, .. } => id,
Self::Separator | Self::Spacer => "",
}
}
}
#[derive(Clone, Debug)]
pub enum DropdownItemDef {
Action {
id: String,
label: String,
icon: Option<ToolbarIconId>,
shortcut: Option<String>,
},
Submenu {
id: String,
label: String,
icon: Option<ToolbarIconId>,
items: Vec<DropdownItemDef>,
grid_columns: Option<u8>,
},
Header {
label: String,
},
Separator,
}
impl DropdownItemDef {
pub fn action(id: impl Into<String>, label: impl Into<String>) -> Self {
Self::Action {
id: id.into(),
label: label.into(),
icon: None,
shortcut: None,
}
}
pub fn with_icon(mut self, icon: impl Into<ToolbarIconId>) -> Self {
match &mut self {
Self::Action { icon: ref mut i, .. } => *i = Some(icon.into()),
Self::Submenu { icon: ref mut i, .. } => *i = Some(icon.into()),
_ => {}
}
self
}
pub fn with_shortcut(mut self, shortcut: impl Into<String>) -> Self {
if let Self::Action { shortcut: ref mut s, .. } = &mut self {
*s = Some(shortcut.into());
}
self
}
}
#[derive(Clone, Debug)]
pub struct ToolbarSectionDef {
pub items: Vec<ToolbarItemDef>,
pub show_separator: bool,
pub align: SectionAlign,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum SectionAlign {
#[default]
Start,
End,
}
impl ToolbarSectionDef {
pub fn new(items: Vec<ToolbarItemDef>) -> Self {
Self {
items,
show_separator: false,
align: SectionAlign::Start,
}
}
pub fn with_separator(mut self) -> Self {
self.show_separator = true;
self
}
pub fn align_end(mut self) -> Self {
self.align = SectionAlign::End;
self
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum ToolbarOrientation {
#[default]
Horizontal,
Vertical,
}
#[derive(Clone, Debug)]
pub struct PanelToolbarDef {
pub sections: Vec<ToolbarSectionDef>,
pub orientation: ToolbarOrientation,
pub size: f64,
pub item_size: f64,
pub icon_size: f64,
pub spacing: f64,
pub padding: f64,
}
impl Default for PanelToolbarDef {
fn default() -> Self {
Self {
sections: Vec::new(),
orientation: ToolbarOrientation::Horizontal,
size: 32.0,
item_size: 28.0,
icon_size: 16.0,
spacing: 2.0,
padding: 4.0,
}
}
}
impl PanelToolbarDef {
pub fn horizontal(sections: Vec<ToolbarSectionDef>) -> Self {
Self {
sections,
orientation: ToolbarOrientation::Horizontal,
..Default::default()
}
}
pub fn vertical(sections: Vec<ToolbarSectionDef>) -> Self {
Self {
sections,
orientation: ToolbarOrientation::Vertical,
size: 40.0,
item_size: 32.0,
icon_size: 18.0,
spacing: 2.0,
padding: 4.0,
}
}
pub fn with_size(mut self, size: f64) -> Self {
self.size = size;
self
}
}