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`).
|
||||
* You can no longer throw windows
|
||||
* `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
|
||||
|
||||
|
|
|
@ -36,11 +36,12 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
{
|
||||
let mut ctx = egui::Context::new();
|
||||
ctx.begin_frame(raw_input);
|
||||
let mut ui = ctx.background_ui();
|
||||
c.bench_function("label", |b| {
|
||||
b.iter(|| {
|
||||
ui.label(egui::demos::LOREM_IPSUM_LONG);
|
||||
})
|
||||
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
c.bench_function("label", |b| {
|
||||
b.iter(|| {
|
||||
ui.label(egui::demos::LOREM_IPSUM_LONG);
|
||||
})
|
||||
});
|
||||
});
|
||||
// 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.
|
||||
pub trait App {
|
||||
/// 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(
|
||||
&mut self,
|
||||
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 {
|
||||
Self {
|
||||
margin: Vec2::new(8.0, 2.0),
|
||||
|
|
|
@ -17,7 +17,7 @@ pub use {
|
|||
collapsing_header::*,
|
||||
combo_box::*,
|
||||
frame::Frame,
|
||||
panel::{SidePanel, TopPanel},
|
||||
panel::{CentralPanel, SidePanel, TopPanel},
|
||||
popup::*,
|
||||
resize::Resize,
|
||||
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 std::sync::Arc;
|
||||
|
@ -103,3 +105,41 @@ impl TopPanel {
|
|||
(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,
|
||||
|
||||
/// 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>>,
|
||||
/// How much space is used by panels.
|
||||
used_by_panels: Mutex<Option<Rect>>,
|
||||
|
||||
// The output of a frame:
|
||||
graphics: Mutex<GraphicLayers>,
|
||||
|
@ -67,6 +69,7 @@ impl Clone for Context {
|
|||
animation_manager: self.animation_manager.clone(),
|
||||
input: self.input.clone(),
|
||||
available_rect: self.available_rect.clone(),
|
||||
used_by_panels: self.used_by_panels.clone(),
|
||||
graphics: self.graphics.clone(),
|
||||
output: self.output.clone(),
|
||||
used_ids: self.used_ids.clone(),
|
||||
|
@ -199,10 +202,7 @@ impl Context {
|
|||
// ---------------------------------------------------------------------
|
||||
|
||||
/// Call at the start of every frame.
|
||||
/// To get a `Ui` to place widgets into you one or more of:
|
||||
/// * `SidePanel` or `TopPanel`
|
||||
/// * `Window`
|
||||
/// * `Context::background_ui()`
|
||||
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||
pub fn begin_frame(self: &mut Arc<Self>, new_input: RawInput) {
|
||||
let mut self_: Self = (**self).clone();
|
||||
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.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();
|
||||
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()`.
|
||||
pub(crate) fn allocate_left_panel(&self, panel_rect: Rect) {
|
||||
let mut remainder = self.available_rect();
|
||||
remainder.min.x = panel_rect.max.x;
|
||||
*self.available_rect.lock() = Some(remainder);
|
||||
self.register_panel(panel_rect);
|
||||
}
|
||||
|
||||
/// Shrink `available_rect()`.
|
||||
|
@ -310,6 +292,38 @@ impl Context {
|
|||
let mut remainder = self.available_rect();
|
||||
remainder.min.y = panel_rect.max.y;
|
||||
*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 {
|
||||
/// 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(
|
||||
&mut self,
|
||||
ctx: &std::sync::Arc<egui::Context>,
|
||||
|
|
Loading…
Reference in a new issue