use uuid::Uuid;
use vek::Vec4;
use crate::ui::layouts::{HStack, VStack};
use crate::ui::workspace::NodeId;
use crate::ui::{Drawable, UiView, ViewContext};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolbarOrientation {
Horizontal,
Vertical,
}
#[derive(Debug, Clone)]
pub struct ToolbarStyle {
pub rect: [f32; 4], pub fill: Vec4<f32>, pub border: Vec4<f32>, pub radius_px: f32, pub border_px: f32, pub layer: i32, }
#[derive(Debug, Clone)]
pub struct ToolbarSeparator {
pub color: Vec4<f32>,
pub thickness: f32,
pub length: f32, }
impl Default for ToolbarSeparator {
fn default() -> Self {
Self {
color: Vec4::new(0.3, 0.3, 0.35, 1.0),
thickness: 1.0,
length: 24.0,
}
}
}
#[derive(Debug, Clone)]
pub struct Toolbar {
pub id: String,
render_id: Uuid,
pub style: ToolbarStyle,
pub orientation: ToolbarOrientation,
pub draw_background: bool, pub hstack: Option<HStack>, pub vstack: Option<VStack>, pub manual_separators: Vec<(f32, ToolbarSeparator)>, }
impl Toolbar {
pub fn new(style: ToolbarStyle, orientation: ToolbarOrientation) -> Self {
let rect = style.rect;
let (hstack, vstack) = match orientation {
ToolbarOrientation::Horizontal => (
Some(HStack::new(rect).with_spacing(4.0).with_padding(8.0)),
None,
),
ToolbarOrientation::Vertical => (
None,
Some(VStack::new(rect).with_spacing(4.0).with_padding(8.0)),
),
};
Self {
id: String::new(),
render_id: Uuid::new_v4(),
style,
orientation,
draw_background: true,
hstack,
vstack,
manual_separators: Vec::new(),
}
}
pub fn with_id(mut self, id: impl Into<String>) -> Self {
self.id = id.into();
self
}
pub fn with_background(mut self, draw: bool) -> Self {
self.draw_background = draw;
self
}
pub fn with_spacing(mut self, spacing: f32) -> Self {
match self.orientation {
ToolbarOrientation::Horizontal => {
if let Some(ref mut hstack) = self.hstack {
*hstack = hstack.clone().with_spacing(spacing);
}
}
ToolbarOrientation::Vertical => {
if let Some(ref mut vstack) = self.vstack {
*vstack = vstack.clone().with_spacing(spacing);
}
}
}
self
}
pub fn with_padding(mut self, padding: f32) -> Self {
match self.orientation {
ToolbarOrientation::Horizontal => {
if let Some(ref mut hstack) = self.hstack {
*hstack = hstack.clone().with_padding(padding);
}
}
ToolbarOrientation::Vertical => {
if let Some(ref mut vstack) = self.vstack {
*vstack = vstack.clone().with_padding(padding);
}
}
}
self
}
pub fn add_child(&mut self, child: NodeId) {
match self.orientation {
ToolbarOrientation::Horizontal => {
if let Some(ref mut hstack) = self.hstack {
hstack.add_child(child);
}
}
ToolbarOrientation::Vertical => {
if let Some(ref mut vstack) = self.vstack {
vstack.add_child(child);
}
}
}
}
pub fn children(&self) -> &[NodeId] {
match self.orientation {
ToolbarOrientation::Horizontal => self
.hstack
.as_ref()
.map(|h| h.children.as_slice())
.unwrap_or(&[]),
ToolbarOrientation::Vertical => self
.vstack
.as_ref()
.map(|v| v.children.as_slice())
.unwrap_or(&[]),
}
}
pub fn add_separator_at(&mut self, position: f32, separator_style: Option<ToolbarSeparator>) {
let sep = separator_style.unwrap_or_default();
self.manual_separators.push((position, sep));
}
pub fn create_separator_at(
&self,
position: f32,
separator_style: Option<ToolbarSeparator>,
) -> Drawable {
let sep = separator_style.unwrap_or_default();
let [x, y, w, h] = self.style.rect;
let rect = match self.orientation {
ToolbarOrientation::Horizontal => {
let sep_y = y + (h - sep.length) / 2.0;
[position, sep_y, sep.thickness, sep.length]
}
ToolbarOrientation::Vertical => {
let sep_x = x + (w - sep.length) / 2.0;
[sep_x, position, sep.length, sep.thickness]
}
};
Drawable::Rect {
id: Uuid::new_v4(),
rect,
fill: sep.color,
border: Vec4::new(0.0, 0.0, 0.0, 0.0),
radius_px: 0.0,
border_px: 0.0,
layer: self.style.layer + 1,
}
}
}
impl UiView for Toolbar {
fn build(&mut self, ctx: &mut ViewContext) {
if self.draw_background {
ctx.push(Drawable::Rect {
id: self.render_id,
rect: self.style.rect,
fill: self.style.fill,
border: self.style.border,
radius_px: self.style.radius_px,
border_px: self.style.border_px,
layer: self.style.layer,
});
}
for (position, sep) in &self.manual_separators {
let drawable = self.create_separator_at(*position, Some(sep.clone()));
ctx.push(drawable);
}
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn view_id(&self) -> &str {
&self.id
}
}