Improve text layout
This commit is contained in:
parent
a4fc56b441
commit
1c6fd220b2
7 changed files with 80 additions and 134 deletions
Binary file not shown.
|
@ -63,8 +63,7 @@ function paint_command(canvas, cmd) {
|
||||||
case "text":
|
case "text":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
||||||
ctx.font = cmd.font_size + "px " + cmd.font_name;
|
ctx.font = cmd.font_size + "px " + cmd.font_name;
|
||||||
ctx.textAlign = cmd.text_align;
|
ctx.textBaseline = "middle";
|
||||||
ctx.textBaseline = "top";
|
|
||||||
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,6 @@ interface Text {
|
||||||
pos: Vec2;
|
pos: Vec2;
|
||||||
stroke_color: Color | null;
|
stroke_color: Color | null;
|
||||||
text: string;
|
text: string;
|
||||||
text_align: "start" | "center" | "end";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaintCmd = Circle | Clear | Line | Rect | Text;
|
type PaintCmd = Circle | Clear | Line | Rect | Text;
|
||||||
|
@ -132,8 +131,7 @@ function paint_command(canvas, cmd: PaintCmd) {
|
||||||
case "text":
|
case "text":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
||||||
ctx.font = `${cmd.font_size}px ${cmd.font_name}`;
|
ctx.font = `${cmd.font_size}px ${cmd.font_name}`;
|
||||||
ctx.textAlign = cmd.text_align;
|
ctx.textBaseline = "middle";
|
||||||
ctx.textBaseline = "top";
|
|
||||||
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
17
src/app.rs
17
src/app.rs
|
@ -56,7 +56,7 @@ impl GuiSettings for App {
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.label(format!("The button have been clicked {} times", self.count));
|
gui.label(format!("This is a multiline label.\nThe button have been clicked {} times.\nBelow are more options.", self.count));
|
||||||
|
|
||||||
gui.foldable("Box rendering options", |gui| {
|
gui.foldable("Box rendering options", |gui| {
|
||||||
gui.slider_f32("width", &mut self.width, 0.0, 500.0);
|
gui.slider_f32("width", &mut self.width, 0.0, 500.0);
|
||||||
|
@ -78,9 +78,9 @@ impl GuiSettings for App {
|
||||||
}]));
|
}]));
|
||||||
|
|
||||||
gui.foldable("LayoutOptions", |gui| {
|
gui.foldable("LayoutOptions", |gui| {
|
||||||
let mut layout_options = gui.layout_options;
|
let mut options = gui.options;
|
||||||
layout_options.show_gui(gui);
|
options.show_gui(gui);
|
||||||
gui.layout_options = layout_options;
|
gui.options = options;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,16 +94,11 @@ impl GuiSettings for crate::layout::LayoutOptions {
|
||||||
gui.slider_f32("char_size.y", &mut self.char_size.y, 0.0, 20.0);
|
gui.slider_f32("char_size.y", &mut self.char_size.y, 0.0, 20.0);
|
||||||
gui.slider_f32("item_spacing.x", &mut self.item_spacing.x, 0.0, 10.0);
|
gui.slider_f32("item_spacing.x", &mut self.item_spacing.x, 0.0, 10.0);
|
||||||
gui.slider_f32("item_spacing.y", &mut self.item_spacing.y, 0.0, 10.0);
|
gui.slider_f32("item_spacing.y", &mut self.item_spacing.y, 0.0, 10.0);
|
||||||
|
gui.slider_f32("indent", &mut self.indent, 0.0, 100.0);
|
||||||
gui.slider_f32("width", &mut self.width, 0.0, 1000.0);
|
gui.slider_f32("width", &mut self.width, 0.0, 1000.0);
|
||||||
gui.slider_f32("button_padding.x", &mut self.button_padding.x, 0.0, 20.0);
|
gui.slider_f32("button_padding.x", &mut self.button_padding.x, 0.0, 20.0);
|
||||||
gui.slider_f32("button_padding.y", &mut self.button_padding.y, 0.0, 20.0);
|
gui.slider_f32("button_padding.y", &mut self.button_padding.y, 0.0, 20.0);
|
||||||
gui.slider_f32(
|
gui.slider_f32("start_icon_width", &mut self.start_icon_width, 0.0, 60.0);
|
||||||
"checkbox_radio_height",
|
|
||||||
&mut self.checkbox_radio_height,
|
|
||||||
0.0,
|
|
||||||
60.0,
|
|
||||||
);
|
|
||||||
gui.slider_f32("slider_height", &mut self.slider_height, 0.0, 60.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
105
src/layout.rs
105
src/layout.rs
|
@ -22,23 +22,20 @@ pub struct LayoutOptions {
|
||||||
/// Button size is text size plus this on each side
|
/// Button size is text size plus this on each side
|
||||||
pub button_padding: Vec2,
|
pub button_padding: Vec2,
|
||||||
|
|
||||||
/// Height of a checkbox and radio button
|
/// Checkboxed, radio button and foldables have an icon at the start.
|
||||||
pub checkbox_radio_height: f32,
|
/// The text starts after this many pixels.
|
||||||
|
pub start_icon_width: f32,
|
||||||
/// Height of a slider
|
|
||||||
pub slider_height: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LayoutOptions {
|
impl Default for LayoutOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
LayoutOptions {
|
LayoutOptions {
|
||||||
char_size: vec2(7.2, 14.0),
|
char_size: vec2(7.2, 14.0),
|
||||||
item_spacing: vec2(5.0, 3.0),
|
item_spacing: vec2(8.0, 4.0),
|
||||||
indent: 21.0,
|
indent: 21.0,
|
||||||
width: 200.0,
|
width: 200.0,
|
||||||
button_padding: vec2(8.0, 8.0),
|
button_padding: vec2(5.0, 3.0),
|
||||||
checkbox_radio_height: 24.0,
|
start_icon_width: 20.0,
|
||||||
slider_height: 32.0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +66,7 @@ type Id = u64;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
pub layout_options: LayoutOptions,
|
pub options: LayoutOptions,
|
||||||
pub input: GuiInput,
|
pub input: GuiInput,
|
||||||
pub cursor: Vec2,
|
pub cursor: Vec2,
|
||||||
id: Id,
|
id: Id,
|
||||||
|
@ -92,23 +89,26 @@ impl Layout {
|
||||||
let text: String = text.into();
|
let text: String = text.into();
|
||||||
let id = self.get_id(&text);
|
let id = self.get_id(&text);
|
||||||
let (text, text_size) = self.layout_text(&text);
|
let (text, text_size) = self.layout_text(&text);
|
||||||
let text_cursor = self.cursor + self.layout_options.button_padding;
|
let text_cursor = self.cursor + self.options.button_padding;
|
||||||
let (rect, interact) =
|
let (rect, interact) =
|
||||||
self.reserve_space(id, text_size + 2.0 * self.layout_options.button_padding);
|
self.reserve_space(id, text_size + 2.0 * self.options.button_padding);
|
||||||
self.commands.push(GuiCmd::Button { interact, rect });
|
self.commands.push(GuiCmd::Button { interact, rect });
|
||||||
self.add_text(text_cursor, text);
|
self.add_text(text_cursor, text);
|
||||||
interact
|
interact
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkbox<S: Into<String>>(&mut self, label: S, checked: &mut bool) -> InteractInfo {
|
pub fn checkbox<S: Into<String>>(&mut self, text: S, checked: &mut bool) -> InteractInfo {
|
||||||
let label: String = label.into();
|
let text: String = text.into();
|
||||||
let id = self.get_id(&label);
|
let id = self.get_id(&text);
|
||||||
|
let (text, text_size) = self.layout_text(&text);
|
||||||
|
let text_cursor =
|
||||||
|
self.cursor + self.options.button_padding + vec2(self.options.start_icon_width, 0.0);
|
||||||
let (rect, interact) = self.reserve_space(
|
let (rect, interact) = self.reserve_space(
|
||||||
id,
|
id,
|
||||||
Vec2 {
|
self.options.button_padding
|
||||||
x: self.layout_options.width,
|
+ vec2(self.options.start_icon_width, 0.0)
|
||||||
y: self.layout_options.checkbox_radio_height,
|
+ text_size
|
||||||
},
|
+ self.options.button_padding,
|
||||||
);
|
);
|
||||||
if interact.clicked {
|
if interact.clicked {
|
||||||
*checked = !*checked;
|
*checked = !*checked;
|
||||||
|
@ -117,8 +117,8 @@ impl Layout {
|
||||||
checked: *checked,
|
checked: *checked,
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
text: label,
|
|
||||||
});
|
});
|
||||||
|
self.add_text(text_cursor, text);
|
||||||
interact
|
interact
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,57 +127,68 @@ impl Layout {
|
||||||
let (text, text_size) = self.layout_text(&text);
|
let (text, text_size) = self.layout_text(&text);
|
||||||
self.add_text(self.cursor, text);
|
self.add_text(self.cursor, text);
|
||||||
self.cursor.y += text_size.y;
|
self.cursor.y += text_size.y;
|
||||||
self.cursor.y += self.layout_options.item_spacing.y;
|
self.cursor.y += self.options.item_spacing.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A radio button
|
/// A radio button
|
||||||
pub fn radio<S: Into<String>>(&mut self, label: S, checked: bool) -> InteractInfo {
|
pub fn radio<S: Into<String>>(&mut self, text: S, checked: bool) -> InteractInfo {
|
||||||
let label: String = label.into();
|
let text: String = text.into();
|
||||||
let id = self.get_id(&label);
|
let id = self.get_id(&text);
|
||||||
|
let (text, text_size) = self.layout_text(&text);
|
||||||
|
let text_cursor =
|
||||||
|
self.cursor + self.options.button_padding + vec2(self.options.start_icon_width, 0.0);
|
||||||
let (rect, interact) = self.reserve_space(
|
let (rect, interact) = self.reserve_space(
|
||||||
id,
|
id,
|
||||||
Vec2 {
|
self.options.button_padding
|
||||||
x: self.layout_options.width,
|
+ vec2(self.options.start_icon_width, 0.0)
|
||||||
y: self.layout_options.checkbox_radio_height,
|
+ text_size
|
||||||
},
|
+ self.options.button_padding,
|
||||||
);
|
);
|
||||||
self.commands.push(GuiCmd::RadioButton {
|
self.commands.push(GuiCmd::RadioButton {
|
||||||
checked,
|
checked,
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
text: label,
|
|
||||||
});
|
});
|
||||||
|
self.add_text(text_cursor, text);
|
||||||
interact
|
interact
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slider_f32<S: Into<String>>(
|
pub fn slider_f32<S: Into<String>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: S,
|
text: S,
|
||||||
value: &mut f32,
|
value: &mut f32,
|
||||||
min: f32,
|
min: f32,
|
||||||
max: f32,
|
max: f32,
|
||||||
) -> InteractInfo {
|
) -> InteractInfo {
|
||||||
debug_assert!(min <= max);
|
debug_assert!(min <= max);
|
||||||
let label: String = label.into();
|
let text: String = text.into();
|
||||||
let id = self.get_id(&label);
|
let id = self.get_id(&text);
|
||||||
let (rect, interact) = self.reserve_space(
|
let (text, text_size) = self.layout_text(&format!("{}: {:.3}", text, value));
|
||||||
|
self.add_text(self.cursor, text);
|
||||||
|
self.cursor.y += text_size.y;
|
||||||
|
let (slider_rect, interact) = self.reserve_space(
|
||||||
id,
|
id,
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: self.layout_options.width,
|
x: self.options.width,
|
||||||
y: self.layout_options.slider_height,
|
y: self.options.char_size.y,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if interact.active {
|
if interact.active {
|
||||||
*value = remap_clamp(self.input.mouse_pos.x, rect.min().x, rect.max().x, min, max);
|
*value = remap_clamp(
|
||||||
|
self.input.mouse_pos.x,
|
||||||
|
slider_rect.min().x,
|
||||||
|
slider_rect.max().x,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.commands.push(GuiCmd::Slider {
|
self.commands.push(GuiCmd::Slider {
|
||||||
interact,
|
interact,
|
||||||
label,
|
|
||||||
max,
|
max,
|
||||||
min,
|
min,
|
||||||
rect,
|
rect: slider_rect,
|
||||||
value: *value,
|
value: *value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -195,12 +206,12 @@ impl Layout {
|
||||||
let text: String = text.into();
|
let text: String = text.into();
|
||||||
let id = self.get_id(&text);
|
let id = self.get_id(&text);
|
||||||
let (text, text_size) = self.layout_text(&text);
|
let (text, text_size) = self.layout_text(&text);
|
||||||
let text_cursor = self.cursor + self.layout_options.button_padding;
|
let text_cursor = self.cursor + self.options.button_padding;
|
||||||
let (rect, interact) = self.reserve_space(
|
let (rect, interact) = self.reserve_space(
|
||||||
id,
|
id,
|
||||||
vec2(
|
vec2(
|
||||||
self.layout_options.width,
|
self.options.width,
|
||||||
text_size.y + 2.0 * self.layout_options.button_padding.y,
|
text_size.y + 2.0 * self.options.button_padding.y,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -218,14 +229,13 @@ impl Layout {
|
||||||
rect,
|
rect,
|
||||||
open,
|
open,
|
||||||
});
|
});
|
||||||
let icon_width = 16.0; // TODO: this offset is ugly
|
self.add_text(text_cursor + vec2(self.options.start_icon_width, 0.0), text);
|
||||||
self.add_text(text_cursor + vec2(icon_width, 0.0), text);
|
|
||||||
|
|
||||||
if open {
|
if open {
|
||||||
let old_id = self.id;
|
let old_id = self.id;
|
||||||
self.id = id;
|
self.id = id;
|
||||||
let old_x = self.cursor.x;
|
let old_x = self.cursor.x;
|
||||||
self.cursor.x += self.layout_options.indent;
|
self.cursor.x += self.options.indent;
|
||||||
add_contents(self);
|
add_contents(self);
|
||||||
self.cursor.x = old_x;
|
self.cursor.x = old_x;
|
||||||
self.id = old_id;
|
self.id = old_id;
|
||||||
|
@ -242,7 +252,7 @@ impl Layout {
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
let interact = self.interactive_rect(id, &rect);
|
let interact = self.interactive_rect(id, &rect);
|
||||||
self.cursor.y += rect.size.y + self.layout_options.item_spacing.y;
|
self.cursor.y += rect.size.y + self.options.item_spacing.y;
|
||||||
(rect, interact)
|
(rect, interact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +280,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_text(&self, text: &str) -> (TextFragments, Vec2) {
|
fn layout_text(&self, text: &str) -> (TextFragments, Vec2) {
|
||||||
let char_size = self.layout_options.char_size;
|
let char_size = self.options.char_size;
|
||||||
let mut cursor_y = 0.0;
|
let mut cursor_y = 0.0;
|
||||||
let mut max_width = 0.0;
|
let mut max_width = 0.0;
|
||||||
let mut text_fragments = Vec::new();
|
let mut text_fragments = Vec::new();
|
||||||
|
@ -293,10 +303,9 @@ impl Layout {
|
||||||
fn add_text(&mut self, pos: Vec2, text: Vec<TextFragment>) {
|
fn add_text(&mut self, pos: Vec2, text: Vec<TextFragment>) {
|
||||||
for fragment in text {
|
for fragment in text {
|
||||||
self.commands.push(GuiCmd::Text {
|
self.commands.push(GuiCmd::Text {
|
||||||
pos: pos + fragment.rect.pos,
|
pos: pos + vec2(fragment.rect.pos.x, fragment.rect.center().y),
|
||||||
style: TextStyle::Label,
|
style: TextStyle::Label,
|
||||||
text: fragment.text,
|
text: fragment.text,
|
||||||
text_align: TextAlign::Start,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
66
src/style.rs
66
src/style.rs
|
@ -59,8 +59,8 @@ impl Style {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns small icon rectangle, big icon rectangle, and the remaining rectangle
|
/// Returns small icon rectangle and big icon rectangle
|
||||||
fn icon_rectangles(&self, rect: &Rect) -> (Rect, Rect, Rect) {
|
fn icon_rectangles(&self, rect: &Rect) -> (Rect, Rect) {
|
||||||
let box_side = 16.0;
|
let box_side = 16.0;
|
||||||
let big_icon_rect = Rect::from_center_size(
|
let big_icon_rect = Rect::from_center_size(
|
||||||
vec2(rect.min().x + 4.0 + box_side * 0.5, rect.center().y),
|
vec2(rect.min().x + 4.0 + box_side * 0.5, rect.center().y),
|
||||||
|
@ -69,10 +69,7 @@ impl Style {
|
||||||
|
|
||||||
let small_icon_rect = Rect::from_center_size(big_icon_rect.center(), vec2(10.0, 10.0));
|
let small_icon_rect = Rect::from_center_size(big_icon_rect.center(), vec2(10.0, 10.0));
|
||||||
|
|
||||||
let rest_rect =
|
(small_icon_rect, big_icon_rect)
|
||||||
Rect::from_min_size(vec2(big_icon_rect.max().x + 4.0, rect.min().y), rect.size);
|
|
||||||
|
|
||||||
(small_icon_rect, big_icon_rect, rest_rect)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,9 +106,8 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
checked,
|
checked,
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
text,
|
|
||||||
} => {
|
} => {
|
||||||
let (small_icon_rect, big_icon_rect, rest_rect) = style.icon_rectangles(&rect);
|
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&rect);
|
||||||
out_commands.push(PaintCmd::Rect {
|
out_commands.push(PaintCmd::Rect {
|
||||||
corner_radius: 3.0,
|
corner_radius: 3.0,
|
||||||
fill_color: Some(style.interact_fill_color(&interact)),
|
fill_color: Some(style.interact_fill_color(&interact)),
|
||||||
|
@ -134,18 +130,6 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
out_commands.push(PaintCmd::Text {
|
|
||||||
fill_color: stroke_color,
|
|
||||||
font_name: style.font_name.clone(),
|
|
||||||
font_size: style.font_size,
|
|
||||||
pos: Vec2 {
|
|
||||||
x: rest_rect.min().x,
|
|
||||||
y: rest_rect.center().y - 4.0,
|
|
||||||
},
|
|
||||||
text,
|
|
||||||
text_align: TextAlign::Start,
|
|
||||||
});
|
|
||||||
|
|
||||||
if style.debug_rects {
|
if style.debug_rects {
|
||||||
out_commands.push(debug_rect(rect));
|
out_commands.push(debug_rect(rect));
|
||||||
}
|
}
|
||||||
|
@ -168,7 +152,7 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
|
|
||||||
// TODO: paint a little triangle or arrow or something instead of this
|
// TODO: paint a little triangle or arrow or something instead of this
|
||||||
|
|
||||||
let (small_icon_rect, _, _) = style.icon_rectangles(&rect);
|
let (small_icon_rect, _) = style.icon_rectangles(&rect);
|
||||||
// Draw a minus:
|
// Draw a minus:
|
||||||
out_commands.push(PaintCmd::Line {
|
out_commands.push(PaintCmd::Line {
|
||||||
points: vec![
|
points: vec![
|
||||||
|
@ -178,7 +162,7 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
color: stroke_color,
|
color: stroke_color,
|
||||||
width: style.line_width,
|
width: style.line_width,
|
||||||
});
|
});
|
||||||
if open {
|
if !open {
|
||||||
// Draw it as a plus:
|
// Draw it as a plus:
|
||||||
out_commands.push(PaintCmd::Line {
|
out_commands.push(PaintCmd::Line {
|
||||||
points: vec![
|
points: vec![
|
||||||
|
@ -194,12 +178,11 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
checked,
|
checked,
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
text,
|
|
||||||
} => {
|
} => {
|
||||||
let fill_color = style.interact_fill_color(&interact);
|
let fill_color = style.interact_fill_color(&interact);
|
||||||
let stroke_color = style.interact_stroke_color(&interact);
|
let stroke_color = style.interact_stroke_color(&interact);
|
||||||
|
|
||||||
let (small_icon_rect, big_icon_rect, rest_rect) = style.icon_rectangles(&rect);
|
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&rect);
|
||||||
|
|
||||||
out_commands.push(PaintCmd::Circle {
|
out_commands.push(PaintCmd::Circle {
|
||||||
center: big_icon_rect.center(),
|
center: big_icon_rect.center(),
|
||||||
|
@ -217,35 +200,18 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
out_commands.push(PaintCmd::Text {
|
|
||||||
fill_color: stroke_color,
|
|
||||||
font_name: style.font_name.clone(),
|
|
||||||
font_size: style.font_size,
|
|
||||||
pos: Vec2 {
|
|
||||||
x: rest_rect.min().x,
|
|
||||||
y: rect.center().y - 4.0,
|
|
||||||
},
|
|
||||||
text,
|
|
||||||
text_align: TextAlign::Start,
|
|
||||||
});
|
|
||||||
|
|
||||||
if style.debug_rects {
|
if style.debug_rects {
|
||||||
out_commands.push(debug_rect(rect));
|
out_commands.push(debug_rect(rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GuiCmd::Slider {
|
GuiCmd::Slider {
|
||||||
interact,
|
interact,
|
||||||
label,
|
|
||||||
max,
|
max,
|
||||||
min,
|
min,
|
||||||
rect,
|
rect,
|
||||||
value,
|
value,
|
||||||
} => {
|
} => {
|
||||||
let thin_rect = Rect::from_min_size(
|
let thin_rect = Rect::from_center_size(rect.center(), vec2(rect.size.x, 6.0));
|
||||||
vec2(rect.min().x, lerp(rect.min().y, rect.max().y, 2.0 / 3.0)),
|
|
||||||
vec2(rect.size.x, 8.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
let marker_center_x = remap_clamp(value, min, max, rect.min().x, rect.max().x);
|
let marker_center_x = remap_clamp(value, min, max, rect.min().x, rect.max().x);
|
||||||
|
|
||||||
let marker_rect = Rect::from_center_size(
|
let marker_rect = Rect::from_center_size(
|
||||||
|
@ -269,18 +235,6 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
size: marker_rect.size,
|
size: marker_rect.size,
|
||||||
});
|
});
|
||||||
|
|
||||||
out_commands.push(PaintCmd::Text {
|
|
||||||
fill_color: style.interact_stroke_color(&interact),
|
|
||||||
font_name: style.font_name.clone(),
|
|
||||||
font_size: style.font_size,
|
|
||||||
pos: vec2(
|
|
||||||
rect.min().x,
|
|
||||||
lerp(rect.min().y, rect.max().y, 1.0 / 3.0) - 5.0,
|
|
||||||
),
|
|
||||||
text: format!("{}: {:.3}", label, value),
|
|
||||||
text_align: TextAlign::Start,
|
|
||||||
});
|
|
||||||
|
|
||||||
if style.debug_rects {
|
if style.debug_rects {
|
||||||
out_commands.push(debug_rect(rect));
|
out_commands.push(debug_rect(rect));
|
||||||
}
|
}
|
||||||
|
@ -288,7 +242,6 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
GuiCmd::Text {
|
GuiCmd::Text {
|
||||||
pos,
|
pos,
|
||||||
text,
|
text,
|
||||||
text_align,
|
|
||||||
style: text_style,
|
style: text_style,
|
||||||
} => {
|
} => {
|
||||||
let fill_color = match text_style {
|
let fill_color = match text_style {
|
||||||
|
@ -298,9 +251,8 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
fill_color,
|
fill_color,
|
||||||
font_name: style.font_name.clone(),
|
font_name: style.font_name.clone(),
|
||||||
font_size: style.font_size,
|
font_size: style.font_size,
|
||||||
pos: pos + vec2(0.0, style.font_size / 2.0 - 5.0), // TODO
|
pos,
|
||||||
text,
|
text,
|
||||||
text_align,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
src/types.rs
19
src/types.rs
|
@ -74,14 +74,6 @@ pub struct InteractInfo {
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum TextAlign {
|
|
||||||
Start, // Test with arabic text
|
|
||||||
Center,
|
|
||||||
End,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum TextStyle {
|
pub enum TextStyle {
|
||||||
|
@ -100,7 +92,6 @@ pub enum GuiCmd {
|
||||||
checked: bool,
|
checked: bool,
|
||||||
interact: InteractInfo,
|
interact: InteractInfo,
|
||||||
rect: Rect,
|
rect: Rect,
|
||||||
text: String,
|
|
||||||
},
|
},
|
||||||
/// The header button background for a foldable region
|
/// The header button background for a foldable region
|
||||||
FoldableHeader {
|
FoldableHeader {
|
||||||
|
@ -112,21 +103,21 @@ pub enum GuiCmd {
|
||||||
checked: bool,
|
checked: bool,
|
||||||
interact: InteractInfo,
|
interact: InteractInfo,
|
||||||
rect: Rect,
|
rect: Rect,
|
||||||
text: String,
|
|
||||||
},
|
},
|
||||||
Slider {
|
Slider {
|
||||||
interact: InteractInfo,
|
interact: InteractInfo,
|
||||||
label: String,
|
|
||||||
max: f32,
|
max: f32,
|
||||||
min: f32,
|
min: f32,
|
||||||
rect: Rect,
|
rect: Rect,
|
||||||
value: f32,
|
value: f32,
|
||||||
},
|
},
|
||||||
|
/// Paint a single line of mono-space text.
|
||||||
|
/// The text should start at the given position and flow to the right.
|
||||||
|
/// The text should be vertically centered at the given position.
|
||||||
Text {
|
Text {
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
style: TextStyle,
|
style: TextStyle,
|
||||||
text: String,
|
text: String,
|
||||||
text_align: TextAlign,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +153,9 @@ pub enum PaintCmd {
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
},
|
},
|
||||||
|
/// Paint a single line of mono-space text.
|
||||||
|
/// The text should start at the given position and flow to the right.
|
||||||
|
/// The text should be vertically centered at the given position.
|
||||||
Text {
|
Text {
|
||||||
fill_color: Color,
|
fill_color: Color,
|
||||||
/// Name, e.g. Palatino
|
/// Name, e.g. Palatino
|
||||||
|
@ -170,6 +164,5 @@ pub enum PaintCmd {
|
||||||
font_size: f32,
|
font_size: f32,
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
text: String,
|
text: String,
|
||||||
text_align: TextAlign,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue