Center window titles
This commit is contained in:
parent
430fcd9e91
commit
e079ac5b46
|
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
### Changed 🔧
|
||||
|
||||
* Center window titles.
|
||||
* Tweak size and alignment of some emojis to match other text.
|
||||
|
||||
### Fixed 🐛
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//! One- and two-dimensional alignment ([`Align::Center`], [`LEFT_TOP`] etc).
|
||||
|
||||
use crate::math::{pos2, Rect};
|
||||
use crate::math::*;
|
||||
|
||||
/// left/center/right or top/center/bottom alignment for e.g. anchors and `Layout`s.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
|
@ -77,3 +77,23 @@ pub(crate) fn anchor_rect(rect: Rect, anchor: (Align, Align)) -> Rect {
|
|||
};
|
||||
Rect::from_min_size(pos2(x, y), rect.size())
|
||||
}
|
||||
|
||||
/// e.g. center a size within a given frame
|
||||
pub fn align_size_within_rect(align: (Align, Align), size: Vec2, frame: Rect) -> Rect {
|
||||
let x = match align.0 {
|
||||
Align::Min => frame.left(),
|
||||
Align::Center => frame.center().x - size.x / 2.0,
|
||||
Align::Max => frame.right() - size.x,
|
||||
};
|
||||
let y = match align.1 {
|
||||
Align::Min => frame.top(),
|
||||
Align::Center => frame.center().y - size.y / 2.0,
|
||||
Align::Max => frame.bottom() - size.y,
|
||||
};
|
||||
|
||||
Rect::from_min_size(Pos2::new(x, y), size)
|
||||
}
|
||||
|
||||
pub fn center_size_in_rect(size: Vec2, frame: Rect) -> Rect {
|
||||
align_size_within_rect(CENTER_CENTER, size, frame)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -632,7 +632,7 @@ struct TitleBar {
|
|||
id: Id,
|
||||
title_label: Label,
|
||||
title_galley: Galley,
|
||||
title_rect: Rect,
|
||||
min_rect: Rect,
|
||||
rect: Rect,
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +645,8 @@ fn show_title_bar(
|
|||
collapsible: bool,
|
||||
) -> TitleBar {
|
||||
let (title_bar, response) = ui.horizontal(|ui| {
|
||||
ui.set_min_height(title_label.font_height(ui.fonts(), ui.style()));
|
||||
let height = title_label.font_height(ui.fonts(), ui.style());
|
||||
ui.set_min_height(height);
|
||||
|
||||
let item_spacing = ui.style().spacing.item_spacing;
|
||||
let button_size = ui.style().spacing.icon_width;
|
||||
|
|
@ -663,27 +664,22 @@ fn show_title_bar(
|
|||
}
|
||||
|
||||
let title_galley = title_label.layout(ui);
|
||||
let (id, title_rect) = ui.allocate_space(title_galley.size);
|
||||
|
||||
if show_close_button {
|
||||
// Reserve space for close button which will be added later (once we know our full width):
|
||||
let close_max_x = title_rect.right() + item_spacing.x + button_size + item_spacing.x;
|
||||
let close_max_x = close_max_x.max(ui.max_rect_finite().right());
|
||||
let close_rect = Rect::from_min_size(
|
||||
pos2(
|
||||
close_max_x - button_size,
|
||||
title_rect.center().y - 0.5 * button_size,
|
||||
),
|
||||
Vec2::splat(button_size),
|
||||
);
|
||||
ui.expand_to_include_rect(close_rect);
|
||||
}
|
||||
let minimum_width = if collapsible || show_close_button {
|
||||
// If at least one button is shown we make room for both buttons (since title is centered)
|
||||
let space_x = item_spacing.x;
|
||||
space_x + button_size + space_x + title_galley.size.x + space_x + button_size + space_x
|
||||
} else {
|
||||
item_spacing.x + title_galley.size.x + item_spacing.x
|
||||
};
|
||||
let min_rect = Rect::from_min_size(ui.min_rect().min, vec2(minimum_width, height));
|
||||
let id = ui.advance_cursor_after_rect(min_rect);
|
||||
|
||||
TitleBar {
|
||||
id,
|
||||
title_label,
|
||||
title_galley,
|
||||
title_rect,
|
||||
min_rect,
|
||||
rect: Rect::invalid(), // Will be filled in later
|
||||
}
|
||||
});
|
||||
|
|
@ -716,9 +712,18 @@ impl TitleBar {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: pick style for title based on move interaction
|
||||
let style = if ui.ui_contains_mouse() {
|
||||
ui.style().visuals.widgets.hovered
|
||||
} else {
|
||||
ui.style().visuals.widgets.inactive
|
||||
};
|
||||
self.title_label = self.title_label.text_color(style.fg_stroke.color);
|
||||
|
||||
let full_top_rect = Rect::from_x_y_ranges(self.rect.x_range(), self.min_rect.y_range());
|
||||
let text_pos = align::center_size_in_rect(self.title_galley.size, full_top_rect);
|
||||
let text_pos = text_pos.left_top() - 2.0 * Vec2::Y; // HACK: center on x-height of text (looks better)
|
||||
self.title_label
|
||||
.paint_galley(ui, self.title_rect.min, self.title_galley);
|
||||
.paint_galley(ui, text_pos, self.title_galley);
|
||||
|
||||
if let Some(content_response) = &content_response {
|
||||
// paint separator between title and content:
|
||||
|
|
@ -760,6 +765,8 @@ fn close_button(ui: &mut Ui, rect: Rect) -> Response {
|
|||
let response = ui.interact(rect, close_id, Sense::click());
|
||||
ui.expand_to_include_rect(response.rect);
|
||||
|
||||
let rect = rect.shrink(2.0);
|
||||
|
||||
let stroke = ui.style().interact(&response).fg_stroke;
|
||||
ui.painter()
|
||||
.line_segment([rect.left_top(), rect.right_bottom()], stroke);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ impl Rect {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_x_y_ranges(x_range: RangeInclusive<f32>, y_range: RangeInclusive<f32>) -> Self {
|
||||
Rect {
|
||||
min: pos2(*x_range.start(), *y_range.start()),
|
||||
max: pos2(*x_range.end(), *y_range.end()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand by this much in each direction, keeping the center
|
||||
#[must_use]
|
||||
pub fn expand(self, amnt: f32) -> Self {
|
||||
|
|
|
|||
Loading…
Reference in New Issue