Refactor Region: remember region rectangle
This will be used as a clip rectangle for generated paint commands.
This commit is contained in:
parent
7f85b2623b
commit
472e0b9afe
9 changed files with 128 additions and 83 deletions
|
@ -49,9 +49,9 @@ impl Emigui {
|
||||||
id: Id::background(),
|
id: Id::background(),
|
||||||
dir: layout::Direction::Vertical,
|
dir: layout::Direction::Vertical,
|
||||||
align: layout::Align::Center,
|
align: layout::Align::Center,
|
||||||
|
rect: Rect::from_min_size(Default::default(), self.ctx.input.screen_size),
|
||||||
cursor: Default::default(),
|
cursor: Default::default(),
|
||||||
bounding_size: Default::default(),
|
bounding_size: Default::default(),
|
||||||
available_space: self.ctx.input.screen_size,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ pub fn align_rect(rect: Rect, align: (Align, Align)) -> Rect {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO: move show_popup, and expand its features (default size, autosize, etc)
|
||||||
/// Show a pop-over window
|
/// Show a pop-over window
|
||||||
pub fn show_popup<F>(ctx: &Arc<Context>, window_pos: Pos2, add_contents: F)
|
pub fn show_popup<F>(ctx: &Arc<Context>, window_pos: Pos2, add_contents: F)
|
||||||
where
|
where
|
||||||
|
@ -105,17 +106,9 @@ where
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let window_padding = style.window_padding;
|
let window_padding = style.window_padding;
|
||||||
|
|
||||||
let mut contents_region = Region {
|
let size = vec2(ctx.input.screen_size.x.min(350.0), std::f32::INFINITY); // TODO: popup/tooltip width
|
||||||
ctx: ctx.clone(),
|
let inner_rect = Rect::from_min_size(window_pos + window_padding, size);
|
||||||
layer,
|
let mut contents_region = Region::new(ctx.clone(), layer, Id::popup(), inner_rect);
|
||||||
style,
|
|
||||||
id: Id::popup(),
|
|
||||||
dir: Direction::Vertical,
|
|
||||||
align: Align::Min,
|
|
||||||
cursor: window_pos + window_padding,
|
|
||||||
bounding_size: vec2(0.0, 0.0),
|
|
||||||
available_space: vec2(ctx.input.screen_size.x.min(350.0), std::f32::INFINITY), // TODO: popup/tooltip width
|
|
||||||
};
|
|
||||||
|
|
||||||
add_contents(&mut contents_region);
|
add_contents(&mut contents_region);
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,16 @@ impl Rect {
|
||||||
Rect::from_min_size(self.min() + amnt, self.size())
|
Rect::from_min_size(self.min() + amnt, self.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keep min
|
||||||
|
pub fn set_width(&mut self, w: f32) {
|
||||||
|
self.max.x = self.min.x + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep min
|
||||||
|
pub fn set_height(&mut self, h: f32) {
|
||||||
|
self.max.y = self.min.y + h;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn contains(&self, p: Pos2) -> bool {
|
pub fn contains(&self, p: Pos2) -> bool {
|
||||||
self.min.x <= p.x
|
self.min.x <= p.x
|
||||||
&& p.x <= self.min.x + self.size().x
|
&& p.x <= self.min.x + self.size().x
|
||||||
|
|
|
@ -21,20 +21,42 @@ pub struct Region {
|
||||||
|
|
||||||
pub(crate) align: Align,
|
pub(crate) align: Align,
|
||||||
|
|
||||||
|
// The `rect` represents where in space the region is
|
||||||
|
// and its max size (original available_space).
|
||||||
|
// Note that the size may be infinite in one or both dimensions.
|
||||||
|
// The widgets will TRY to fit within the rect,
|
||||||
|
// but may overflow (which you will see in bounding_size).
|
||||||
|
// It will use the rect (which never changes) as a
|
||||||
|
// clip rect when painting the contents of the region.
|
||||||
|
pub(crate) rect: Rect,
|
||||||
|
|
||||||
/// Where the next widget will be put.
|
/// Where the next widget will be put.
|
||||||
/// Progresses along self.dir
|
/// Progresses along self.dir.
|
||||||
|
/// Initially set to rect.min()
|
||||||
pub(crate) cursor: Pos2,
|
pub(crate) cursor: Pos2,
|
||||||
|
|
||||||
/// Bounding box of children.
|
/// Bounding box of children.
|
||||||
/// We keep track of our max-size along the orthogonal to self.dir
|
/// We keep track of our max-size along the orthogonal to self.dir
|
||||||
|
/// Initially set to zero.
|
||||||
pub(crate) bounding_size: Vec2,
|
pub(crate) bounding_size: Vec2,
|
||||||
|
|
||||||
/// This how much more space we can take up without overflowing our parent.
|
|
||||||
/// Shrinks as cursor increments.
|
|
||||||
pub(crate) available_space: Vec2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region {
|
impl Region {
|
||||||
|
pub fn new(ctx: Arc<Context>, layer: Layer, id: Id, rect: Rect) -> Self {
|
||||||
|
let style = ctx.style();
|
||||||
|
Region {
|
||||||
|
ctx,
|
||||||
|
layer,
|
||||||
|
style,
|
||||||
|
id,
|
||||||
|
dir: Direction::Vertical,
|
||||||
|
align: Align::Min,
|
||||||
|
rect,
|
||||||
|
cursor: rect.min(),
|
||||||
|
bounding_size: Vec2::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// It is up to the caller to make sure there is room for this.
|
/// It is up to the caller to make sure there is room for this.
|
||||||
/// Can be used for free painting.
|
/// Can be used for free painting.
|
||||||
/// NOTE: all coordinates are screen coordinates!
|
/// NOTE: all coordinates are screen coordinates!
|
||||||
|
@ -63,16 +85,18 @@ impl Region {
|
||||||
&*self.ctx.fonts
|
&*self.ctx.fonts
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> f32 {
|
pub fn available_width(&self) -> f32 {
|
||||||
self.available_space.x
|
self.rect.max().x - self.cursor.x
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> f32 {
|
pub fn available_height(&self) -> f32 {
|
||||||
self.available_space.y
|
self.rect.max().y - self.cursor.y
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> Vec2 {
|
/// This how much more space we can take up without overflowing our parent.
|
||||||
self.available_space
|
/// Shrinks as cursor increments.
|
||||||
|
pub fn available_space(&self) -> Vec2 {
|
||||||
|
self.rect.max() - self.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn direction(&self) -> Direction {
|
pub fn direction(&self) -> Direction {
|
||||||
|
@ -103,11 +127,11 @@ impl Region {
|
||||||
let id = self.make_unique_id(&text);
|
let id = self.make_unique_id(&text);
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = &self.fonts()[text_style];
|
let font = &self.fonts()[text_style];
|
||||||
let (text, text_size) = font.layout_multiline(&text, self.width());
|
let (text, text_size) = font.layout_multiline(&text, self.available_width());
|
||||||
let text_cursor = self.cursor + self.style.button_padding;
|
let text_cursor = self.cursor + self.style.button_padding;
|
||||||
let interact = self.reserve_space(
|
let interact = self.reserve_space(
|
||||||
vec2(
|
vec2(
|
||||||
self.available_space.x,
|
self.available_width(),
|
||||||
text_size.y + 2.0 * self.style.button_padding.y,
|
text_size.y + 2.0 * self.style.button_padding.y,
|
||||||
),
|
),
|
||||||
Some(id),
|
Some(id),
|
||||||
|
@ -180,6 +204,7 @@ impl Region {
|
||||||
F: FnOnce(&mut Region),
|
F: FnOnce(&mut Region),
|
||||||
{
|
{
|
||||||
let indent = vec2(self.style.indent, 0.0);
|
let indent = vec2(self.style.indent, 0.0);
|
||||||
|
let region_pos = self.cursor + indent;
|
||||||
let mut child_region = Region {
|
let mut child_region = Region {
|
||||||
ctx: self.ctx.clone(),
|
ctx: self.ctx.clone(),
|
||||||
layer: self.layer,
|
layer: self.layer,
|
||||||
|
@ -187,9 +212,9 @@ impl Region {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
dir: self.dir,
|
dir: self.dir,
|
||||||
align: Align::Min,
|
align: Align::Min,
|
||||||
cursor: self.cursor + indent,
|
rect: Rect::from_min_max(region_pos, self.rect.max()),
|
||||||
|
cursor: region_pos,
|
||||||
bounding_size: vec2(0.0, 0.0),
|
bounding_size: vec2(0.0, 0.0),
|
||||||
available_space: self.available_space - indent,
|
|
||||||
};
|
};
|
||||||
add_contents(&mut child_region);
|
add_contents(&mut child_region);
|
||||||
let size = child_region.bounding_size;
|
let size = child_region.bounding_size;
|
||||||
|
@ -198,16 +223,17 @@ impl Region {
|
||||||
|
|
||||||
/// Return a sub-region relative to the parent
|
/// Return a sub-region relative to the parent
|
||||||
pub fn relative_region(&mut self, rect: Rect) -> Region {
|
pub fn relative_region(&mut self, rect: Rect) -> Region {
|
||||||
|
let region_pos = self.cursor + rect.min().to_vec2();
|
||||||
Region {
|
Region {
|
||||||
ctx: self.ctx.clone(),
|
ctx: self.ctx.clone(),
|
||||||
layer: self.layer,
|
layer: self.layer,
|
||||||
style: self.style,
|
style: self.style,
|
||||||
id: self.id,
|
id: self.id,
|
||||||
dir: self.dir,
|
dir: self.dir,
|
||||||
cursor: self.cursor + rect.min().to_vec2(),
|
|
||||||
align: self.align,
|
align: self.align,
|
||||||
|
rect: Rect::from_min_max(region_pos, self.rect.max()),
|
||||||
|
cursor: region_pos,
|
||||||
bounding_size: vec2(0.0, 0.0),
|
bounding_size: vec2(0.0, 0.0),
|
||||||
available_space: rect.size(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,12 +241,12 @@ impl Region {
|
||||||
pub fn column(&mut self, column_position: Align, width: f32) -> Region {
|
pub fn column(&mut self, column_position: Align, width: f32) -> Region {
|
||||||
let x = match column_position {
|
let x = match column_position {
|
||||||
Align::Min => 0.0,
|
Align::Min => 0.0,
|
||||||
Align::Center => self.available_space.x / 2.0 - width / 2.0,
|
Align::Center => self.available_width() / 2.0 - width / 2.0,
|
||||||
Align::Max => self.available_space.x - width,
|
Align::Max => self.available_width() - width,
|
||||||
};
|
};
|
||||||
self.relative_region(Rect::from_min_size(
|
self.relative_region(Rect::from_min_size(
|
||||||
pos2(x, 0.0),
|
pos2(x, 0.0),
|
||||||
vec2(width, self.available_space.y),
|
vec2(width, self.available_height()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,9 +273,9 @@ impl Region {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
dir,
|
dir,
|
||||||
align,
|
align,
|
||||||
|
rect: Rect::from_min_max(self.cursor, self.rect.max()),
|
||||||
cursor: self.cursor,
|
cursor: self.cursor,
|
||||||
bounding_size: vec2(0.0, 0.0),
|
bounding_size: vec2(0.0, 0.0),
|
||||||
available_space: self.available_space,
|
|
||||||
};
|
};
|
||||||
add_contents(&mut child_region);
|
add_contents(&mut child_region);
|
||||||
let size = child_region.bounding_size;
|
let size = child_region.bounding_size;
|
||||||
|
@ -285,19 +311,22 @@ impl Region {
|
||||||
// TODO: ensure there is space
|
// TODO: ensure there is space
|
||||||
let padding = self.style.item_spacing.x;
|
let padding = self.style.item_spacing.x;
|
||||||
let total_padding = padding * (num_columns as f32 - 1.0);
|
let total_padding = padding * (num_columns as f32 - 1.0);
|
||||||
let column_width = (self.available_space.x - total_padding) / (num_columns as f32);
|
let column_width = (self.available_width() - total_padding) / (num_columns as f32);
|
||||||
|
|
||||||
let mut columns: Vec<Region> = (0..num_columns)
|
let mut columns: Vec<Region> = (0..num_columns)
|
||||||
.map(|col_idx| Region {
|
.map(|col_idx| {
|
||||||
|
let pos = self.cursor + vec2((col_idx as f32) * (column_width + padding), 0.0);
|
||||||
|
Region {
|
||||||
ctx: self.ctx.clone(),
|
ctx: self.ctx.clone(),
|
||||||
layer: self.layer,
|
layer: self.layer,
|
||||||
style: self.style,
|
style: self.style,
|
||||||
id: self.make_child_region_id(&("column", col_idx)),
|
id: self.make_child_region_id(&("column", col_idx)),
|
||||||
dir: Direction::Vertical,
|
dir: Direction::Vertical,
|
||||||
align: self.align,
|
align: self.align,
|
||||||
cursor: self.cursor + vec2((col_idx as f32) * (column_width + padding), 0.0),
|
rect: Rect::from_min_max(pos, pos2(pos.x + column_width, self.rect.max().y)),
|
||||||
|
cursor: pos,
|
||||||
bounding_size: vec2(0.0, 0.0),
|
bounding_size: vec2(0.0, 0.0),
|
||||||
available_space: vec2(column_width, self.available_space.y),
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -309,7 +338,7 @@ impl Region {
|
||||||
max_height = size.y.max(max_height);
|
max_height = size.y.max(max_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.reserve_space_without_padding(vec2(self.available_space.x, max_height));
|
self.reserve_space_without_padding(vec2(self.available_width(), max_height));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,21 +363,19 @@ impl Region {
|
||||||
if self.dir == Direction::Horizontal {
|
if self.dir == Direction::Horizontal {
|
||||||
pos.y += match self.align {
|
pos.y += match self.align {
|
||||||
Align::Min => 0.0,
|
Align::Min => 0.0,
|
||||||
Align::Center => 0.5 * (self.available_space.y - size.y),
|
Align::Center => 0.5 * (self.available_height() - size.y),
|
||||||
Align::Max => self.available_space.y - size.y,
|
Align::Max => self.available_height() - size.y,
|
||||||
};
|
};
|
||||||
self.cursor.x += size.x;
|
self.cursor.x += size.x;
|
||||||
self.available_space.x -= size.x;
|
|
||||||
self.bounding_size.x += size.x;
|
self.bounding_size.x += size.x;
|
||||||
self.bounding_size.y = self.bounding_size.y.max(size.y);
|
self.bounding_size.y = self.bounding_size.y.max(size.y);
|
||||||
} else {
|
} else {
|
||||||
pos.x += match self.align {
|
pos.x += match self.align {
|
||||||
Align::Min => 0.0,
|
Align::Min => 0.0,
|
||||||
Align::Center => 0.5 * (self.available_space.x - size.x),
|
Align::Center => 0.5 * (self.available_width() - size.x),
|
||||||
Align::Max => self.available_space.x - size.x,
|
Align::Max => self.available_width() - size.x,
|
||||||
};
|
};
|
||||||
self.cursor.y += size.y;
|
self.cursor.y += size.y;
|
||||||
self.available_space.y -= size.x;
|
|
||||||
self.bounding_size.y += size.y;
|
self.bounding_size.y += size.y;
|
||||||
self.bounding_size.x = self.bounding_size.x.max(size.x);
|
self.bounding_size.x = self.bounding_size.x.max(size.x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,8 @@ impl Texture {
|
||||||
self.height
|
self.height
|
||||||
));
|
));
|
||||||
let mut size = vec2(self.width as f32, self.height as f32);
|
let mut size = vec2(self.width as f32, self.height as f32);
|
||||||
if size.x > region.width() {
|
if size.x > region.available_width() {
|
||||||
size *= region.width() / size.x;
|
size *= region.available_width() / size.x;
|
||||||
}
|
}
|
||||||
let interact = region.reserve_space(size, None);
|
let interact = region.reserve_space(size, None);
|
||||||
let rect = interact.rect;
|
let rect = interact.rect;
|
||||||
|
|
|
@ -50,7 +50,7 @@ macro_rules! label {
|
||||||
impl Widget for Label {
|
impl Widget for Label {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let font = ®ion.fonts()[self.text_style];
|
let font = ®ion.fonts()[self.text_style];
|
||||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
let (text, text_size) = font.layout_multiline(&self.text, region.available_width());
|
||||||
let interact = region.reserve_space(text_size, None);
|
let interact = region.reserve_space(text_size, None);
|
||||||
region.add_text(interact.rect.min(), self.text_style, text, self.text_color);
|
region.add_text(interact.rect.min(), self.text_style, text, self.text_color);
|
||||||
region.response(interact)
|
region.response(interact)
|
||||||
|
@ -83,7 +83,7 @@ impl Widget for Button {
|
||||||
let id = region.make_position_id();
|
let id = region.make_position_id();
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = ®ion.fonts()[text_style];
|
let font = ®ion.fonts()[text_style];
|
||||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
let (text, text_size) = font.layout_multiline(&self.text, region.available_width());
|
||||||
let padding = region.style().button_padding;
|
let padding = region.style().button_padding;
|
||||||
let mut size = text_size + 2.0 * padding;
|
let mut size = text_size + 2.0 * padding;
|
||||||
size.y = size.y.max(region.style().clickable_diameter);
|
size.y = size.y.max(region.style().clickable_diameter);
|
||||||
|
@ -129,7 +129,7 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
let id = region.make_position_id();
|
let id = region.make_position_id();
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = ®ion.fonts()[text_style];
|
let font = ®ion.fonts()[text_style];
|
||||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
let (text, text_size) = font.layout_multiline(&self.text, region.available_width());
|
||||||
let interact = region.reserve_space(
|
let interact = region.reserve_space(
|
||||||
region.style().button_padding
|
region.style().button_padding
|
||||||
+ vec2(region.style().start_icon_width, 0.0)
|
+ vec2(region.style().start_icon_width, 0.0)
|
||||||
|
@ -203,7 +203,7 @@ impl Widget for RadioButton {
|
||||||
let id = region.make_position_id();
|
let id = region.make_position_id();
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = ®ion.fonts()[text_style];
|
let font = ®ion.fonts()[text_style];
|
||||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
let (text, text_size) = font.layout_multiline(&self.text, region.available_width());
|
||||||
let interact = region.reserve_space(
|
let interact = region.reserve_space(
|
||||||
region.style().button_padding
|
region.style().button_padding
|
||||||
+ vec2(region.style().start_icon_width, 0.0)
|
+ vec2(region.style().start_icon_width, 0.0)
|
||||||
|
@ -353,7 +353,7 @@ impl<'a> Widget for Slider<'a> {
|
||||||
let naked = Slider { text: None, ..self };
|
let naked = Slider { text: None, ..self };
|
||||||
|
|
||||||
if text_on_top {
|
if text_on_top {
|
||||||
let (text, text_size) = font.layout_multiline(&full_text, region.width());
|
let (text, text_size) = font.layout_multiline(&full_text, region.available_width());
|
||||||
let pos = region.reserve_space_without_padding(text_size);
|
let pos = region.reserve_space_without_padding(text_size);
|
||||||
region.add_text(pos, text_style, text, text_color);
|
region.add_text(pos, text_style, text, text_color);
|
||||||
naked.add_to(region)
|
naked.add_to(region)
|
||||||
|
@ -361,7 +361,8 @@ impl<'a> Widget for Slider<'a> {
|
||||||
region.columns(2, |columns| {
|
region.columns(2, |columns| {
|
||||||
let response = naked.add_to(&mut columns[0]);
|
let response = naked.add_to(&mut columns[0]);
|
||||||
|
|
||||||
columns[1].available_space.y = response.rect.size().y;
|
// columns[1].available_space.y = response.rect.size().y;
|
||||||
|
columns[1].rect.set_height(response.rect.size().y); // TODO: explain this line
|
||||||
columns[1].horizontal(Align::Center, |region| {
|
columns[1].horizontal(Align::Center, |region| {
|
||||||
region.add(Label::new(full_text));
|
region.add(Label::new(full_text));
|
||||||
});
|
});
|
||||||
|
@ -378,7 +379,7 @@ impl<'a> Widget for Slider<'a> {
|
||||||
let id = region.make_position_id();
|
let id = region.make_position_id();
|
||||||
let interact = region.reserve_space(
|
let interact = region.reserve_space(
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: region.available_space.x,
|
x: region.available_width(),
|
||||||
y: height,
|
y: height,
|
||||||
},
|
},
|
||||||
Some(id),
|
Some(id),
|
||||||
|
@ -472,7 +473,7 @@ impl Separator {
|
||||||
|
|
||||||
impl Widget for Separator {
|
impl Widget for Separator {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let available_space = region.available_space;
|
let available_space = region.available_space();
|
||||||
let (points, interact) = match region.direction() {
|
let (points, interact) = match region.direction() {
|
||||||
Direction::Horizontal => {
|
Direction::Horizontal => {
|
||||||
let interact = region.reserve_space(vec2(self.min_length, available_space.y), None);
|
let interact = region.reserve_space(vec2(self.min_length, available_space.y), None);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{layout::Direction, mesher::Path, widgets::*, *};
|
use crate::{mesher::Path, widgets::*, *};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct WindowState {
|
pub struct WindowState {
|
||||||
|
@ -54,19 +54,33 @@ impl Window {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shrink_to_fit_content(mut self, shrink_to_fit_content: bool) -> Self {
|
||||||
|
self.shrink_to_fit_content = shrink_to_fit_content;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_to_fit_content(mut self, expand_to_fit_content: bool) -> Self {
|
||||||
|
self.expand_to_fit_content = expand_to_fit_content;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn show<F>(self, ctx: &Arc<Context>, add_contents: F)
|
pub fn show<F>(self, ctx: &Arc<Context>, add_contents: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Region),
|
F: FnOnce(&mut Region),
|
||||||
{
|
{
|
||||||
let default_pos = self.default_pos.unwrap_or(pos2(100.0, 100.0)); // TODO
|
let default_pos = self.default_pos.unwrap_or(pos2(100.0, 100.0)); // TODO
|
||||||
let default_size = vec2(200.0, 50.0); // TODO
|
let default_size = vec2(200.0, 50.0); // TODO
|
||||||
|
let default_rect = Rect::from_min_size(default_pos, default_size);
|
||||||
|
|
||||||
let id = ctx.make_unique_id(&self.title, default_pos);
|
let id = ctx.make_unique_id(&self.title, default_pos);
|
||||||
|
|
||||||
let mut state = ctx
|
let (mut state, is_new_window) = match ctx.memory.lock().get_window(id) {
|
||||||
.memory
|
Some(state) => (state, false),
|
||||||
.lock()
|
None => {
|
||||||
.get_or_create_window(id, Rect::from_min_size(default_pos, default_size));
|
let state = WindowState { rect: default_rect };
|
||||||
|
(state, true)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let layer = Layer::Window(id);
|
let layer = Layer::Window(id);
|
||||||
let where_to_put_background = ctx.graphics.lock().layer(layer).len();
|
let where_to_put_background = ctx.graphics.lock().layer(layer).len();
|
||||||
|
@ -74,17 +88,11 @@ impl Window {
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let window_padding = style.window_padding;
|
let window_padding = style.window_padding;
|
||||||
|
|
||||||
let mut contents_region = Region {
|
let inner_rect = Rect::from_min_size(
|
||||||
ctx: ctx.clone(),
|
state.rect.min() + window_padding,
|
||||||
layer,
|
state.rect.size() - 2.0 * window_padding,
|
||||||
style,
|
);
|
||||||
id,
|
let mut contents_region = Region::new(ctx.clone(), layer, id, inner_rect);
|
||||||
dir: Direction::Vertical,
|
|
||||||
align: Align::Min,
|
|
||||||
cursor: state.rect.min() + window_padding,
|
|
||||||
bounding_size: vec2(0.0, 0.0),
|
|
||||||
available_space: state.rect.size() - 2.0 * window_padding,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Show top bar:
|
// Show top bar:
|
||||||
contents_region.add(Label::new(self.title).text_style(TextStyle::Heading));
|
contents_region.add(Label::new(self.title).text_style(TextStyle::Heading));
|
||||||
|
@ -104,7 +112,7 @@ impl Window {
|
||||||
new_outer_size = new_outer_size.min(desired_outer_size);
|
new_outer_size = new_outer_size.min(desired_outer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.expand_to_fit_content {
|
if self.expand_to_fit_content || is_new_window {
|
||||||
new_outer_size = new_outer_size.max(desired_outer_size);
|
new_outer_size = new_outer_size.max(desired_outer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ fn main() {
|
||||||
|
|
||||||
emigui.new_frame(raw_input);
|
emigui.new_frame(raw_input);
|
||||||
let mut region = emigui.background_region();
|
let mut region = emigui.background_region();
|
||||||
let mut region = region.left_column(region.width().min(480.0));
|
let mut region = region.left_column(region.available_width().min(480.0));
|
||||||
region.set_align(Align::Min);
|
region.set_align(Align::Min);
|
||||||
region.add(label!("Emigui running inside of Glium").text_style(emigui::TextStyle::Heading));
|
region.add(label!("Emigui running inside of Glium").text_style(emigui::TextStyle::Heading));
|
||||||
if region.add(Button::new("Quit")).clicked {
|
if region.add(Button::new("Quit")).clicked {
|
||||||
|
@ -94,12 +94,18 @@ fn main() {
|
||||||
// TODO: Make it even simpler to show a window
|
// TODO: Make it even simpler to show a window
|
||||||
Window::new("Test window").show(region.ctx(), |region| {
|
Window::new("Test window").show(region.ctx(), |region| {
|
||||||
region.add(label!("Grab the window and move it around!"));
|
region.add(label!("Grab the window and move it around!"));
|
||||||
|
|
||||||
|
region.add(label!(
|
||||||
|
"This window can be reisized, but not smaller than the contents."
|
||||||
|
));
|
||||||
});
|
});
|
||||||
Window::new("Another test window")
|
Window::new("Resize me!")
|
||||||
.default_pos(pos2(400.0, 100.0))
|
.default_pos(pos2(400.0, 100.0))
|
||||||
|
.expand_to_fit_content(false)
|
||||||
.show(region.ctx(), |region| {
|
.show(region.ctx(), |region| {
|
||||||
region.add(label!("This might be on top of the other window?"));
|
region.add(label!(
|
||||||
region.add(label!("Second line of text"));
|
"This window may shrink so small that its contents no longer fit."
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
let mesh = emigui.paint();
|
let mesh = emigui.paint();
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl State {
|
||||||
self.emigui.new_frame(raw_input);
|
self.emigui.new_frame(raw_input);
|
||||||
|
|
||||||
let mut region = self.emigui.background_region();
|
let mut region = self.emigui.background_region();
|
||||||
let mut region = region.centered_column(region.width().min(480.0));
|
let mut region = region.centered_column(region.available_width().min(480.0));
|
||||||
region.add(label!("Emigui!").text_style(TextStyle::Heading));
|
region.add(label!("Emigui!").text_style(TextStyle::Heading));
|
||||||
region.add(label!("Emigui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."));
|
region.add(label!("Emigui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."));
|
||||||
region.add(label!(
|
region.add(label!(
|
||||||
|
|
Loading…
Reference in a new issue