abletk/src/widget/row.rs

133 lines
3.7 KiB
Rust
Executable File

/*
* Copyright (C) 2022 Umut İnan Erdoğan <umutinanerdogan@pm.me>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
use crate::{layout::position::Position, widget::Widget, window::Window};
use abletk_common::Renderer;
use winit::event::MouseButton;
pub struct Row {
widgets: Vec<Box<dyn Widget>>,
}
impl Widget for Row {
fn draw(&self, renderer: &mut Renderer) {
let (prev_x, _) = renderer.position();
self.widgets.iter().for_each(|widget| {
let pos = widget.position(renderer);
renderer.position_at(
renderer.position().0 + pos.x(),
renderer.position().1 + pos.y()
);
widget.draw(renderer);
renderer.position_at(
renderer.position().0 + pos.width(),
renderer.position().1
);
});
renderer.position_at(prev_x, renderer.position().1)
}
fn position(&self, renderer: &mut Renderer) -> Position {
let (width, height) = self.widgets.iter()
.map(|widget| widget.position(renderer))
.map(|pos| (pos.width(), pos.height()))
.fold((0, 0), |accum, item| (
accum.0 + item.0,
if item.1 > accum.1 { item.1 } else { accum.1 }
));
Position::new(0, 0, width, height)
}
fn mouse_pressed(&mut self,
renderer: &mut Renderer,
window: &mut Window,
button: MouseButton,
x: u32,
y: u32,
) {
let mut pos = Position::new(0, 0, 0, 0);
for widget in &mut self.widgets {
let widget_pos = widget.position(renderer);
pos = Position::new(
widget_pos.x() + pos.x(),
widget_pos.y(),
widget_pos.width(),
widget_pos.height(),
);
if pos.contains(x, y) {
widget.mouse_pressed(
renderer,
window,
button,
x - pos.x(),
y - pos.y(),
);
}
pos = Position::new(
pos.x() + widget_pos.width(),
pos.y(),
pos.width(),
pos.height(),
);
}
}
fn mouse_released(&mut self,
renderer: &mut Renderer,
window: &mut Window,
button: MouseButton,
x: u32,
y: u32,
) {
let mut pos = Position::new(0, 0, 0, 0);
for widget in &mut self.widgets {
let widget_pos = widget.position(renderer);
pos = Position::new(
widget_pos.x() + pos.x(),
widget_pos.y(),
widget_pos.width(),
widget_pos.height(),
);
if pos.contains(x, y) {
widget.mouse_released(
renderer,
window,
button,
x - pos.x(),
y - pos.y(),
);
}
pos = Position::new(
pos.x() + widget_pos.width(),
pos.y(),
pos.width(),
pos.height(),
);
}
}
}
impl Row {
pub fn new() -> Self {
Self {
widgets: Vec::new(),
}
}
pub fn add<T: Widget + 'static>(mut self, widget: T) -> Self {
self.widgets.push(Box::new(widget));
self
}
}