Move widgets out of Region into own file
This commit is contained in:
parent
9f876b3ccd
commit
984a56aae9
6 changed files with 340 additions and 191 deletions
|
@ -4,7 +4,12 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{font::Font, math::*, types::*};
|
use crate::{
|
||||||
|
font::Font,
|
||||||
|
math::*,
|
||||||
|
types::*,
|
||||||
|
widgets::{label, Widget},
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -72,7 +77,7 @@ impl GuiResponse {
|
||||||
/// Show this text if the item was hovered
|
/// Show this text if the item was hovered
|
||||||
pub fn tooltip_text<S: Into<String>>(&mut self, text: S) -> &mut Self {
|
pub fn tooltip_text<S: Into<String>>(&mut self, text: S) -> &mut Self {
|
||||||
self.tooltip(|popup| {
|
self.tooltip(|popup| {
|
||||||
popup.label(text);
|
popup.add(label(text));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +95,7 @@ pub struct Memory {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
struct TextFragment {
|
pub struct TextFragment {
|
||||||
/// The start of each character, starting at zero.
|
/// The start of each character, starting at zero.
|
||||||
x_offsets: Vec<f32>,
|
x_offsets: Vec<f32>,
|
||||||
/// 0 for the first line, n * line_spacing for the rest
|
/// 0 for the first line, n * line_spacing for the rest
|
||||||
|
@ -98,7 +103,7 @@ struct TextFragment {
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
type TextFragments = Vec<TextFragment>;
|
pub type TextFragments = Vec<TextFragment>;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -116,7 +121,14 @@ impl Default for Direction {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Id = u64;
|
pub type Id = u64;
|
||||||
|
|
||||||
|
pub fn make_id<H: Hash>(source: &H) -> Id {
|
||||||
|
use std::hash::Hasher;
|
||||||
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||||
|
source.hash(&mut hasher);
|
||||||
|
hasher.finish()
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -271,137 +283,6 @@ impl Region {
|
||||||
self.cursor
|
self.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn button<S: Into<String>>(&mut self, text: S) -> GuiResponse {
|
|
||||||
let text: String = text.into();
|
|
||||||
let id = self.make_child_id(&text);
|
|
||||||
let (text, text_size) = self.layout_text(&text);
|
|
||||||
let text_cursor = self.cursor + self.options().button_padding;
|
|
||||||
let (rect, interact) =
|
|
||||||
self.reserve_space(text_size + 2.0 * self.options().button_padding, Some(id));
|
|
||||||
self.add_graphic(GuiCmd::Button { interact, rect });
|
|
||||||
self.add_text(text_cursor, text);
|
|
||||||
self.response(interact)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn checkbox<S: Into<String>>(&mut self, text: S, checked: &mut bool) -> GuiResponse {
|
|
||||||
let text: String = text.into();
|
|
||||||
let id = self.make_child_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(
|
|
||||||
self.options().button_padding
|
|
||||||
+ vec2(self.options().start_icon_width, 0.0)
|
|
||||||
+ text_size
|
|
||||||
+ self.options().button_padding,
|
|
||||||
Some(id),
|
|
||||||
);
|
|
||||||
if interact.clicked {
|
|
||||||
*checked = !*checked;
|
|
||||||
}
|
|
||||||
self.add_graphic(GuiCmd::Checkbox {
|
|
||||||
checked: *checked,
|
|
||||||
interact,
|
|
||||||
rect,
|
|
||||||
});
|
|
||||||
self.add_text(text_cursor, text);
|
|
||||||
self.response(interact)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn label<S: Into<String>>(&mut self, text: S) -> GuiResponse {
|
|
||||||
let text: String = text.into();
|
|
||||||
let (text, text_size) = self.layout_text(&text);
|
|
||||||
self.add_text(self.cursor, text);
|
|
||||||
let (_, interact) = self.reserve_space(text_size, None);
|
|
||||||
self.response(interact)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A radio button
|
|
||||||
pub fn radio<S: Into<String>>(&mut self, text: S, checked: bool) -> GuiResponse {
|
|
||||||
let text: String = text.into();
|
|
||||||
let id = self.make_child_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(
|
|
||||||
self.options().button_padding
|
|
||||||
+ vec2(self.options().start_icon_width, 0.0)
|
|
||||||
+ text_size
|
|
||||||
+ self.options().button_padding,
|
|
||||||
Some(id),
|
|
||||||
);
|
|
||||||
self.add_graphic(GuiCmd::RadioButton {
|
|
||||||
checked,
|
|
||||||
interact,
|
|
||||||
rect,
|
|
||||||
});
|
|
||||||
self.add_text(text_cursor, text);
|
|
||||||
self.response(interact)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn slider_f32<S: Into<String>>(
|
|
||||||
&mut self,
|
|
||||||
text: S,
|
|
||||||
value: &mut f32,
|
|
||||||
min: f32,
|
|
||||||
max: f32,
|
|
||||||
) -> GuiResponse {
|
|
||||||
let text_string: String = text.into();
|
|
||||||
if true {
|
|
||||||
// Text to the right of the slider
|
|
||||||
self.columns(2, |columns| {
|
|
||||||
columns[1].label(format!("{}: {:.3}", text_string, value));
|
|
||||||
columns[0].naked_slider_f32(&text_string, value, min, max)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// Text above slider
|
|
||||||
let (text, text_size) = self.layout_text(&format!("{}: {:.3}", text_string, value));
|
|
||||||
self.add_text(self.cursor, text);
|
|
||||||
self.reserve_space_inner(text_size);
|
|
||||||
self.naked_slider_f32(&text_string, value, min, max)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn naked_slider_f32<H: Hash>(
|
|
||||||
&mut self,
|
|
||||||
id: &H,
|
|
||||||
value: &mut f32,
|
|
||||||
min: f32,
|
|
||||||
max: f32,
|
|
||||||
) -> GuiResponse {
|
|
||||||
debug_assert!(min <= max);
|
|
||||||
let id = self.make_child_id(id);
|
|
||||||
let (slider_rect, interact) = self.reserve_space(
|
|
||||||
Vec2 {
|
|
||||||
x: self.available_space.x,
|
|
||||||
y: self.data.font.line_spacing(),
|
|
||||||
},
|
|
||||||
Some(id),
|
|
||||||
);
|
|
||||||
|
|
||||||
if interact.active {
|
|
||||||
*value = remap_clamp(
|
|
||||||
self.input().mouse_pos.x,
|
|
||||||
slider_rect.min().x,
|
|
||||||
slider_rect.max().x,
|
|
||||||
min,
|
|
||||||
max,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.add_graphic(GuiCmd::Slider {
|
|
||||||
interact,
|
|
||||||
max,
|
|
||||||
min,
|
|
||||||
rect: slider_rect,
|
|
||||||
value: *value,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.response(interact)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Sub-regions:
|
// Sub-regions:
|
||||||
|
|
||||||
|
@ -507,11 +388,11 @@ impl Region {
|
||||||
self.reserve_space_inner(size);
|
self.reserve_space_inner(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporarily split split a vertical layout into two column regions.
|
/// Temporarily split split a vertical layout into several columns.
|
||||||
///
|
///
|
||||||
/// gui.columns(2, |columns| {
|
/// gui.columns(2, |columns| {
|
||||||
/// columns[0].label("First column");
|
/// columns[0].add(label("First column"));
|
||||||
/// columns[1].label("Second column");
|
/// columns[1].add(label("Second column"));
|
||||||
/// });
|
/// });
|
||||||
pub fn columns<F, R>(&mut self, num_columns: usize, add_contents: F) -> R
|
pub fn columns<F, R>(&mut self, num_columns: usize, add_contents: F) -> R
|
||||||
where
|
where
|
||||||
|
@ -547,6 +428,13 @@ impl Region {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub fn add<W: Widget>(&mut self, widget: W) -> GuiResponse {
|
||||||
|
widget.add_to(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO: Return a Rect
|
||||||
pub fn reserve_space(
|
pub fn reserve_space(
|
||||||
&mut self,
|
&mut self,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
|
@ -577,8 +465,9 @@ impl Region {
|
||||||
(rect, interact)
|
(rect, interact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Return a Rect
|
||||||
/// Reserve this much space and move the cursor.
|
/// Reserve this much space and move the cursor.
|
||||||
fn reserve_space_inner(&mut self, size: Vec2) {
|
pub fn reserve_space_inner(&mut self, size: Vec2) {
|
||||||
if self.dir == Direction::Horizontal {
|
if self.dir == Direction::Horizontal {
|
||||||
self.cursor.x += size.x;
|
self.cursor.x += size.x;
|
||||||
self.available_space.x -= size.x;
|
self.available_space.x -= size.x;
|
||||||
|
@ -592,7 +481,7 @@ impl Region {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_child_id<H: Hash>(&self, child_id: &H) -> Id {
|
pub fn make_child_id<H: Hash>(&self, child_id: &H) -> Id {
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||||
hasher.write_u64(self.id);
|
hasher.write_u64(self.id);
|
||||||
|
@ -600,8 +489,18 @@ impl Region {
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this function
|
pub fn combined_id(&self, child_id: Option<Id>) -> Option<Id> {
|
||||||
fn layout_text(&self, text: &str) -> (TextFragments, Vec2) {
|
child_id.map(|child_id| {
|
||||||
|
use std::hash::Hasher;
|
||||||
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||||
|
hasher.write_u64(self.id);
|
||||||
|
child_id.hash(&mut hasher);
|
||||||
|
hasher.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move this function to Font
|
||||||
|
pub fn layout_text(&self, text: &str) -> (TextFragments, Vec2) {
|
||||||
let line_spacing = self.data.font.line_spacing();
|
let line_spacing = self.data.font.line_spacing();
|
||||||
let mut cursor_y = 0.0;
|
let mut cursor_y = 0.0;
|
||||||
let mut max_width = 0.0;
|
let mut max_width = 0.0;
|
||||||
|
@ -622,7 +521,7 @@ impl Region {
|
||||||
(text_fragments, bounding_size)
|
(text_fragments, bounding_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_text(&mut self, pos: Vec2, text: Vec<TextFragment>) {
|
pub fn add_text(&mut self, pos: Vec2, text: Vec<TextFragment>) {
|
||||||
for fragment in text {
|
for fragment in text {
|
||||||
self.add_graphic(GuiCmd::Text {
|
self.add_graphic(GuiCmd::Text {
|
||||||
pos: pos + vec2(0.0, fragment.y_offset),
|
pos: pos + vec2(0.0, fragment.y_offset),
|
||||||
|
@ -633,7 +532,7 @@ impl Region {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn response(&mut self, interact: InteractInfo) -> GuiResponse {
|
pub fn response(&mut self, interact: InteractInfo) -> GuiResponse {
|
||||||
GuiResponse {
|
GuiResponse {
|
||||||
hovered: interact.hovered,
|
hovered: interact.hovered,
|
||||||
clicked: interact.clicked,
|
clicked: interact.clicked,
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub mod math;
|
||||||
mod painter;
|
mod painter;
|
||||||
mod style;
|
mod style;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
pub mod widgets;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
emgui::Emgui,
|
emgui::Emgui,
|
||||||
|
|
|
@ -7,11 +7,6 @@ pub struct Style {
|
||||||
|
|
||||||
/// For stuff like check marks in check boxes.
|
/// For stuff like check marks in check boxes.
|
||||||
pub line_width: f32,
|
pub line_width: f32,
|
||||||
|
|
||||||
pub font_name: String,
|
|
||||||
|
|
||||||
/// Height in pixels of most text.
|
|
||||||
pub font_size: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Style {
|
impl Default for Style {
|
||||||
|
@ -19,10 +14,6 @@ impl Default for Style {
|
||||||
Style {
|
Style {
|
||||||
debug_rects: false,
|
debug_rects: false,
|
||||||
line_width: 2.0,
|
line_width: 2.0,
|
||||||
// font_name: "Palatino".to_string(),
|
|
||||||
font_name: "Courier".to_string(),
|
|
||||||
// font_name: "Courier New".to_string(),
|
|
||||||
font_size: 12.0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
246
emgui/src/widgets.rs
Normal file
246
emgui/src/widgets.rs
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
use crate::{
|
||||||
|
layout::{make_id, GuiResponse, Id, Region},
|
||||||
|
math::{remap_clamp, vec2, Vec2},
|
||||||
|
types::GuiCmd,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Anything implementing Widget can be added to a Region with Region::add
|
||||||
|
pub trait Widget {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub struct Label {
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Label {
|
||||||
|
pub fn new<S: Into<String>>(text: S) -> Self {
|
||||||
|
Label { text: text.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn label<S: Into<String>>(text: S) -> Label {
|
||||||
|
Label::new(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Label {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let (text, text_size) = region.layout_text(&self.text);
|
||||||
|
region.add_text(region.cursor(), text);
|
||||||
|
let (_, interact) = region.reserve_space(text_size, None);
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub struct Button {
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Button {
|
||||||
|
pub fn new<S: Into<String>>(text: S) -> Self {
|
||||||
|
Button { text: text.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Button {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let id = region.make_child_id(&self.text);
|
||||||
|
let (text, text_size) = region.layout_text(&self.text);
|
||||||
|
let text_cursor = region.cursor() + region.options().button_padding;
|
||||||
|
let (rect, interact) =
|
||||||
|
region.reserve_space(text_size + 2.0 * region.options().button_padding, Some(id));
|
||||||
|
region.add_graphic(GuiCmd::Button { interact, rect });
|
||||||
|
region.add_text(text_cursor, text);
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Checkbox<'a> {
|
||||||
|
checked: &'a mut bool,
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Checkbox<'a> {
|
||||||
|
pub fn new<S: Into<String>>(checked: &'a mut bool, text: S) -> Self {
|
||||||
|
Checkbox {
|
||||||
|
checked,
|
||||||
|
text: text.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Widget for Checkbox<'a> {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let id = region.make_child_id(&self.text);
|
||||||
|
let (text, text_size) = region.layout_text(&self.text);
|
||||||
|
let text_cursor = region.cursor()
|
||||||
|
+ region.options().button_padding
|
||||||
|
+ vec2(region.options().start_icon_width, 0.0);
|
||||||
|
let (rect, interact) = region.reserve_space(
|
||||||
|
region.options().button_padding
|
||||||
|
+ vec2(region.options().start_icon_width, 0.0)
|
||||||
|
+ text_size
|
||||||
|
+ region.options().button_padding,
|
||||||
|
Some(id),
|
||||||
|
);
|
||||||
|
if interact.clicked {
|
||||||
|
*self.checked = !*self.checked;
|
||||||
|
}
|
||||||
|
region.add_graphic(GuiCmd::Checkbox {
|
||||||
|
checked: *self.checked,
|
||||||
|
interact,
|
||||||
|
rect,
|
||||||
|
});
|
||||||
|
region.add_text(text_cursor, text);
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RadioButton {
|
||||||
|
checked: bool,
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RadioButton {
|
||||||
|
pub fn new<S: Into<String>>(checked: bool, text: S) -> Self {
|
||||||
|
RadioButton {
|
||||||
|
checked,
|
||||||
|
text: text.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn radio<S: Into<String>>(checked: bool, text: S) -> RadioButton {
|
||||||
|
RadioButton::new(checked, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for RadioButton {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let id = region.make_child_id(&self.text);
|
||||||
|
let (text, text_size) = region.layout_text(&self.text);
|
||||||
|
let text_cursor = region.cursor()
|
||||||
|
+ region.options().button_padding
|
||||||
|
+ vec2(region.options().start_icon_width, 0.0);
|
||||||
|
let (rect, interact) = region.reserve_space(
|
||||||
|
region.options().button_padding
|
||||||
|
+ vec2(region.options().start_icon_width, 0.0)
|
||||||
|
+ text_size
|
||||||
|
+ region.options().button_padding,
|
||||||
|
Some(id),
|
||||||
|
);
|
||||||
|
region.add_graphic(GuiCmd::RadioButton {
|
||||||
|
checked: self.checked,
|
||||||
|
interact,
|
||||||
|
rect,
|
||||||
|
});
|
||||||
|
region.add_text(text_cursor, text);
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Slider<'a> {
|
||||||
|
value: &'a mut f32,
|
||||||
|
min: f32,
|
||||||
|
max: f32,
|
||||||
|
id: Option<Id>,
|
||||||
|
text: Option<String>,
|
||||||
|
text_on_top: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Slider<'a> {
|
||||||
|
pub fn new(value: &'a mut f32, min: f32, max: f32) -> Self {
|
||||||
|
Slider {
|
||||||
|
value,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
id: None,
|
||||||
|
text: None,
|
||||||
|
text_on_top: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(mut self, id: Id) -> Self {
|
||||||
|
self.id = Some(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text<S: Into<String>>(mut self, text: S) -> Self {
|
||||||
|
self.text = Some(text.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Widget for Slider<'a> {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
if let Some(text) = &self.text {
|
||||||
|
let text_on_top = self.text_on_top.unwrap_or_default();
|
||||||
|
let full_text = format!("{}: {:.3}", text, self.value);
|
||||||
|
let id = Some(self.id.unwrap_or(make_id(text)));
|
||||||
|
let mut naked = self;
|
||||||
|
naked.id = id;
|
||||||
|
naked.text = None;
|
||||||
|
|
||||||
|
if text_on_top {
|
||||||
|
let (text, text_size) = region.layout_text(&full_text);
|
||||||
|
region.add_text(region.cursor(), text);
|
||||||
|
region.reserve_space_inner(text_size);
|
||||||
|
naked.add_to(region)
|
||||||
|
} else {
|
||||||
|
region.columns(2, |columns| {
|
||||||
|
columns[1].add(label(full_text));
|
||||||
|
naked.add_to(&mut columns[0])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let value = self.value;
|
||||||
|
let min = self.min;
|
||||||
|
let max = self.max;
|
||||||
|
debug_assert!(min <= max);
|
||||||
|
let id = region.combined_id(self.id);
|
||||||
|
let (slider_rect, interact) = region.reserve_space(
|
||||||
|
Vec2 {
|
||||||
|
x: region.available_space.x,
|
||||||
|
y: region.data.font.line_spacing(),
|
||||||
|
},
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if interact.active {
|
||||||
|
*value = remap_clamp(
|
||||||
|
region.input().mouse_pos.x,
|
||||||
|
slider_rect.min().x,
|
||||||
|
slider_rect.max().x,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
region.add_graphic(GuiCmd::Slider {
|
||||||
|
interact,
|
||||||
|
max,
|
||||||
|
min,
|
||||||
|
rect: slider_rect,
|
||||||
|
value: *value,
|
||||||
|
});
|
||||||
|
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
|
@ -1,4 +1,4 @@
|
||||||
use emgui::{math::*, types::*, Region};
|
use emgui::{math::*, types::*, widgets::*, Region};
|
||||||
|
|
||||||
pub trait GuiSettings {
|
pub trait GuiSettings {
|
||||||
fn show_gui(&mut self, gui: &mut Region);
|
fn show_gui(&mut self, gui: &mut Region);
|
||||||
|
@ -29,45 +29,54 @@ impl Default for App {
|
||||||
|
|
||||||
impl GuiSettings for App {
|
impl GuiSettings for App {
|
||||||
fn show_gui(&mut self, gui: &mut Region) {
|
fn show_gui(&mut self, gui: &mut Region) {
|
||||||
gui.label(format!(
|
gui.add(label(format!(
|
||||||
"Screen size: {} x {}",
|
"Screen size: {} x {}",
|
||||||
gui.input().screen_size.x,
|
gui.input().screen_size.x,
|
||||||
gui.input().screen_size.y,
|
gui.input().screen_size.y,
|
||||||
));
|
)));
|
||||||
|
|
||||||
gui.label("Hover me").tooltip_text(
|
gui.add(label("Hover me")).tooltip_text(
|
||||||
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
|
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
|
||||||
);
|
);
|
||||||
|
|
||||||
gui.checkbox("checkbox", &mut self.checked);
|
gui.add(Checkbox::new(&mut self.checked, "checkbox"));
|
||||||
|
|
||||||
gui.horizontal(|gui| {
|
gui.horizontal(|gui| {
|
||||||
if gui.radio("First", self.selected_alternative == 0).clicked {
|
if gui
|
||||||
|
.add(radio(self.selected_alternative == 0, "First"))
|
||||||
|
.clicked
|
||||||
|
{
|
||||||
self.selected_alternative = 0;
|
self.selected_alternative = 0;
|
||||||
}
|
}
|
||||||
if gui.radio("Second", self.selected_alternative == 1).clicked {
|
if gui
|
||||||
|
.add(radio(self.selected_alternative == 1, "Second"))
|
||||||
|
.clicked
|
||||||
|
{
|
||||||
self.selected_alternative = 1;
|
self.selected_alternative = 1;
|
||||||
}
|
}
|
||||||
if gui.radio("Final", self.selected_alternative == 2).clicked {
|
if gui
|
||||||
|
.add(radio(self.selected_alternative == 2, "Final"))
|
||||||
|
.clicked
|
||||||
|
{
|
||||||
self.selected_alternative = 2;
|
self.selected_alternative = 2;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if gui
|
if gui
|
||||||
.button("Click me")
|
.add(Button::new("Click me"))
|
||||||
.tooltip_text("This will just increase a counter.")
|
.tooltip_text("This will just increase a counter.")
|
||||||
.clicked
|
.clicked
|
||||||
{
|
{
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.label(format!("This is a multiline label.\nThe button have been clicked {} times.\nBelow are more options.", self.count));
|
gui.add(label(format!("This is a multiline label.\nThe button have been clicked {} times.\nBelow are more options.", self.count)));
|
||||||
|
|
||||||
gui.foldable("Test box rendering", |gui| {
|
gui.foldable("Test box rendering", |gui| {
|
||||||
gui.slider_f32("width", &mut self.size.x, 0.0, 500.0);
|
gui.add(Slider::new(&mut self.size.x, 0.0, 500.0).text("width"));
|
||||||
gui.slider_f32("height", &mut self.size.y, 0.0, 500.0);
|
gui.add(Slider::new(&mut self.size.y, 0.0, 500.0).text("height"));
|
||||||
gui.slider_f32("corner_radius", &mut self.corner_radius, 0.0, 50.0);
|
gui.add(Slider::new(&mut self.corner_radius, 0.0, 50.0).text("corner_radius"));
|
||||||
gui.slider_f32("stroke_width", &mut self.stroke_width, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.stroke_width, 0.0, 10.0).text("stroke_width"));
|
||||||
|
|
||||||
let pos = gui.cursor();
|
let pos = gui.cursor();
|
||||||
gui.add_graphic(GuiCmd::PaintCommands(vec![PaintCmd::Rect {
|
gui.add_graphic(GuiCmd::PaintCommands(vec![PaintCmd::Rect {
|
||||||
|
@ -87,27 +96,26 @@ impl GuiSettings for App {
|
||||||
|
|
||||||
impl GuiSettings for emgui::LayoutOptions {
|
impl GuiSettings for emgui::LayoutOptions {
|
||||||
fn show_gui(&mut self, gui: &mut Region) {
|
fn show_gui(&mut self, gui: &mut Region) {
|
||||||
if gui.button("Reset LayoutOptions").clicked {
|
if gui.add(Button::new("Reset LayoutOptions")).clicked {
|
||||||
*self = Default::default();
|
*self = Default::default();
|
||||||
}
|
}
|
||||||
gui.slider_f32("item_spacing.x", &mut self.item_spacing.x, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.item_spacing.x, 0.0, 10.0).text("item_spacing.x"));
|
||||||
gui.slider_f32("item_spacing.y", &mut self.item_spacing.y, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.item_spacing.y, 0.0, 10.0).text("item_spacing.y"));
|
||||||
gui.slider_f32("window_padding.x", &mut self.window_padding.x, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.window_padding.x, 0.0, 10.0).text("window_padding.x"));
|
||||||
gui.slider_f32("window_padding.y", &mut self.window_padding.y, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.window_padding.y, 0.0, 10.0).text("window_padding.y"));
|
||||||
gui.slider_f32("indent", &mut self.indent, 0.0, 100.0);
|
gui.add(Slider::new(&mut self.indent, 0.0, 100.0).text("indent"));
|
||||||
gui.slider_f32("button_padding.x", &mut self.button_padding.x, 0.0, 20.0);
|
gui.add(Slider::new(&mut self.button_padding.x, 0.0, 20.0).text("button_padding.x"));
|
||||||
gui.slider_f32("button_padding.y", &mut self.button_padding.y, 0.0, 20.0);
|
gui.add(Slider::new(&mut self.button_padding.y, 0.0, 20.0).text("button_padding.y"));
|
||||||
gui.slider_f32("start_icon_width", &mut self.start_icon_width, 0.0, 60.0);
|
gui.add(Slider::new(&mut self.start_icon_width, 0.0, 60.0).text("start_icon_width"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiSettings for emgui::Style {
|
impl GuiSettings for emgui::Style {
|
||||||
fn show_gui(&mut self, gui: &mut Region) {
|
fn show_gui(&mut self, gui: &mut Region) {
|
||||||
if gui.button("Reset Style").clicked {
|
if gui.add(Button::new("Reset Style")).clicked {
|
||||||
*self = Default::default();
|
*self = Default::default();
|
||||||
}
|
}
|
||||||
gui.checkbox("debug_rects", &mut self.debug_rects);
|
gui.add(Checkbox::new(&mut self.debug_rects, "debug_rects"));
|
||||||
gui.slider_f32("line_width", &mut self.line_width, 0.0, 10.0);
|
gui.add(Slider::new(&mut self.line_width, 0.0, 10.0).text("line_width"));
|
||||||
gui.slider_f32("font_size", &mut self.font_size, 5.0, 32.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ extern crate emgui;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use emgui::{Emgui, Font, RawInput};
|
use emgui::{widgets::label, Emgui, Font, RawInput};
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
@ -73,21 +73,25 @@ impl State {
|
||||||
style.show_gui(gui);
|
style.show_gui(gui);
|
||||||
});
|
});
|
||||||
|
|
||||||
let stats = self.stats; // TODO: avoid
|
|
||||||
let webgl_info = self.webgl_painter.debug_info(); // TODO: avoid
|
|
||||||
region.foldable("Stats", |gui| {
|
region.foldable("Stats", |gui| {
|
||||||
gui.label(format!("num_vertices: {}", stats.num_vertices));
|
gui.add(label(format!("num_vertices: {}", self.stats.num_vertices)));
|
||||||
gui.label(format!("num_triangles: {}", stats.num_triangles));
|
gui.add(label(format!(
|
||||||
|
"num_triangles: {}",
|
||||||
|
self.stats.num_triangles
|
||||||
|
)));
|
||||||
|
|
||||||
gui.label("WebGl painter info:");
|
gui.add(label("WebGl painter info:"));
|
||||||
gui.indent(|gui| {
|
gui.indent(|gui| {
|
||||||
gui.label(webgl_info);
|
gui.add(label(self.webgl_painter.debug_info()));
|
||||||
});
|
});
|
||||||
|
|
||||||
gui.label("Timings:");
|
gui.add(label("Timings:"));
|
||||||
gui.indent(|gui| {
|
gui.indent(|gui| {
|
||||||
gui.label(format!("Everything: {:.1} ms", stats.everything_ms));
|
gui.add(label(format!(
|
||||||
gui.label(format!("WebGL: {:.1} ms", stats.webgl_ms));
|
"Everything: {:.1} ms",
|
||||||
|
self.stats.everything_ms
|
||||||
|
)));
|
||||||
|
gui.add(label(format!("WebGL: {:.1} ms", self.stats.webgl_ms)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue