Skip to content

Commit

Permalink
Triple whammy to fix button alignment — I think this is good enough
Browse files Browse the repository at this point in the history
  • Loading branch information
LPGhatguy committed Nov 21, 2024
1 parent 8ad7dd2 commit 0fbee87
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 12 deletions.
8 changes: 7 additions & 1 deletion crates/yakui-widgets/src/widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,17 @@ impl Widget for ButtonWidget {
text_style = style.text.clone();
}

let align = match text_style.align {
TextAlignment::Start => Alignment::CENTER_LEFT,
TextAlignment::Center => Alignment::CENTER,
TextAlignment::End => Alignment::CENTER_RIGHT,
};

let mut container = RoundRect::new(self.props.border_radius);
container.color = color;
container.show_children(|| {
crate::pad(self.props.padding, || {
crate::align(Alignment::CENTER_LEFT, || {
crate::align(align, || {
RenderText::with_style(self.props.text.clone(), text_style).show();
});
});
Expand Down
45 changes: 34 additions & 11 deletions crates/yakui-widgets/src/widgets/render_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use yakui_core::widget::{LayoutContext, PaintContext, Widget};
use yakui_core::{Response, TextureId};

use crate::font::Fonts;
use crate::style::TextStyle;
use crate::style::{TextAlignment, TextStyle};
use crate::text_renderer::{GlyphRender, Kind, TextGlobalState};
use crate::util::widget;

Expand Down Expand Up @@ -59,6 +59,7 @@ impl RenderText {
pub struct RenderTextWidget {
props: RenderText,
buffer: RefCell<Option<cosmic_text::Buffer>>,
line_offsets: RefCell<Vec<f32>>,
size: Cell<Option<Vec2>>,
last_text: RefCell<String>,
max_size: Cell<Option<(Option<f32>, Option<f32>)>>,
Expand All @@ -75,6 +76,7 @@ impl Widget for RenderTextWidget {
Self {
props: RenderText::new(""),
buffer: RefCell::default(),
line_offsets: RefCell::default(),
size: Cell::default(),
last_text: RefCell::new(String::new()),
max_size: Cell::default(),
Expand Down Expand Up @@ -157,23 +159,43 @@ impl Widget for RenderTextWidget {

buffer.shape_until_scroll(font_system, true);

let size = {
let size_x = buffer
.layout_runs()
.map(|layout| layout.line_w)
.max_by(|a, b| a.total_cmp(b))
.unwrap_or_default()
.ceil();
let mut line_offsets = self.line_offsets.borrow_mut();
line_offsets.clear();

let widest_line = buffer
.layout_runs()
.map(|layout| layout.line_w)
.max_by(|a, b| a.total_cmp(b))
.unwrap_or_default()
.ceil()
.max(constraints.min.x * ctx.layout.scale_factor());

for run in buffer.layout_runs() {
let offset = match self.props.style.align {
TextAlignment::Start => 0.0,
TextAlignment::Center => (widest_line - run.line_w) / 2.0,
TextAlignment::End => widest_line - run.line_w,
};

line_offsets.push(offset / ctx.layout.scale_factor());
}

let mut size = {
let size_y = buffer
.layout_runs()
.map(|layout| layout.line_height)
.sum::<f32>()
.ceil();

(Vec2::new(size_x, size_y) / ctx.layout.scale_factor()).round()
(Vec2::new(widest_line, size_y) / ctx.layout.scale_factor()).round()
};

size.x = size.x.max(constraints.min.x);

if constraints.max.x.is_finite() {
size.x = size.x.max(constraints.max.x);
}

let size = constraints.constrain(size);
self.size.set(Some(size));

Expand All @@ -191,17 +213,18 @@ impl Widget for RenderTextWidget {
};

fonts.with_system(|font_system| {
let line_offsets = self.line_offsets.borrow();
let text_global = ctx.dom.get_global_or_init(TextGlobalState::new);

for layout in buffer.layout_runs() {
for (layout, x_offset) in buffer.layout_runs().zip(line_offsets.iter().copied()) {
for glyph in layout.glyphs {
if let Some(render) = text_global.get_or_insert(ctx.paint, font_system, glyph) {
paint_text(
&mut ctx,
self.props.style.color,
glyph,
render,
layout_node.rect.pos(),
layout_node.rect.pos() + Vec2::new(x_offset, 0.0),
layout.line_y,
)
}
Expand Down
40 changes: 40 additions & 0 deletions crates/yakui/examples/button_constrained.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use yakui::style::TextAlignment;
use yakui::widgets::{Button, List};
use yakui::{constrained, Constraints, CrossAxisAlignment, Vec2};

pub fn run() {
const ALIGNMENTS: &[TextAlignment] = &[
TextAlignment::Start,
TextAlignment::Center,
TextAlignment::End,
];

let mut list = List::row();
list.cross_axis_alignment = CrossAxisAlignment::End;
list.item_spacing = 16.0;
list.show(|| {
for &alignment in ALIGNMENTS {
menu_button(alignment);
}
});
}

fn menu_button(alignment: TextAlignment) {
let constraints = Constraints {
min: Vec2::new(120.0, 0.0),
max: Vec2::new(f32::INFINITY, f32::INFINITY),
};

constrained(constraints, || {
let mut button = Button::styled(format!("Foo ({alignment:?})"));
button.style.text.font_size = 12.0;
button.style.text.align = alignment;
button.hover_style.text.align = alignment;
button.down_style.text.align = alignment;
button.show();
});
}

fn main() {
bootstrap::start(run as fn());
}

0 comments on commit 0fbee87

Please sign in to comment.