abacus/abacus-ui/src/app_header.rs

189 lines
6.5 KiB
Rust

use druid::{
widget::{Container, Controller, Flex, Label, Padding, Painter, Svg, SvgData},
Color, Data, LifeCycle, RenderContext, Widget, WidgetExt,
};
use crate::AppData;
pub fn app_header_ui() -> impl Widget<AppData> {
let open_svg = include_str!("../assets/folder-open.svg")
.parse::<SvgData>()
.unwrap_or_default();
let disk_svg = include_str!("../assets/floppy-disk.svg")
.parse::<SvgData>()
.unwrap_or_default();
let run_svg = include_str!("../assets/play.svg")
.parse::<SvgData>()
.unwrap_or_default();
let plus_svg = include_str!("../assets/plus.svg")
.parse::<SvgData>()
.unwrap_or_default();
let abacus_svg = include_str!("../assets/abacus.svg")
.parse::<SvgData>()
.unwrap_or_default();
Container::new(
Flex::row()
.must_fill_main_axis(true)
.with_spacer(10.0)
.with_child(
Container::new(Padding::new(5.0, Svg::new(abacus_svg).fix_width(20.0)))
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
.on_click(|_ctx, _, _| {}),
)
.with_spacer(20.0)
.with_child(
Container::new(Padding::new(10.0, Svg::new(open_svg).fix_width(10.0)))
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
.on_click(|ctx, _, _| {
let abacus = druid::FileSpec::new("Abacus File", &["abacus"]);
let json = druid::FileSpec::new("JSON File", &["json"]);
let open_dialog_options = druid::FileDialogOptions::new()
.allowed_types(vec![abacus, json])
.default_type(abacus)
.name_label("Source")
.title("Open Workbook")
.button_text("Open");
ctx.submit_command(
druid::commands::SHOW_OPEN_PANEL.with(open_dialog_options),
);
}),
)
.with_spacer(10.0)
.with_child(
Container::new(Padding::new(10.0, Svg::new(disk_svg).fix_width(10.0)))
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
.on_click(|ctx, data: &mut AppData, _| {
let abacus = druid::FileSpec::new("Abacus File", &["abacus"]);
let json = druid::FileSpec::new("JSON File", &["json"]);
if data.filename.is_some() {
data.save();
} else {
let save_dialog_options = druid::FileDialogOptions::new()
.allowed_types(vec![abacus, json])
.default_type(abacus)
.name_label("Target")
.title("Save workbook")
.button_text("Save");
ctx.submit_command(
druid::commands::SHOW_SAVE_PANEL.with(save_dialog_options),
);
}
}),
)
.with_spacer(20.0)
.with_flex_child(
Padding::new(
5.0,
Container::new(Padding::new(
3.0,
Label::dynamic(|data: &AppData, _| {
data.filename
.clone()
.unwrap_or_else(|| String::from("Scratch file"))
})
.with_text_size(12.0)
.center(),
))
.background(Color::rgb8(35, 35, 35))
.rounded(4.0)
.border(Color::rgb8(10, 10, 10), 1.0)
.expand_width(),
),
1.0,
)
.with_spacer(20.0)
.with_child(
Container::new(Padding::new(10.0, Svg::new(plus_svg).fix_width(10.0)))
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
.on_click(|_ctx, data: &mut AppData, _env| {
data.blocks.push_back(crate::Block::new(
&format!("Block #{}", data.blocks.len() + 1),
data.blocks.len(),
));
}),
)
.with_spacer(10.0)
.with_child(
Container::new(Padding::new(10.0, Svg::new(run_svg).fix_width(10.0)))
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
.on_click(|_ctx, data: &mut AppData, _env| data.process()),
)
.with_spacer(20.0)
.expand_width(),
)
.background(Color::rgb8(20, 20, 20))
}
pub fn header_separater() -> impl Widget<AppData> {
Painter::new(|ctx, _data, _env| {
let rect = ctx.size().to_rect();
ctx.fill(rect, &Color::rgb8(0, 0, 0))
})
.fix_height(1.0)
}
pub struct ToolbarButtonController {
color: Color,
}
impl ToolbarButtonController {
pub fn new(color: Color) -> Self {
Self { color }
}
}
impl<T: Data> Controller<T, Container<T>> for ToolbarButtonController {
fn event(
&mut self,
child: &mut Container<T>,
ctx: &mut druid::EventCtx,
event: &druid::Event,
data: &mut T,
env: &druid::Env,
) {
ctx.set_cursor(&druid::Cursor::Pointer);
child.event(ctx, event, data, env)
}
fn lifecycle(
&mut self,
child: &mut Container<T>,
ctx: &mut druid::LifeCycleCtx,
event: &druid::LifeCycle,
data: &T,
env: &druid::Env,
) {
match event {
LifeCycle::HotChanged(true) => {
child.set_background(self.color.clone());
ctx.request_paint();
}
LifeCycle::HotChanged(false) => {
child.set_background(Color::TRANSPARENT);
ctx.request_paint();
}
_ => {}
}
child.lifecycle(ctx, event, data, env)
}
fn update(
&mut self,
child: &mut Container<T>,
ctx: &mut druid::UpdateCtx,
old_data: &T,
data: &T,
env: &druid::Env,
) {
child.update(ctx, old_data, data, env)
}
}