Compare commits

...

2 Commits

Author SHA1 Message Date
TheOddGarlic f491fce00b text size calculation and very primitive row layout 2022-04-26 19:20:57 +03:00
TheOddGarlic f0d752570b refactor things around 2022-04-24 18:59:48 +03:00
9 changed files with 101 additions and 16 deletions

View File

@ -34,17 +34,15 @@ impl From<Color> for D2D1_COLOR_F {
}
}
// fixme: figure out how to tell RGB, RGBA, HSL, HSLA, any of those in
// hexadecimal numbers, etc. apart.
#[macro_export]
macro_rules! color {
macro_rules! rgb {
($r:expr, $g:expr, $b:expr, $a:expr) => {
$crate::color::Color($r, $g, $b, $a)
};
($r:expr, $g:expr, $b:expr) => {
$crate::color::Color($r, $g, $b, 1.0)
};
// ($rgba:expr) => {
// $crate::color::Color::from_rgba($rgba)
// };
($rgba:expr) => {
$crate::color::Color::from_rgba($rgba)
};
}

View File

@ -69,6 +69,14 @@ impl Renderer {
self.renderer.fill_rect(rect)
}
pub fn get_text_size(&self, text: &str) -> (u32, u32) {
self.renderer.get_text_size(text)
}
pub fn position(&self) -> (u32, u32) {
(self.x, self.y)
}
pub fn position_at(&mut self, x: u32, y: u32) {
self.x = x;
self.y = y

View File

@ -91,6 +91,21 @@ impl Renderer {
}
}
pub fn get_text_size(&self, text: &str) -> (u32, u32) {
let metrics = unsafe {
let layout = self.dw_factory.CreateTextLayout(
// fixme: make this not hacky
&text.as_bytes().iter().map(|b| *b as u16).collect::<Vec<_>>(),
&self.text_format,
f32::INFINITY,
f32::INFINITY,
).unwrap();
layout.GetMetrics().unwrap()
};
(metrics.widthIncludingTrailingWhitespace as u32, metrics.height as u32)
}
pub fn resized(&mut self, width: u32, height: u32) {
unsafe {
if let Some(target) = self.target.as_ref() {

View File

@ -8,7 +8,7 @@
//! Able GUI Toolkit (AbleTK)
#[doc(inline)] pub use abletk_macros::*;
pub use abletk_common::color;
pub use abletk_common::*;
pub mod application;
pub mod context;
pub mod event;
@ -24,8 +24,9 @@ pub mod prelude {
pub use crate::event::window::Event as WindowEvent;
pub use crate::platform::Platform;
pub use crate::widget::Label;
pub use crate::widget::Row;
pub use crate::widget::Widget;
pub use crate::window::*;
pub use crate::color;
pub use crate::rgb;
pub use crate::launch;
}

View File

@ -14,6 +14,9 @@ fn launch() -> _ {
Application::new()
.apply_plugin(QuitPlugin)
.add_window(Window::builder(
Label::new("Hello, AbleTK!")
.color(color!(0xFF00FFFF))))
Row::new()
.add(Label::new("Hello, AbleTK! ")
.color(rgb!(0xFF00FFFF)))
.add(Label::new("Hello, World!")
.color(rgb!(0x64CAFEFF)))))
}

View File

@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
use abletk_common::{Renderer, brush::Brush, color::Color};
use abletk_common::{Renderer, brush::Brush, color::Color, rgb};
use crate::{widget::Widget, layout::position::Position};
pub struct Label {
@ -20,8 +20,9 @@ impl Widget for Label {
renderer.draw_text(&self.text);
}
fn position(&self) -> Position {
Position::new(100, 0, 0, 0)
fn position(&self, renderer: &mut Renderer) -> Position {
let (width, height) = renderer.get_text_size(&self.text);
Position::new(0, 0, width, height)
}
}
@ -29,7 +30,7 @@ impl Label {
pub fn new<S: Into<String>>(text: S) -> Self {
Self {
text: text.into(),
color: Color(1.0, 1.0, 1.0, 1.0),
color: rgb!(0xFFFFFFFF),
}
}

View File

@ -7,13 +7,16 @@
*/
mod label;
mod row;
use abletk_common::Renderer;
pub use label::*;
pub use row::*;
use crate::layout::position::Position;
pub trait Widget {
fn draw(&self, renderer: &mut Renderer);
fn position(&self) -> Position;
// fixme: don't pass renderer
fn position(&self, renderer: &mut Renderer) -> Position;
}

56
src/widget/row.rs Executable file
View File

@ -0,0 +1,56 @@
/*
* 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};
use abletk_common::Renderer;
pub struct Row {
widgets: Vec<Box<dyn Widget>>,
}
impl Widget for Row {
fn draw(&self, renderer: &mut Renderer) {
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
);
});
}
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)
}
}
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
}
}

View File

@ -72,7 +72,7 @@ impl Window {
}
pub fn render(&mut self) {
let position = self.root.position();
let position = self.root.position(&mut self.renderer);
eprintln!("Rendering window with id {:?}", self.id());
eprintln!("Root widget position: {position:?}");