click events! soon there will be buttons!
This commit is contained in:
parent
dbf64e8b7f
commit
4a4b94ba2a
|
@ -9,7 +9,7 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use winit::event::{Event, WindowEvent as WinitWindowEvent};
|
use winit::event::{Event, WindowEvent as WinitWindowEvent, ElementState};
|
||||||
use winit::event_loop::EventLoop;
|
use winit::event_loop::EventLoop;
|
||||||
use winit::window::WindowId;
|
use winit::window::WindowId;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
|
@ -107,14 +107,39 @@ impl Application {
|
||||||
emit_app_event!(self, ApplicationEvent::AllWindowsDestroyed);
|
emit_app_event!(self, ApplicationEvent::AllWindowsDestroyed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
window_id,
|
window_id,
|
||||||
event: WinitWindowEvent::Resized(size)
|
event: WinitWindowEvent::Resized(size)
|
||||||
} => self.windows.get_mut(&window_id).unwrap().resized(size),
|
} => self.windows.get_mut(&window_id).unwrap().resized(size),
|
||||||
|
|
||||||
|
Event::WindowEvent {
|
||||||
|
window_id,
|
||||||
|
event: WinitWindowEvent::CursorMoved {
|
||||||
|
position,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
} => self.windows.get_mut(&window_id).unwrap().cursor_moved(position),
|
||||||
|
|
||||||
|
Event::WindowEvent {
|
||||||
|
window_id,
|
||||||
|
event: WinitWindowEvent::MouseInput {
|
||||||
|
state,
|
||||||
|
button,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
} => match state {
|
||||||
|
ElementState::Pressed => self.windows
|
||||||
|
.get_mut(&window_id).unwrap().mouse_pressed(button),
|
||||||
|
ElementState::Released => self.windows
|
||||||
|
.get_mut(&window_id).unwrap().mouse_released(button),
|
||||||
|
}
|
||||||
|
|
||||||
Event::MainEventsCleared => {
|
Event::MainEventsCleared => {
|
||||||
// determine if state changed and request redraw if needed
|
// determine if state changed and request redraw if needed
|
||||||
// rinse and repeat for every window
|
// rinse and repeat for every window
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::RedrawRequested(window_id) =>
|
Event::RedrawRequested(window_id) =>
|
||||||
self.windows.get_mut(&window_id).unwrap().render(),
|
self.windows.get_mut(&window_id).unwrap().render(),
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ impl Position {
|
||||||
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
|
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
|
||||||
Position { x, y, width, height }
|
Position { x, y, width, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, x: u32, y: u32) -> bool {
|
||||||
|
x >= self.x && y >= self.y && x < self.x + self.width && y < self.y + self.height
|
||||||
|
}
|
||||||
|
|
||||||
pub fn x(&self) -> u32 {
|
pub fn x(&self) -> u32 {
|
||||||
self.x
|
self.x
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{layout::position::Position, widget::Widget};
|
use crate::{layout::position::Position, widget::Widget, window::Window};
|
||||||
use abletk_common::Renderer;
|
use abletk_common::Renderer;
|
||||||
|
use winit::event::MouseButton;
|
||||||
|
|
||||||
pub struct Column {
|
pub struct Column {
|
||||||
widgets: Vec<Box<dyn Widget>>,
|
widgets: Vec<Box<dyn Widget>>,
|
||||||
|
@ -43,6 +44,78 @@ impl Widget for Column {
|
||||||
|
|
||||||
Position::new(0, 0, width, height)
|
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.y() + 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(),
|
||||||
|
pos.y() + widget_pos.height(),
|
||||||
|
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.y() + 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(),
|
||||||
|
pos.y() + widget_pos.height(),
|
||||||
|
pos.width(),
|
||||||
|
pos.height(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Column {
|
impl Column {
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use abletk_common::{Renderer, brush::Brush, color::Color, rgb};
|
use abletk_common::{Renderer, brush::Brush, color::Color, rgb};
|
||||||
use crate::{widget::Widget, layout::position::Position};
|
use winit::event::MouseButton;
|
||||||
|
use crate::{widget::Widget, layout::position::Position, window::Window};
|
||||||
|
|
||||||
pub struct Label {
|
pub struct Label {
|
||||||
text: String,
|
text: String,
|
||||||
|
@ -28,6 +29,26 @@ impl Widget for Label {
|
||||||
let (width, height) = renderer.get_text_size(&self.text);
|
let (width, height) = renderer.get_text_size(&self.text);
|
||||||
Position::new(0, 0, width, height)
|
Position::new(0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mouse_pressed(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
) {
|
||||||
|
eprintln!("Label::mouse_pressed {} {x}, {y}", self.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_released(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
) {
|
||||||
|
eprintln!("Label::mouse_released {} {x}, {y}", self.text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Label {
|
impl Label {
|
||||||
|
|
|
@ -16,11 +16,29 @@ pub use column::*;
|
||||||
pub use label::*;
|
pub use label::*;
|
||||||
pub use padding::*;
|
pub use padding::*;
|
||||||
pub use row::*;
|
pub use row::*;
|
||||||
|
use winit::event::MouseButton;
|
||||||
|
|
||||||
use crate::layout::position::Position;
|
use crate::{layout::position::Position, window::Window};
|
||||||
|
|
||||||
pub trait Widget {
|
pub trait Widget {
|
||||||
fn draw(&self, renderer: &mut Renderer);
|
fn draw(&self, renderer: &mut Renderer);
|
||||||
|
|
||||||
// fixme: don't pass renderer
|
// fixme: don't pass renderer
|
||||||
fn position(&self, renderer: &mut Renderer) -> Position;
|
fn position(&self, renderer: &mut Renderer) -> Position;
|
||||||
|
|
||||||
|
fn mouse_pressed(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn mouse_released(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{layout::position::Position, widget::Widget};
|
use crate::{layout::position::Position, widget::Widget, window::Window};
|
||||||
use abletk_common::Renderer;
|
use abletk_common::Renderer;
|
||||||
|
use winit::event::MouseButton;
|
||||||
|
|
||||||
pub struct Padding<W: Widget> {
|
pub struct Padding<W: Widget> {
|
||||||
widget: W,
|
widget: W,
|
||||||
|
@ -32,6 +33,32 @@ impl<W: Widget> Widget for Padding<W> {
|
||||||
pos.height() + self.bottom,
|
pos.height() + self.bottom,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mouse_pressed(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
) {
|
||||||
|
let pos = self.position(renderer);
|
||||||
|
if pos.contains(x, y) {
|
||||||
|
self.widget.mouse_pressed(renderer, window, button, x - pos.x(), y - pos.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_released(&mut self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
window: &mut Window,
|
||||||
|
button: MouseButton,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
) {
|
||||||
|
let pos = self.position(renderer);
|
||||||
|
if pos.contains(x, y) {
|
||||||
|
self.widget.mouse_released(renderer, window, button, x - pos.x(), y - pos.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> Padding<W> {
|
impl<W: Widget> Padding<W> {
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::{layout::position::Position, widget::Widget};
|
use crate::{layout::position::Position, widget::Widget, window::Window};
|
||||||
use abletk_common::Renderer;
|
use abletk_common::Renderer;
|
||||||
|
use winit::event::MouseButton;
|
||||||
|
|
||||||
pub struct Row {
|
pub struct Row {
|
||||||
widgets: Vec<Box<dyn Widget>>,
|
widgets: Vec<Box<dyn Widget>>,
|
||||||
|
@ -43,6 +44,78 @@ impl Widget for Row {
|
||||||
|
|
||||||
Position::new(0, 0, width, height)
|
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 {
|
impl Row {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::rc::Rc;
|
||||||
use raw_window_handle::HasRawWindowHandle;
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
use winit::{
|
use winit::{
|
||||||
event_loop::EventLoopWindowTarget,
|
event_loop::EventLoopWindowTarget,
|
||||||
window::{Window as WinitWindow, WindowBuilder as WinitWindowBuilder},
|
window::{Window as WinitWindow, WindowBuilder as WinitWindowBuilder}, dpi::PhysicalPosition, event::MouseButton,
|
||||||
};
|
};
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
use winit::error::OsError;
|
use winit::error::OsError;
|
||||||
|
@ -26,10 +26,11 @@ use crate::widget::Widget;
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
window: WinitWindow,
|
window: WinitWindow,
|
||||||
events: HashMap<Event, Vec<fn(&mut Context, &mut Window)>>,
|
events: HashMap<Event, Vec<fn(&mut Context, &mut Window)>>,
|
||||||
root: Box<dyn Widget>,
|
root: Option<Box<dyn Widget>>,
|
||||||
ctx: Rc<RefCell<Context>>,
|
ctx: Rc<RefCell<Context>>,
|
||||||
renderer: Renderer,
|
renderer: Option<Renderer>,
|
||||||
background: Color,
|
background: Color,
|
||||||
|
cursor_pos: (u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
@ -58,12 +59,13 @@ impl Window {
|
||||||
.build(event_loop)?;
|
.build(event_loop)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
renderer: Renderer::new(window.raw_window_handle()),
|
renderer: Some(Renderer::new(window.raw_window_handle())),
|
||||||
window,
|
window,
|
||||||
background,
|
background,
|
||||||
events,
|
events,
|
||||||
root,
|
root: Some(root),
|
||||||
ctx,
|
ctx,
|
||||||
|
cursor_pos: (0, 0),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,16 +74,14 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn render(&mut self) {
|
pub(crate) fn render(&mut self) {
|
||||||
let position = self.root.position(&mut self.renderer);
|
let root = self.root.as_ref().unwrap();
|
||||||
self.renderer.begin_draw();
|
let renderer = self.renderer.as_mut().unwrap();
|
||||||
self.renderer.clear(self.background);
|
let position = root.position(renderer);
|
||||||
self.renderer.position_at(position.x(), position.y());
|
renderer.begin_draw();
|
||||||
self.root.draw(&mut self.renderer);
|
renderer.clear(self.background);
|
||||||
self.renderer.end_draw()
|
renderer.position_at(position.x(), position.y());
|
||||||
}
|
root.draw(renderer);
|
||||||
|
renderer.end_draw()
|
||||||
pub fn set_always_on_top(&self, value: bool) {
|
|
||||||
self.window.set_always_on_top(value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus(&self) {
|
pub fn focus(&self) {
|
||||||
|
@ -92,6 +92,10 @@ impl Window {
|
||||||
self.window.request_redraw()
|
self.window.request_redraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_always_on_top(&self, value: bool) {
|
||||||
|
self.window.set_always_on_top(value)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_title<S: AsRef<str> + Into<String>>(&mut self, title: S) {
|
pub fn set_title<S: AsRef<str> + Into<String>>(&mut self, title: S) {
|
||||||
self.window.set_title(title.as_ref())
|
self.window.set_title(title.as_ref())
|
||||||
}
|
}
|
||||||
|
@ -109,12 +113,60 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn cursor_moved(&mut self, pos: PhysicalPosition<f64>) {
|
||||||
|
self.cursor_pos = (pos.x as u32, pos.y as u32)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn id(&self) -> WindowId {
|
pub(crate) fn id(&self) -> WindowId {
|
||||||
self.window.id()
|
self.window.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mouse_pressed(&mut self, button: MouseButton) {
|
||||||
|
if self.root
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.position(self.renderer.as_mut().unwrap())
|
||||||
|
.contains(self.cursor_pos.0, self.cursor_pos.1)
|
||||||
|
{
|
||||||
|
let mut root = self.root.take().unwrap();
|
||||||
|
let mut renderer = self.renderer.take().unwrap();
|
||||||
|
root.mouse_pressed(
|
||||||
|
&mut renderer,
|
||||||
|
self,
|
||||||
|
button,
|
||||||
|
self.cursor_pos.0,
|
||||||
|
self.cursor_pos.1,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.root = Some(root);
|
||||||
|
self.renderer = Some(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mouse_released(&mut self, button: MouseButton) {
|
||||||
|
if self.root
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.position(self.renderer.as_mut().unwrap())
|
||||||
|
.contains(self.cursor_pos.0, self.cursor_pos.1)
|
||||||
|
{
|
||||||
|
let mut root = self.root.take().unwrap();
|
||||||
|
let mut renderer = self.renderer.take().unwrap();
|
||||||
|
root.mouse_released(
|
||||||
|
&mut renderer,
|
||||||
|
self,
|
||||||
|
button,
|
||||||
|
self.cursor_pos.0,
|
||||||
|
self.cursor_pos.1,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.root = Some(root);
|
||||||
|
self.renderer = Some(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn resized(&mut self, size: PhysicalSize<u32>) {
|
pub(crate) fn resized(&mut self, size: PhysicalSize<u32>) {
|
||||||
self.renderer.resized(size.width, size.height);
|
self.renderer.as_mut().unwrap().resized(size.width, size.height);
|
||||||
self.emit_event(Event::Resized)
|
self.emit_event(Event::Resized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue