Replace ctx.background_ui with CentralPanel
This commit is contained in:
parent
44a7cac046
commit
4b549a773e
8 changed files with 100 additions and 35 deletions
|
@ -11,7 +11,7 @@
|
||||||
* Fix a bug where some regions would slowly grow for non-integral scales (`pixels_per_point`).
|
* Fix a bug where some regions would slowly grow for non-integral scales (`pixels_per_point`).
|
||||||
* You can no longer throw windows
|
* You can no longer throw windows
|
||||||
* `Context::begin_frame()` no longer returns anything.
|
* `Context::begin_frame()` no longer returns anything.
|
||||||
* Put your widgets into a `SidePanel`, `TopPanel`, `Window` or into `ctx.background_ui()`.
|
* Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
|
|
||||||
## 0.2.0 - 2020-10-10
|
## 0.2.0 - 2020-10-10
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,12 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
{
|
{
|
||||||
let mut ctx = egui::Context::new();
|
let mut ctx = egui::Context::new();
|
||||||
ctx.begin_frame(raw_input);
|
ctx.begin_frame(raw_input);
|
||||||
let mut ui = ctx.background_ui();
|
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||||
c.bench_function("label", |b| {
|
c.bench_function("label", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
ui.label(egui::demos::LOREM_IPSUM_LONG);
|
ui.label(egui::demos::LOREM_IPSUM_LONG);
|
||||||
})
|
})
|
||||||
|
});
|
||||||
});
|
});
|
||||||
// let _ = ctx.end_frame(); // skip, because tessellating all that text is slow
|
// let _ = ctx.end_frame(); // skip, because tessellating all that text is slow
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::Context;
|
||||||
/// and deployed as a web site using the [`egui_web`](https://crates.io/crates/egui_web) crate.
|
/// and deployed as a web site using the [`egui_web`](https://crates.io/crates/egui_web) crate.
|
||||||
pub trait App {
|
pub trait App {
|
||||||
/// Called each time the UI needs repainting, which may be many times per second.
|
/// Called each time the UI needs repainting, which may be many times per second.
|
||||||
/// Put your widgets into a `SidePanel`, `TopPanel`, `Window` or into `ctx.background_ui()`.
|
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
fn ui(
|
fn ui(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &std::sync::Arc<Context>,
|
ctx: &std::sync::Arc<Context>,
|
||||||
|
|
|
@ -31,6 +31,16 @@ impl Frame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Suitable for a fullscreen app
|
||||||
|
pub fn background(style: &Style) -> Self {
|
||||||
|
Self {
|
||||||
|
margin: Vec2::new(8.0, 8.0),
|
||||||
|
corner_radius: 0.0,
|
||||||
|
fill: style.visuals.widgets.noninteractive.bg_fill,
|
||||||
|
stroke: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn panel(style: &Style) -> Self {
|
pub(crate) fn panel(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
margin: Vec2::new(8.0, 2.0),
|
margin: Vec2::new(8.0, 2.0),
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub use {
|
||||||
collapsing_header::*,
|
collapsing_header::*,
|
||||||
combo_box::*,
|
combo_box::*,
|
||||||
frame::Frame,
|
frame::Frame,
|
||||||
panel::{SidePanel, TopPanel},
|
panel::{CentralPanel, SidePanel, TopPanel},
|
||||||
popup::*,
|
popup::*,
|
||||||
resize::Resize,
|
resize::Resize,
|
||||||
scroll_area::ScrollArea,
|
scroll_area::ScrollArea,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//! Panels
|
//! Panels are fixed `Ui` regions.
|
||||||
|
//! Together with `Window` and `Area`:s they are
|
||||||
|
//! the only places where you can put you widgets.
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -103,3 +105,41 @@ impl TopPanel {
|
||||||
(r, response)
|
(r, response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// A panel that covers the remainder of the screen,
|
||||||
|
/// i.e. whatever area is left after adding other panels.
|
||||||
|
///
|
||||||
|
/// `CentralPanel` should be added after all other panels.
|
||||||
|
/// Any `Window`s and `Area`s will cover the `CentralPanel`.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CentralPanel {}
|
||||||
|
|
||||||
|
impl CentralPanel {
|
||||||
|
pub fn show<R>(
|
||||||
|
self,
|
||||||
|
ctx: &Arc<Context>,
|
||||||
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
|
) -> (R, Response) {
|
||||||
|
let Self {} = self;
|
||||||
|
|
||||||
|
let panel_rect = ctx.available_rect();
|
||||||
|
|
||||||
|
let layer_id = LayerId::background();
|
||||||
|
let id = Id::new("central_panel");
|
||||||
|
|
||||||
|
let clip_rect = ctx.input().screen_rect();
|
||||||
|
let mut panel_ui = Ui::new(ctx.clone(), layer_id, id, panel_rect, clip_rect);
|
||||||
|
|
||||||
|
let frame = Frame::background(&ctx.style());
|
||||||
|
let r = frame.show(&mut panel_ui, |ui| add_contents(ui));
|
||||||
|
|
||||||
|
let panel_rect = panel_ui.min_rect();
|
||||||
|
let response = panel_ui.interact_hover(panel_rect);
|
||||||
|
|
||||||
|
ctx.allocate_central_panel(panel_rect);
|
||||||
|
|
||||||
|
(r, response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -43,8 +43,10 @@ pub struct Context {
|
||||||
input: InputState,
|
input: InputState,
|
||||||
|
|
||||||
/// Starts off as the screen_rect, shrinks as panels are added.
|
/// Starts off as the screen_rect, shrinks as panels are added.
|
||||||
/// Becomes `Rect::nothing()` when `Context::background_ui` is called.
|
/// Becomes `Rect::nothing()` after a `CentralPanel` is finished.
|
||||||
available_rect: Mutex<Option<Rect>>,
|
available_rect: Mutex<Option<Rect>>,
|
||||||
|
/// How much space is used by panels.
|
||||||
|
used_by_panels: Mutex<Option<Rect>>,
|
||||||
|
|
||||||
// The output of a frame:
|
// The output of a frame:
|
||||||
graphics: Mutex<GraphicLayers>,
|
graphics: Mutex<GraphicLayers>,
|
||||||
|
@ -67,6 +69,7 @@ impl Clone for Context {
|
||||||
animation_manager: self.animation_manager.clone(),
|
animation_manager: self.animation_manager.clone(),
|
||||||
input: self.input.clone(),
|
input: self.input.clone(),
|
||||||
available_rect: self.available_rect.clone(),
|
available_rect: self.available_rect.clone(),
|
||||||
|
used_by_panels: self.used_by_panels.clone(),
|
||||||
graphics: self.graphics.clone(),
|
graphics: self.graphics.clone(),
|
||||||
output: self.output.clone(),
|
output: self.output.clone(),
|
||||||
used_ids: self.used_ids.clone(),
|
used_ids: self.used_ids.clone(),
|
||||||
|
@ -199,10 +202,7 @@ impl Context {
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
/// Call at the start of every frame.
|
/// Call at the start of every frame.
|
||||||
/// To get a `Ui` to place widgets into you one or more of:
|
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
/// * `SidePanel` or `TopPanel`
|
|
||||||
/// * `Window`
|
|
||||||
/// * `Context::background_ui()`
|
|
||||||
pub fn begin_frame(self: &mut Arc<Self>, new_input: RawInput) {
|
pub fn begin_frame(self: &mut Arc<Self>, new_input: RawInput) {
|
||||||
let mut self_: Self = (**self).clone();
|
let mut self_: Self = (**self).clone();
|
||||||
self_.begin_frame_mut(new_input);
|
self_.begin_frame_mut(new_input);
|
||||||
|
@ -216,6 +216,7 @@ impl Context {
|
||||||
|
|
||||||
self.input = std::mem::take(&mut self.input).begin_frame(new_raw_input);
|
self.input = std::mem::take(&mut self.input).begin_frame(new_raw_input);
|
||||||
*self.available_rect.lock() = Some(self.input.screen_rect());
|
*self.available_rect.lock() = Some(self.input.screen_rect());
|
||||||
|
*self.used_by_panels.lock() = Some(Rect::nothing());
|
||||||
|
|
||||||
let mut font_definitions = self.options.lock().font_definitions.clone();
|
let mut font_definitions = self.options.lock().font_definitions.clone();
|
||||||
font_definitions.pixels_per_point = self.input.pixels_per_point();
|
font_definitions.pixels_per_point = self.input.pixels_per_point();
|
||||||
|
@ -278,31 +279,12 @@ impl Context {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
/// A `Ui` that covers the whole background (not used by panels).
|
|
||||||
///
|
|
||||||
/// This is the same area that `Window`s are put in to,
|
|
||||||
/// so either put your UI into `background_ui()` or into `Window`s.
|
|
||||||
///
|
|
||||||
/// Call this at most once per frame.
|
|
||||||
pub fn background_ui(self: &Arc<Self>) -> Ui {
|
|
||||||
let rect = self.available_rect();
|
|
||||||
debug_assert!(
|
|
||||||
rect != Rect::nothing(),
|
|
||||||
"You already called `background_ui()` once this frame!"
|
|
||||||
);
|
|
||||||
*self.available_rect.lock() = Some(Rect::nothing()); // Nothing left after this
|
|
||||||
|
|
||||||
let layer_id = LayerId::background();
|
|
||||||
Ui::new(self.clone(), layer_id, layer_id.id, rect, rect)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// Shrink `available_rect()`.
|
/// Shrink `available_rect()`.
|
||||||
pub(crate) fn allocate_left_panel(&self, panel_rect: Rect) {
|
pub(crate) fn allocate_left_panel(&self, panel_rect: Rect) {
|
||||||
let mut remainder = self.available_rect();
|
let mut remainder = self.available_rect();
|
||||||
remainder.min.x = panel_rect.max.x;
|
remainder.min.x = panel_rect.max.x;
|
||||||
*self.available_rect.lock() = Some(remainder);
|
*self.available_rect.lock() = Some(remainder);
|
||||||
|
self.register_panel(panel_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shrink `available_rect()`.
|
/// Shrink `available_rect()`.
|
||||||
|
@ -310,6 +292,38 @@ impl Context {
|
||||||
let mut remainder = self.available_rect();
|
let mut remainder = self.available_rect();
|
||||||
remainder.min.y = panel_rect.max.y;
|
remainder.min.y = panel_rect.max.y;
|
||||||
*self.available_rect.lock() = Some(remainder);
|
*self.available_rect.lock() = Some(remainder);
|
||||||
|
self.register_panel(panel_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shrink `available_rect()`.
|
||||||
|
pub(crate) fn allocate_central_panel(&self, panel_rect: Rect) {
|
||||||
|
let mut available_rect = self.available_rect.lock();
|
||||||
|
debug_assert!(
|
||||||
|
*available_rect != Some(Rect::nothing()),
|
||||||
|
"You already created a `CentralPanel` this frame!"
|
||||||
|
);
|
||||||
|
*available_rect = Some(Rect::nothing()); // Nothing left after this
|
||||||
|
self.register_panel(panel_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_panel(&self, panel_rect: Rect) {
|
||||||
|
let mut used = self.used_by_panels.lock();
|
||||||
|
*used = Some(used.unwrap_or(Rect::nothing()).union(panel_rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How much space is used by panels and windows.
|
||||||
|
pub fn used_rect(&self) -> Rect {
|
||||||
|
let mut used = self.used_by_panels.lock().unwrap_or(Rect::nothing());
|
||||||
|
for window in self.memory().areas.visible_windows() {
|
||||||
|
used = used.union(window.rect());
|
||||||
|
}
|
||||||
|
used
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How much space is used by panels and windows.
|
||||||
|
/// You can shrink your Egui area to this size and still fit all Egui components.
|
||||||
|
pub fn used_size(&self) -> Vec2 {
|
||||||
|
self.used_rect().max - Pos2::new(0.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct MyApp {
|
||||||
|
|
||||||
impl egui::app::App for MyApp {
|
impl egui::app::App for MyApp {
|
||||||
/// Called each time the UI needs repainting, which may be many times per second.
|
/// Called each time the UI needs repainting, which may be many times per second.
|
||||||
/// Put your widgets into a `SidePanel`, `TopPanel`, `Window` or into `ctx.background_ui()`.
|
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
fn ui(
|
fn ui(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &std::sync::Arc<egui::Context>,
|
ctx: &std::sync::Arc<egui::Context>,
|
||||||
|
|
Loading…
Reference in a new issue