From 889aef5cdc68a40f8acd7859776375ecb027bb85 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Fri, 22 Apr 2022 20:00:03 +0300 Subject: [PATCH] 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. --- abletk-common/src/lib.rs | 24 ++++++++++++++++++++++-- abletk-direct2d/src/lib.rs | 18 +++++++----------- src/layout/mod.rs | 9 +++++++++ src/layout/position.rs | 37 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/widget/label.rs | 8 ++++++-- src/widget/mod.rs | 3 +++ src/window.rs | 3 +++ 8 files changed, 88 insertions(+), 15 deletions(-) create mode 100755 src/layout/mod.rs create mode 100755 src/layout/position.rs diff --git a/abletk-common/src/lib.rs b/abletk-common/src/lib.rs index d922eda..eae8dc0 100755 --- a/abletk-common/src/lib.rs +++ b/abletk-common/src/lib.rs @@ -20,6 +20,8 @@ use abletk_direct2d as backend; pub struct Renderer { renderer: backend::Renderer, + x: u32, + y: u32, } impl Renderer { @@ -30,7 +32,9 @@ impl Renderer { }; 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>(&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) { @@ -54,6 +69,11 @@ impl Renderer { 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) { self.renderer.resized(width, height) } diff --git a/abletk-direct2d/src/lib.rs b/abletk-direct2d/src/lib.rs index 46ea8ec..f2eeaf6 100755 --- a/abletk-direct2d/src/lib.rs +++ b/abletk-direct2d/src/lib.rs @@ -61,21 +61,15 @@ impl Renderer { unsafe { self.target.as_ref().unwrap().Clear(&color.into()) } } - pub fn draw_text(&self, text: &str) { + pub fn draw_text>(&self, text: &str, layoutrect: R) { unsafe { self.target.as_ref().unwrap().DrawText( // fixme: make this not hacky &text.as_bytes().iter().map(|b| *b as u16).collect::>(), &self.text_format, - // fixme: unhardcode this (needs layout stuff probably) - &D2D_RECT_F { - left: 0.0, - top: 0.0, - right: 100.0, - bottom: 100.0, - }, + &layoutrect.into(), self.brush.as_ref().unwrap(), - D2D1_DRAW_TEXT_OPTIONS_NONE, + D2D1_DRAW_TEXT_OPTIONS_NO_SNAP, DWRITE_MEASURING_MODE_NATURAL, ); } @@ -196,7 +190,7 @@ fn create_text_format(factory: &IDWriteFactory, fonts: &IDWriteFontCollection) -> IDWriteTextFormat { unsafe { - factory.CreateTextFormat( + let format = factory.CreateTextFormat( "Arial", fonts, DWRITE_FONT_WEIGHT_NORMAL, @@ -204,6 +198,8 @@ fn create_text_format(factory: &IDWriteFactory, fonts: &IDWriteFontCollection) DWRITE_FONT_STRETCH_NORMAL, 10.0 * 96.0 / 72.0, "en-US", - ).unwrap() + ).unwrap(); + format.SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP).unwrap(); + format } } diff --git a/src/layout/mod.rs b/src/layout/mod.rs new file mode 100755 index 0000000..86ffcc1 --- /dev/null +++ b/src/layout/mod.rs @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2022 Umut İnan Erdoğan + * + * 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; diff --git a/src/layout/position.rs b/src/layout/position.rs new file mode 100755 index 0000000..90442d3 --- /dev/null +++ b/src/layout/position.rs @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 Umut İnan Erdoğan + * + * 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 + } +} diff --git a/src/lib.rs b/src/lib.rs index fdd8cc9..6647afd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub use abletk_common::color; pub mod application; pub mod context; pub mod event; +pub mod layout; pub mod platform; pub mod plugin; pub mod widget; diff --git a/src/widget/label.rs b/src/widget/label.rs index 0bf6663..ee8d31c 100755 --- a/src/widget/label.rs +++ b/src/widget/label.rs @@ -7,7 +7,7 @@ */ use abletk_common::{Renderer, brush::Brush, color::Color}; -use crate::widget::Widget; +use crate::{widget::Widget, layout::position::Position}; pub struct Label { text: String, @@ -17,7 +17,11 @@ pub struct Label { impl Widget for Label { fn draw(&self, renderer: &mut Renderer) { 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) } } diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 5f1a3be..ada1dcd 100755 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -11,6 +11,9 @@ mod label; use abletk_common::Renderer; pub use label::*; +use crate::layout::position::Position; + pub trait Widget { fn draw(&self, renderer: &mut Renderer); + fn position(&self) -> Position; } diff --git a/src/window.rs b/src/window.rs index c081874..9af57b9 100755 --- a/src/window.rs +++ b/src/window.rs @@ -72,10 +72,13 @@ impl Window { } pub fn render(&mut self) { + let position = self.root.position(); eprintln!("Rendering window with id {:?}", self.id()); + eprintln!("Root widget position: {position:?}"); self.renderer.begin_draw(); self.renderer.clear(self.background); + self.renderer.position_at(position.x(), position.y()); self.root.draw(&mut self.renderer); self.renderer.end_draw() }