start work on early layout stuff

This layout stuff works by letting widgets calculate their bounding
boxes, which will be used to position the rest of the widgets. Currently
only used to position labels.
This commit is contained in:
TheOddGarlic 2022-04-22 20:00:03 +03:00
parent 86cdd411a4
commit 889aef5cdc
8 changed files with 88 additions and 15 deletions

View file

@ -20,6 +20,8 @@ use abletk_direct2d as backend;
pub struct Renderer { pub struct Renderer {
renderer: backend::Renderer, renderer: backend::Renderer,
x: u32,
y: u32,
} }
impl Renderer { impl Renderer {
@ -30,7 +32,9 @@ impl Renderer {
}; };
Self { Self {
renderer: backend::Renderer::new(handle) renderer: backend::Renderer::new(handle),
x: 0,
y: 0,
} }
} }
@ -43,7 +47,18 @@ impl Renderer {
} }
pub fn draw_text<S: AsRef<str>>(&self, text: S) { pub fn draw_text<S: AsRef<str>>(&self, text: S) {
self.renderer.draw_text(text.as_ref()) eprintln!("drawing text at ({}, {})", self.x, self.y);
self.renderer.draw_text(
text.as_ref(),
Rect {
left: self.x as f32,
top: self.y as f32,
// these two need to be as big as possible to make sure that
// text is not cut off or wrapped
right: f32::INFINITY,
bottom: f32::INFINITY,
}
)
} }
pub fn end_draw(&self) { pub fn end_draw(&self) {
@ -54,6 +69,11 @@ impl Renderer {
self.renderer.fill_rect(rect) self.renderer.fill_rect(rect)
} }
pub fn position_at(&mut self, x: u32, y: u32) {
self.x = x;
self.y = y
}
pub fn resized(&mut self, width: u32, height: u32) { pub fn resized(&mut self, width: u32, height: u32) {
self.renderer.resized(width, height) self.renderer.resized(width, height)
} }

View file

@ -61,21 +61,15 @@ impl Renderer {
unsafe { self.target.as_ref().unwrap().Clear(&color.into()) } unsafe { self.target.as_ref().unwrap().Clear(&color.into()) }
} }
pub fn draw_text(&self, text: &str) { pub fn draw_text<R: Into<D2D_RECT_F>>(&self, text: &str, layoutrect: R) {
unsafe { unsafe {
self.target.as_ref().unwrap().DrawText( self.target.as_ref().unwrap().DrawText(
// fixme: make this not hacky // fixme: make this not hacky
&text.as_bytes().iter().map(|b| *b as u16).collect::<Vec<_>>(), &text.as_bytes().iter().map(|b| *b as u16).collect::<Vec<_>>(),
&self.text_format, &self.text_format,
// fixme: unhardcode this (needs layout stuff probably) &layoutrect.into(),
&D2D_RECT_F {
left: 0.0,
top: 0.0,
right: 100.0,
bottom: 100.0,
},
self.brush.as_ref().unwrap(), self.brush.as_ref().unwrap(),
D2D1_DRAW_TEXT_OPTIONS_NONE, D2D1_DRAW_TEXT_OPTIONS_NO_SNAP,
DWRITE_MEASURING_MODE_NATURAL, DWRITE_MEASURING_MODE_NATURAL,
); );
} }
@ -196,7 +190,7 @@ fn create_text_format(factory: &IDWriteFactory, fonts: &IDWriteFontCollection)
-> IDWriteTextFormat -> IDWriteTextFormat
{ {
unsafe { unsafe {
factory.CreateTextFormat( let format = factory.CreateTextFormat(
"Arial", "Arial",
fonts, fonts,
DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_WEIGHT_NORMAL,
@ -204,6 +198,8 @@ fn create_text_format(factory: &IDWriteFactory, fonts: &IDWriteFontCollection)
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
10.0 * 96.0 / 72.0, 10.0 * 96.0 / 72.0,
"en-US", "en-US",
).unwrap() ).unwrap();
format.SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP).unwrap();
format
} }
} }

9
src/layout/mod.rs Executable file
View file

@ -0,0 +1,9 @@
/*
* 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/.
*/
pub mod position;

37
src/layout/position.rs Executable file
View file

@ -0,0 +1,37 @@
/*
* 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/.
*/
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Position {
x: u32,
y: u32,
width: u32,
height: u32,
}
impl Position {
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
Position { x, y, width, height }
}
pub fn x(&self) -> u32 {
self.x
}
pub fn y(&self) -> u32 {
self.y
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
}

View file

@ -12,6 +12,7 @@ pub use abletk_common::color;
pub mod application; pub mod application;
pub mod context; pub mod context;
pub mod event; pub mod event;
pub mod layout;
pub mod platform; pub mod platform;
pub mod plugin; pub mod plugin;
pub mod widget; pub mod widget;

View file

@ -7,7 +7,7 @@
*/ */
use abletk_common::{Renderer, brush::Brush, color::Color}; use abletk_common::{Renderer, brush::Brush, color::Color};
use crate::widget::Widget; use crate::{widget::Widget, layout::position::Position};
pub struct Label { pub struct Label {
text: String, text: String,
@ -17,7 +17,11 @@ pub struct Label {
impl Widget for Label { impl Widget for Label {
fn draw(&self, renderer: &mut Renderer) { fn draw(&self, renderer: &mut Renderer) {
renderer.set_brush(Brush::Solid(self.color)); renderer.set_brush(Brush::Solid(self.color));
renderer.draw_text(&self.text) renderer.draw_text(&self.text);
}
fn position(&self) -> Position {
Position::new(100, 0, 0, 0)
} }
} }

View file

@ -11,6 +11,9 @@ mod label;
use abletk_common::Renderer; use abletk_common::Renderer;
pub use label::*; pub use label::*;
use crate::layout::position::Position;
pub trait Widget { pub trait Widget {
fn draw(&self, renderer: &mut Renderer); fn draw(&self, renderer: &mut Renderer);
fn position(&self) -> Position;
} }

View file

@ -72,10 +72,13 @@ impl Window {
} }
pub fn render(&mut self) { pub fn render(&mut self) {
let position = self.root.position();
eprintln!("Rendering window with id {:?}", self.id()); eprintln!("Rendering window with id {:?}", self.id());
eprintln!("Root widget position: {position:?}");
self.renderer.begin_draw(); self.renderer.begin_draw();
self.renderer.clear(self.background); self.renderer.clear(self.background);
self.renderer.position_at(position.x(), position.y());
self.root.draw(&mut self.renderer); self.root.draw(&mut self.renderer);
self.renderer.end_draw() self.renderer.end_draw()
} }