Replace Arc<Context> with struct CtxRef
This commit is contained in:
parent
ce0ea74c9f
commit
01c65b0dcb
24 changed files with 286 additions and 300 deletions
|
@ -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`.
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue