Replace Arc<Context> with struct CtxRef

This commit is contained in:
Emil Ernerfeldt 2020-12-19 14:48:04 +01:00
parent ce0ea74c9f
commit 01c65b0dcb
24 changed files with 286 additions and 300 deletions

View file

@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed 🔧
* `Arc<Context>` has been replaced with `CtxRef` everywhere.
* Slight tweak of the default `Style` and font sizes.
* `SidePanel::left` and `TopPanel::top` now takes `impl Hash` as first argument.
* A `Window` may now cover an existing `CentralPanel`.

View file

@ -4,7 +4,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let raw_input = egui::RawInput::default();
{
let mut ctx = egui::Context::new();
let mut ctx = egui::CtxRef::default();
let mut demo_windows = egui::demos::DemoWindows::default();
c.bench_function("demo_windows_minimal", |b| {
@ -17,7 +17,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
}
{
let mut ctx = egui::Context::new();
let mut ctx = egui::CtxRef::default();
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
let mut demo_windows = egui::demos::DemoWindows::default();
@ -31,7 +31,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
}
{
let mut ctx = egui::Context::new();
let mut ctx = egui::CtxRef::default();
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
let mut demo_windows = egui::demos::DemoWindows::default();
ctx.begin_frame(raw_input.clone());
@ -44,7 +44,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
}
{
let mut ctx = egui::Context::new();
let mut ctx = egui::CtxRef::default();
ctx.begin_frame(raw_input);
egui::CentralPanel::default().show(&ctx, |ui| {
c.bench_function("label", |b| {

View file

@ -7,8 +7,6 @@
// TODO: move egui/src/app.rs to own crate, e.g. egui_framework ?
use crate::Context;
/// Implement this trait to write apps that can be compiled both natively using the [`egui_glium`](https://crates.io/crates/egui_glium) crate,
/// and deployed as a web site using the [`egui_web`](https://crates.io/crates/egui_web) crate.
pub trait App {
@ -24,15 +22,11 @@ pub trait App {
/// Called once before the first frame.
/// Allows you to do setup code and to call `ctx.set_fonts()`.
/// Optional.
fn setup(&mut self, _ctx: &std::sync::Arc<Context>) {}
fn setup(&mut self, _ctx: &crate::CtxRef) {}
/// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn ui(
&mut self,
ctx: &std::sync::Arc<Context>,
integration_context: &mut IntegrationContext<'_>,
);
fn ui(&mut self, ctx: &crate::CtxRef, integration_context: &mut IntegrationContext<'_>);
/// Called once on shutdown. Allows you to save state.
fn on_exit(&mut self, _storage: &mut dyn Storage) {}

View file

@ -2,7 +2,7 @@
//! It has no frame or own size. It is potentially movable.
//! It is the foundation for windows and popups.
use std::{fmt::Debug, hash::Hash, sync::Arc};
use std::{fmt::Debug, hash::Hash};
use crate::*;
@ -103,7 +103,7 @@ pub(crate) struct Prepared {
}
impl Area {
pub(crate) fn begin(self, ctx: &Arc<Context>) -> Prepared {
pub(crate) fn begin(self, ctx: &CtxRef) -> Prepared {
let Area {
id,
movable,
@ -131,7 +131,7 @@ impl Area {
}
}
pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> Response {
pub fn show(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) -> Response {
let prepared = self.begin(ctx);
let mut content_ui = prepared.content_ui(ctx);
add_contents(&mut content_ui);
@ -148,7 +148,7 @@ impl Prepared {
&mut self.state
}
pub(crate) fn content_ui(&self, ctx: &Arc<Context>) -> Ui {
pub(crate) fn content_ui(&self, ctx: &CtxRef) -> Ui {
let max_rect = Rect::from_min_size(self.state.pos, Vec2::infinity());
let clip_rect = max_rect
.expand(ctx.style().visuals.clip_rect_margin)
@ -163,7 +163,7 @@ impl Prepared {
}
#[allow(clippy::needless_pass_by_value)] // intentional to swallow up `content_ui`.
pub(crate) fn end(self, ctx: &Arc<Context>, content_ui: Ui) -> Response {
pub(crate) fn end(self, ctx: &CtxRef, content_ui: Ui) -> Response {
let Prepared {
layer_id,
mut state,

View file

@ -3,7 +3,6 @@
//! the only places where you can put you widgets.
use crate::*;
use std::sync::Arc;
// ----------------------------------------------------------------------------
@ -27,11 +26,7 @@ impl SidePanel {
}
impl SidePanel {
pub fn show<R>(
self,
ctx: &Arc<Context>,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
let Self { id, max_width } = self;
let mut panel_rect = ctx.available_rect();
@ -80,11 +75,7 @@ impl TopPanel {
}
impl TopPanel {
pub fn show<R>(
self,
ctx: &Arc<Context>,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
let Self { id, max_height } = self;
let max_height = max_height.unwrap_or_else(|| ctx.style().spacing.interact_size.y);
@ -122,11 +113,7 @@ impl TopPanel {
pub struct CentralPanel {}
impl CentralPanel {
pub fn show<R>(
self,
ctx: &Arc<Context>,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> (R, Response) {
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
let Self {} = self;
let panel_rect = ctx.available_rect();

View file

@ -1,9 +1,7 @@
use std::sync::Arc;
use crate::*;
/// Show a tooltip at the current mouse position (if any).
pub fn show_tooltip(ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) {
pub fn show_tooltip(ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) {
let tooltip_rect = ctx.memory().tooltip_rect;
let window_pos = if let Some(tooltip_rect) = tooltip_rect {
@ -23,7 +21,7 @@ pub fn show_tooltip(ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) {
}
/// Show a tooltip at the current mouse position (if any).
pub fn show_tooltip_text(ctx: &Arc<Context>, text: impl Into<String>) {
pub fn show_tooltip_text(ctx: &CtxRef, text: impl Into<String>) {
show_tooltip(ctx, |ui| {
ui.add(crate::widgets::Label::new(text));
})
@ -31,7 +29,7 @@ pub fn show_tooltip_text(ctx: &Arc<Context>, text: impl Into<String>) {
/// Show a pop-over window.
fn show_popup(
ctx: &Arc<Context>,
ctx: &CtxRef,
id: Id,
window_pos: Pos2,
add_contents: impl FnOnce(&mut Ui),

View file

@ -1,7 +1,5 @@
// WARNING: the code in here is horrible. It is a behemoth that needs breaking up into simpler parts.
use std::sync::Arc;
use crate::{paint::*, widgets::*, *};
use super::*;
@ -183,13 +181,13 @@ impl<'open> Window<'open> {
}
impl<'open> Window<'open> {
pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> Option<Response> {
pub fn show(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) -> Option<Response> {
self.show_impl(ctx, Box::new(add_contents))
}
fn show_impl<'c>(
self,
ctx: &Arc<Context>,
ctx: &CtxRef,
add_contents: Box<dyn FnOnce(&mut Ui) + 'c>,
) -> Option<Response> {
let Window {

View file

@ -101,6 +101,236 @@ impl FrameState {
// ----------------------------------------------------------------------------
/// A wrapper around `CtxRef`.
/// This is how you will normally access a [`Context`].
#[derive(Clone)]
pub struct CtxRef(std::sync::Arc<Context>);
impl std::ops::Deref for CtxRef {
type Target = Context;
fn deref(&self) -> &Context {
self.0.deref()
}
}
impl AsRef<Context> for CtxRef {
fn as_ref(&self) -> &Context {
self.0.as_ref()
}
}
impl std::borrow::Borrow<Context> for CtxRef {
fn borrow(&self) -> &Context {
self.0.borrow()
}
}
impl std::cmp::PartialEq for CtxRef {
fn eq(&self, other: &CtxRef) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl Default for CtxRef {
fn default() -> Self {
Self(Arc::new(Context {
// Start with painting an extra frame to compensate for some widgets
// that take two frames before they "settle":
repaint_requests: AtomicU32::new(1),
..Context::default()
}))
}
}
impl CtxRef {
/// Call at the start of every frame.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
pub fn begin_frame(&mut self, new_input: RawInput) {
let mut self_: Context = (*self.0).clone();
self_.begin_frame_mut(new_input);
*self = Self(Arc::new(self_));
}
// ---------------------------------------------------------------------
/// If the given `Id` is not unique, an error will be printed at the given position.
/// Call this for `Id`:s that need interaction or persistence.
pub(crate) fn register_interaction_id(&self, id: Id, new_pos: Pos2) {
let prev_pos = self.memory().used_ids.insert(id, new_pos);
if let Some(prev_pos) = prev_pos {
if prev_pos.distance(new_pos) < 0.1 {
// Likely same Widget being interacted with twice, which is fine.
return;
}
let show_error = |pos: Pos2, text: String| {
let painter = self.debug_painter();
let rect = painter.error(pos, text);
if let Some(mouse_pos) = self.input.mouse.pos {
if rect.contains(mouse_pos) {
painter.error(
rect.left_bottom() + vec2(2.0, 4.0),
"ID clashes happens when things like Windows or CollpasingHeaders share names,\n\
or when things like ScrollAreas and Resize areas aren't given unique id_source:s.",
);
}
}
};
let id_str = id.short_debug_format();
if prev_pos.distance(new_pos) < 4.0 {
show_error(new_pos, format!("Double use of ID {}", id_str));
} else {
show_error(prev_pos, format!("First use of ID {}", id_str));
show_error(new_pos, format!("Second use of ID {}", id_str));
}
// TODO: a tooltip explaining this.
}
}
// ---------------------------------------------------------------------
/// Use `ui.interact` instead
pub(crate) fn interact(
&self,
layer_id: LayerId,
clip_rect: Rect,
item_spacing: Vec2,
rect: Rect,
id: Option<Id>,
sense: Sense,
) -> Response {
let interact_rect = rect.expand2((0.5 * item_spacing).min(Vec2::splat(5.0))); // make it easier to click
let hovered = self.contains_mouse(layer_id, clip_rect, interact_rect);
let has_kb_focus = id.map(|id| self.memory().has_kb_focus(id)).unwrap_or(false);
// If the the focus is lost after the call to interact,
// this will be `false`, so `TextEdit` also sets this manually.
let lost_kb_focus = id
.map(|id| self.memory().lost_kb_focus(id))
.unwrap_or(false);
if id.is_none() || sense == Sense::nothing() || !layer_id.allow_interaction() {
// Not interested or allowed input:
return Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
};
}
let id = id.unwrap();
self.register_interaction_id(id, rect.min);
let mut memory = self.memory();
memory.interaction.click_interest |= hovered && sense.click;
memory.interaction.drag_interest |= hovered && sense.drag;
let active =
memory.interaction.click_id == Some(id) || memory.interaction.drag_id == Some(id);
if self.input.mouse.pressed {
if hovered {
let mut response = Response {
ctx: self.clone(),
sense,
rect,
hovered: true,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
};
if sense.click && memory.interaction.click_id.is_none() {
// start of a click
memory.interaction.click_id = Some(id);
response.active = true;
}
if sense.drag
&& (memory.interaction.drag_id.is_none() || memory.interaction.drag_is_window)
{
// start of a drag
memory.interaction.drag_id = Some(id);
memory.interaction.drag_is_window = false;
memory.window_interaction = None; // HACK: stop moving windows (if any)
response.active = true;
}
response
} else {
// miss
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
}
}
} else if self.input.mouse.released {
let clicked = hovered && active && self.input.mouse.could_be_click;
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked,
double_clicked: clicked && self.input.mouse.double_click,
active,
has_kb_focus,
lost_kb_focus,
}
} else if self.input.mouse.down {
Response {
ctx: self.clone(),
sense,
rect,
hovered: hovered && active,
clicked: false,
double_clicked: false,
active,
has_kb_focus,
lost_kb_focus,
}
} else {
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active,
has_kb_focus,
lost_kb_focus,
}
}
}
pub fn debug_painter(&self) -> Painter {
Painter::new(self.clone(), LayerId::debug(), self.input.screen_rect())
}
}
// ----------------------------------------------------------------------------
/// Thi is the first thing you need when working with Egui.
///
/// Contains the input state, memory, options and output.
@ -149,13 +379,10 @@ impl Clone for Context {
}
impl Context {
pub fn new() -> Arc<Self> {
Arc::new(Self {
// Start with painting an extra frame to compensate for some widgets
// that take two frames before they "settle":
repaint_requests: AtomicU32::new(1),
..Self::default()
})
#[allow(clippy::new_ret_no_self)]
#[deprecated = "Use CtxRef::default() instead"]
pub fn new() -> CtxRef {
CtxRef::default()
}
/// How much space is still available after panels has been added.
@ -289,14 +516,6 @@ impl Context {
// ---------------------------------------------------------------------
/// Call at the start of every frame.
/// 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);
*self = Arc::new(self_);
}
fn begin_frame_mut(&mut self, new_raw_input: RawInput) {
self.memory().begin_frame(&self.input, &new_raw_input);
@ -385,45 +604,6 @@ impl Context {
// ---------------------------------------------------------------------
/// If the given `Id` is not unique, an error will be printed at the given position.
/// Call this for `Id`:s that need interaction or persistence.
pub(crate) fn register_interaction_id(self: &Arc<Self>, id: Id, new_pos: Pos2) {
let prev_pos = self.memory().used_ids.insert(id, new_pos);
if let Some(prev_pos) = prev_pos {
if prev_pos.distance(new_pos) < 0.1 {
// Likely same Widget being interacted with twice, which is fine.
return;
}
let show_error = |pos: Pos2, text: String| {
let painter = self.debug_painter();
let rect = painter.error(pos, text);
if let Some(mouse_pos) = self.input.mouse.pos {
if rect.contains(mouse_pos) {
painter.error(
rect.left_bottom() + vec2(2.0, 4.0),
"ID clashes happens when things like Windows or CollpasingHeaders share names,\n\
or when things like ScrollAreas and Resize areas aren't given unique id_source:s.",
);
}
}
};
let id_str = id.short_debug_format();
if prev_pos.distance(new_pos) < 4.0 {
show_error(new_pos, format!("Double use of ID {}", id_str));
} else {
show_error(prev_pos, format!("First use of ID {}", id_str));
show_error(new_pos, format!("Second use of ID {}", id_str));
}
// TODO: a tooltip explaining this.
}
}
// ---------------------------------------------------------------------
/// Is the mouse over any Egui area?
pub fn is_mouse_over_area(&self) -> bool {
if let Some(mouse_pos) = self.input.mouse.pos {
@ -477,137 +657,6 @@ impl Context {
false
}
}
/// Use `ui.interact` instead
pub(crate) fn interact(
self: &Arc<Self>,
layer_id: LayerId,
clip_rect: Rect,
item_spacing: Vec2,
rect: Rect,
id: Option<Id>,
sense: Sense,
) -> Response {
let interact_rect = rect.expand2((0.5 * item_spacing).min(Vec2::splat(5.0))); // make it easier to click
let hovered = self.contains_mouse(layer_id, clip_rect, interact_rect);
let has_kb_focus = id.map(|id| self.memory().has_kb_focus(id)).unwrap_or(false);
// If the the focus is lost after the call to interact,
// this will be `false`, so `TextEdit` also sets this manually.
let lost_kb_focus = id
.map(|id| self.memory().lost_kb_focus(id))
.unwrap_or(false);
if id.is_none() || sense == Sense::nothing() || !layer_id.allow_interaction() {
// Not interested or allowed input:
return Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
};
}
let id = id.unwrap();
self.register_interaction_id(id, rect.min);
let mut memory = self.memory();
memory.interaction.click_interest |= hovered && sense.click;
memory.interaction.drag_interest |= hovered && sense.drag;
let active =
memory.interaction.click_id == Some(id) || memory.interaction.drag_id == Some(id);
if self.input.mouse.pressed {
if hovered {
let mut response = Response {
ctx: self.clone(),
sense,
rect,
hovered: true,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
};
if sense.click && memory.interaction.click_id.is_none() {
// start of a click
memory.interaction.click_id = Some(id);
response.active = true;
}
if sense.drag
&& (memory.interaction.drag_id.is_none() || memory.interaction.drag_is_window)
{
// start of a drag
memory.interaction.drag_id = Some(id);
memory.interaction.drag_is_window = false;
memory.window_interaction = None; // HACK: stop moving windows (if any)
response.active = true;
}
response
} else {
// miss
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus,
lost_kb_focus,
}
}
} else if self.input.mouse.released {
let clicked = hovered && active && self.input.mouse.could_be_click;
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked,
double_clicked: clicked && self.input.mouse.double_click,
active,
has_kb_focus,
lost_kb_focus,
}
} else if self.input.mouse.down {
Response {
ctx: self.clone(),
sense,
rect,
hovered: hovered && active,
clicked: false,
double_clicked: false,
active,
has_kb_focus,
lost_kb_focus,
}
} else {
Response {
ctx: self.clone(),
sense,
rect,
hovered,
clicked: false,
double_clicked: false,
active,
has_kb_focus,
lost_kb_focus,
}
}
}
}
/// ## Animation
@ -633,13 +682,6 @@ impl Context {
}
}
/// ## Painting
impl Context {
pub fn debug_painter(self: &Arc<Self>) -> Painter {
Painter::new(self.clone(), LayerId::debug(), self.input.screen_rect())
}
}
impl Context {
pub fn settings_ui(&self, ui: &mut Ui) {
use crate::containers::*;

View file

@ -1,5 +1,4 @@
use crate::{app, demos, util::History, Context, Ui};
use std::sync::Arc;
use crate::{app, demos, util::History, CtxRef, Ui};
// ----------------------------------------------------------------------------
@ -282,11 +281,7 @@ impl app::App for DemoApp {
"Egui Demo"
}
fn ui(
&mut self,
ctx: &Arc<Context>,
integration_context: &mut crate::app::IntegrationContext<'_>,
) {
fn ui(&mut self, ctx: &CtxRef, integration_context: &mut crate::app::IntegrationContext<'_>) {
self.frame_history
.on_new_frame(ctx.input().time, integration_context.info.cpu_usage);

View file

@ -1,5 +1,3 @@
use std::sync::Arc;
use crate::{containers::*, demos::*, *};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
@ -17,7 +15,7 @@ impl Demo for DancingStrings {
"♫ Dancing Strings"
}
fn show(&mut self, ctx: &Arc<Context>, open: &mut bool) {
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
Window::new(self.name())
.open(open)
.default_size(vec2(512.0, 256.0))

View file

@ -1,9 +1,7 @@
use std::sync::Arc;
use crate::{
app,
demos::{self, Demo},
Context, Resize, ScrollArea, Ui, Window,
CtxRef, Resize, ScrollArea, Ui, Window,
};
// ----------------------------------------------------------------------------
@ -52,7 +50,7 @@ impl Demos {
}
}
pub fn show(&mut self, ctx: &Arc<Context>) {
pub fn show(&mut self, ctx: &CtxRef) {
for (ref mut open, demo) in &mut self.demos {
demo.show(ctx, open);
}
@ -87,7 +85,7 @@ impl DemoWindows {
/// `sidebar_ui` can be used to optionally show some things in the sidebar
pub fn ui(
&mut self,
ctx: &Arc<Context>,
ctx: &CtxRef,
env: &DemoEnvironment,
tex_allocator: &mut Option<&mut dyn app::TextureAllocator>,
sidebar_ui: impl FnOnce(&mut Ui),
@ -147,7 +145,7 @@ impl DemoWindows {
/// Show the open windows.
fn windows(
&mut self,
ctx: &Arc<Context>,
ctx: &CtxRef,
env: &DemoEnvironment,
tex_allocator: &mut Option<&mut dyn app::TextureAllocator>,
) {
@ -206,7 +204,7 @@ impl DemoWindows {
self.resize_windows(ctx);
}
fn resize_windows(&mut self, ctx: &Arc<Context>) {
fn resize_windows(&mut self, ctx: &CtxRef) {
let open = &mut self.open_windows.resize;
Window::new("resizable")

View file

@ -100,7 +100,7 @@ impl Demo for DragAndDropDemo {
"✋ Drag and Drop"
}
fn show(&mut self, ctx: &std::sync::Arc<Context>, open: &mut bool) {
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
Window::new(self.name())
.open(open)
.default_size(vec2(256.0, 256.0))

View file

@ -45,7 +45,7 @@ impl demos::Demo for FontBook {
"🔤 Font Book"
}
fn show(&mut self, ctx: &std::sync::Arc<crate::Context>, open: &mut bool) {
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
Window::new(self.name()).open(open).show(ctx, |ui| {
use demos::View;
self.ui(ui);

View file

@ -1,5 +1,3 @@
use std::sync::Arc;
use crate::{containers::*, widgets::*, *};
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
@ -31,12 +29,7 @@ impl Default for FractalClock {
}
impl FractalClock {
pub fn window(
&mut self,
ctx: &Arc<Context>,
open: &mut bool,
seconds_since_midnight: Option<f64>,
) {
pub fn window(&mut self, ctx: &CtxRef, open: &mut bool, seconds_since_midnight: Option<f64>) {
Window::new("🕑 Fractal Clock")
.open(open)
.default_size(vec2(512.0, 512.0))

View file

@ -40,7 +40,7 @@ pub trait Demo {
fn name(&self) -> &str;
/// Show windows, etc
fn show(&mut self, ctx: &std::sync::Arc<crate::Context>, open: &mut bool);
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool);
}
// ----------------------------------------------------------------------------

View file

@ -8,7 +8,7 @@ impl demos::Demo for Tests {
"📋 Tests"
}
fn show(&mut self, ctx: &std::sync::Arc<crate::Context>, open: &mut bool) {
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
Window::new(self.name()).open(open).show(ctx, |ui| {
use demos::View;
self.ui(ui);

View file

@ -8,7 +8,7 @@
//! Use one of `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`. For instace:
//!
//! ```
//! # let mut ctx = egui::Context::new();
//! # let mut ctx = egui::CtxRef::default();
//! # ctx.begin_frame(Default::default());
//! egui::CentralPanel::default().show(&ctx, |ui| {
//! ui.label("Hello");
@ -19,7 +19,7 @@
//! To write your own integration for Egui you need to do this:
//!
//! ``` ignore
//! let mut egui_ctx = egui::Context::new();
//! let mut egui_ctx = egui::CtxRef::default();
//!
//! // Game loop:
//! loop {
@ -96,7 +96,7 @@ pub mod widgets;
pub use {
align::Align,
containers::*,
context::Context,
context::{Context, CtxRef},
demos::DemoApp,
id::Id,
input::*,
@ -129,7 +129,7 @@ pub(crate) fn has_debug_assertions() -> bool {
#[test]
fn test_egui_e2e() {
let mut demo_windows = crate::demos::DemoWindows::default();
let mut ctx = crate::Context::new();
let mut ctx = crate::CtxRef::default();
let raw_input = crate::RawInput::default();
const NUM_FRAMES: usize = 5;

View file

@ -1,19 +1,17 @@
use std::sync::Arc;
use crate::{
align::{anchor_rect, Align, LEFT_TOP},
color,
layers::PaintCmdIdx,
math::{Pos2, Rect, Vec2},
paint::{Fonts, Galley, PaintCmd, Stroke, TextStyle},
Context, LayerId, Srgba,
CtxRef, LayerId, Srgba,
};
/// Helper to paint shapes and text to a specific region on a specific layer.
#[derive(Clone)]
pub struct Painter {
/// Source of fonts and destination of paint commands
ctx: Arc<Context>,
ctx: CtxRef,
/// Where we paint
layer_id: LayerId,
@ -24,7 +22,7 @@ pub struct Painter {
}
impl Painter {
pub fn new(ctx: Arc<Context>, layer_id: LayerId, clip_rect: Rect) -> Self {
pub fn new(ctx: CtxRef, layer_id: LayerId, clip_rect: Rect) -> Self {
Self {
ctx,
layer_id,
@ -61,7 +59,7 @@ impl Painter {
/// ## Accessors etc
impl Painter {
pub(crate) fn ctx(&self) -> &Arc<Context> {
pub(crate) fn ctx(&self) -> &CtxRef {
&self.ctx
}

View file

@ -1,6 +1,4 @@
use std::sync::Arc;
use crate::{math::Rect, Context, Ui};
use crate::{math::Rect, CtxRef, Ui};
// ----------------------------------------------------------------------------
@ -57,7 +55,7 @@ impl Default for CursorIcon {
pub struct Response {
// CONTEXT:
/// Used for optionally showing a tooltip
pub ctx: Arc<Context>,
pub ctx: CtxRef,
// IN:
/// The area of the screen we are talking about
@ -143,7 +141,7 @@ impl Response {
/// A logical "or" operation.
/// For instance `a.union(b).hovered` means "was either a or b hovered?".
pub fn union(&self, other: Self) -> Self {
assert!(Arc::ptr_eq(&self.ctx, &other.ctx));
assert!(self.ctx == other.ctx);
Self {
ctx: other.ctx,
rect: self.rect.union(other.rect),

View file

@ -41,13 +41,7 @@ impl Ui {
// ------------------------------------------------------------------------
// Creation:
pub fn new(
ctx: Arc<Context>,
layer_id: LayerId,
id: Id,
max_rect: Rect,
clip_rect: Rect,
) -> Self {
pub fn new(ctx: CtxRef, layer_id: LayerId, id: Id, max_rect: Rect, clip_rect: Rect) -> Self {
let style = ctx.style();
let layout = Layout::default();
let region = layout.region_from_max_rect(max_rect);
@ -77,7 +71,7 @@ impl Ui {
/// Empty `Ui` for use in tests.
pub fn __test() -> Self {
let mut ctx = Context::new();
let mut ctx = CtxRef::default();
ctx.begin_frame(Default::default());
let id = Id::new("__test");
let layer_id = LayerId::new(Order::Middle, id);
@ -106,7 +100,7 @@ impl Ui {
self.style = style.into();
}
pub fn ctx(&self) -> &Arc<Context> {
pub fn ctx(&self) -> &CtxRef {
self.painter.ctx()
}

View file

@ -72,7 +72,7 @@ pub fn run(mut storage: Box<dyn egui::app::Storage>, mut app: Box<dyn App>) -> !
let repaint_signal = std::sync::Arc::new(GliumRepaintSignal(event_loop.create_proxy()));
let mut ctx = egui::Context::new();
let mut ctx = egui::CtxRef::default();
*ctx.memory() = egui::app::get_value(storage.as_ref(), EGUI_MEMORY_KEY).unwrap_or_default();
app.setup(&ctx);

View file

@ -8,7 +8,7 @@ pub use egui::{
// ----------------------------------------------------------------------------
pub struct WebBackend {
ctx: Arc<egui::Context>,
ctx: egui::CtxRef,
painter: webgl::Painter,
previous_frame_time: Option<f32>,
frame_start: Option<f64>,
@ -17,7 +17,7 @@ pub struct WebBackend {
impl WebBackend {
pub fn new(canvas_id: &str) -> Result<Self, JsValue> {
let ctx = egui::Context::new();
let ctx = egui::CtxRef::default();
load_memory(&ctx);
Ok(Self {
ctx,

View file

@ -21,11 +21,7 @@ impl egui::app::App for ExampleApp {
/// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn ui(
&mut self,
ctx: &std::sync::Arc<egui::Context>,
integration_context: &mut egui::app::IntegrationContext,
) {
fn ui(&mut self, ctx: &egui::CtxRef, integration_context: &mut egui::app::IntegrationContext) {
let ExampleApp { name, age } = self;
// Example used in `README.md`.

View file

@ -45,11 +45,7 @@ impl egui::app::App for ExampleApp {
/// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn ui(
&mut self,
ctx: &std::sync::Arc<egui::Context>,
integration_context: &mut egui::app::IntegrationContext,
) {
fn ui(&mut self, ctx: &egui::CtxRef, integration_context: &mut egui::app::IntegrationContext) {
if let Some(receiver) = &mut self.in_progress {
// Are we there yet?
if let Ok(result) = receiver.try_recv() {