Compare commits
1 commit
master
...
strong-ids
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2c76949b9b |
5 changed files with 103 additions and 54 deletions
|
@ -32,7 +32,7 @@ impl State {
|
|||
/// This forms the base of the `Window` container.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Area {
|
||||
id: Id,
|
||||
strong_id: StrongId,
|
||||
movable: bool,
|
||||
interactable: bool,
|
||||
order: Order,
|
||||
|
@ -41,9 +41,9 @@ pub struct Area {
|
|||
}
|
||||
|
||||
impl Area {
|
||||
pub fn new(id_source: impl Hash) -> Self {
|
||||
pub fn new(strong_id_source: impl Hash) -> Self {
|
||||
Self {
|
||||
id: Id::new(id_source),
|
||||
strong_id: StrongId::new(strong_id_source),
|
||||
movable: true,
|
||||
interactable: true,
|
||||
order: Order::Middle,
|
||||
|
@ -53,7 +53,7 @@ impl Area {
|
|||
}
|
||||
|
||||
pub fn layer(&self) -> LayerId {
|
||||
LayerId::new(self.order, self.id)
|
||||
LayerId::new(self.order, self.strong_id)
|
||||
}
|
||||
|
||||
/// moveable by dragging the area?
|
||||
|
@ -105,7 +105,7 @@ pub(crate) struct Prepared {
|
|||
impl Area {
|
||||
pub(crate) fn begin(self, ctx: &Arc<Context>) -> Prepared {
|
||||
let Area {
|
||||
id,
|
||||
strong_id,
|
||||
movable,
|
||||
order,
|
||||
interactable,
|
||||
|
@ -113,9 +113,9 @@ impl Area {
|
|||
fixed_pos,
|
||||
} = self;
|
||||
|
||||
let layer_id = LayerId::new(order, id);
|
||||
let layer_id = LayerId::new(order, strong_id);
|
||||
|
||||
let state = ctx.memory().areas.get(id).cloned();
|
||||
let state = ctx.memory().areas.get(strong_id).cloned();
|
||||
let mut state = state.unwrap_or_else(|| State {
|
||||
pos: default_pos.unwrap_or_else(|| automatic_area_position(ctx)),
|
||||
size: Vec2::zero(),
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//! the only places where you can put you widgets.
|
||||
|
||||
use crate::*;
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -11,14 +12,17 @@ use std::sync::Arc;
|
|||
///
|
||||
/// Panels should be added before adding any `Window`s.
|
||||
pub struct SidePanel {
|
||||
id: Id,
|
||||
strong_id: Id,
|
||||
max_width: f32,
|
||||
}
|
||||
|
||||
impl SidePanel {
|
||||
/// The given `max_width` is a soft maximum (as always), and the actual panel may be smaller or larger.
|
||||
pub fn left(id: Id, max_width: f32) -> Self {
|
||||
Self { id, max_width }
|
||||
pub fn left(strong_id_source: impl Hash, max_width: f32) -> Self {
|
||||
Self {
|
||||
strong_id: StrongId::new(strong_id_source),
|
||||
max_width,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +32,10 @@ impl SidePanel {
|
|||
ctx: &Arc<Context>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> (R, Response) {
|
||||
let Self { id, max_width } = self;
|
||||
let Self {
|
||||
strong_id,
|
||||
max_width,
|
||||
} = self;
|
||||
|
||||
let mut panel_rect = ctx.available_rect();
|
||||
panel_rect.max.x = panel_rect.max.x.at_most(panel_rect.min.x + max_width);
|
||||
|
@ -36,7 +43,7 @@ impl SidePanel {
|
|||
let layer_id = LayerId::background();
|
||||
|
||||
let clip_rect = ctx.input().screen_rect();
|
||||
let mut panel_ui = Ui::new(ctx.clone(), layer_id, id, panel_rect, clip_rect);
|
||||
let mut panel_ui = Ui::new(ctx.clone(), layer_id, strong_id, panel_rect, clip_rect);
|
||||
|
||||
let frame = Frame::panel(&ctx.style());
|
||||
let r = frame.show(&mut panel_ui, |ui| {
|
||||
|
@ -59,16 +66,16 @@ impl SidePanel {
|
|||
///
|
||||
/// Panels should be added before adding any `Window`s.
|
||||
pub struct TopPanel {
|
||||
id: Id,
|
||||
strong_id: StrongId,
|
||||
max_height: Option<f32>,
|
||||
}
|
||||
|
||||
impl TopPanel {
|
||||
/// Default height is that of `interact_size.y` (i.e. a button),
|
||||
/// but the panel will expand as needed.
|
||||
pub fn top(id: Id) -> Self {
|
||||
pub fn top(strong_id_source: impl Hash) -> Self {
|
||||
Self {
|
||||
id,
|
||||
strong_id: StrongId::new(strong_id_source),
|
||||
max_height: None,
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +87,10 @@ impl TopPanel {
|
|||
ctx: &Arc<Context>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> (R, Response) {
|
||||
let Self { id, max_height } = self;
|
||||
let Self {
|
||||
strong_id,
|
||||
max_height,
|
||||
} = self;
|
||||
let max_height = max_height.unwrap_or_else(|| ctx.style().spacing.interact_size.y);
|
||||
|
||||
let mut panel_rect = ctx.available_rect();
|
||||
|
@ -89,7 +99,7 @@ impl TopPanel {
|
|||
let layer_id = LayerId::background();
|
||||
|
||||
let clip_rect = ctx.input().screen_rect();
|
||||
let mut panel_ui = Ui::new(ctx.clone(), layer_id, id, panel_rect, clip_rect);
|
||||
let mut panel_ui = Ui::new(ctx.clone(), layer_id, strong_id, panel_rect, clip_rect);
|
||||
|
||||
let frame = Frame::panel(&ctx.style());
|
||||
let r = frame.show(&mut panel_ui, |ui| {
|
||||
|
@ -127,10 +137,10 @@ impl CentralPanel {
|
|||
let panel_rect = ctx.available_rect();
|
||||
|
||||
let layer_id = LayerId::background();
|
||||
let id = Id::new("central_panel");
|
||||
let strong_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 mut panel_ui = Ui::new(ctx.clone(), layer_id, strong_id, panel_rect, clip_rect);
|
||||
|
||||
let frame = Frame::background(&ctx.style());
|
||||
let r = frame.show(&mut panel_ui, |ui| add_contents(ui));
|
||||
|
|
|
@ -40,14 +40,14 @@ impl Id {
|
|||
Self(1)
|
||||
}
|
||||
|
||||
pub fn new(source: impl Hash) -> Id {
|
||||
pub fn new(source: impl Hash) -> Self {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = ahash::AHasher::default();
|
||||
source.hash(&mut hasher);
|
||||
Id(hasher.finish())
|
||||
}
|
||||
|
||||
pub fn with(self, child: impl Hash) -> Id {
|
||||
pub fn with(self, child: impl Hash) -> Self {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = ahash::AHasher::default();
|
||||
hasher.write_u64(self.0);
|
||||
|
@ -59,3 +59,49 @@ impl Id {
|
|||
format!("{:04X}", self.0 as u16)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// This is an identifier that must be unique over long time.
|
||||
/// Used for storing state, like window position, scroll amount, etc.
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct StrongId(u64);
|
||||
|
||||
impl StrongId {
|
||||
pub fn background() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
pub fn tooltip() -> Self {
|
||||
Self(1)
|
||||
}
|
||||
|
||||
pub fn new(source: impl Hash) -> Self {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = ahash::AHasher::default();
|
||||
source.hash(&mut hasher);
|
||||
Id(hasher.finish())
|
||||
}
|
||||
|
||||
pub fn with(self, child: impl Hash) -> Self {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = ahash::AHasher::default();
|
||||
hasher.write_u64(self.0);
|
||||
child.hash(&mut hasher);
|
||||
Id(hasher.finish())
|
||||
}
|
||||
|
||||
pub(crate) fn short_debug_format(&self) -> String {
|
||||
format!("{:04X}", self.0 as u16)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Ok to weaken a `StrongId`
|
||||
impl From<StrongId> for Id {
|
||||
fn from(strong: StrongId) -> Self {
|
||||
Id(strong.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::{
|
||||
area,
|
||||
cache::Cache,
|
||||
collapsing_header, menu,
|
||||
paint::color::{Hsva, Srgba},
|
||||
resize, scroll_area,
|
||||
widgets::text_edit,
|
||||
window, Id, LayerId, Pos2, Rect,
|
||||
};
|
||||
use crate::{cache::Cache, color::Hsva, *};
|
||||
|
||||
/// The data that Egui persists between frames.
|
||||
///
|
||||
|
@ -24,11 +16,11 @@ pub struct Memory {
|
|||
pub(crate) interaction: Interaction,
|
||||
|
||||
// states of various types of widgets
|
||||
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
||||
pub(crate) collapsing_headers: HashMap<StrongId, collapsing_header::State>,
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
|
||||
pub(crate) resize: HashMap<Id, resize::State>,
|
||||
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
||||
pub(crate) menu_bar: HashMap<StrongId, menu::BarState>,
|
||||
pub(crate) resize: HashMap<StrongId, resize::State>,
|
||||
pub(crate) scroll_areas: HashMap<StrongId, scroll_area::State>,
|
||||
pub(crate) text_edit: HashMap<Id, text_edit::State>,
|
||||
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
|
@ -197,7 +189,7 @@ impl Memory {
|
|||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct Areas {
|
||||
areas: HashMap<Id, area::State>,
|
||||
areas: HashMap<StrongId, area::State>,
|
||||
/// Top is last
|
||||
order: Vec<LayerId>,
|
||||
visible_last_frame: HashSet<LayerId>,
|
||||
|
|
|
@ -7,12 +7,11 @@ use crate::{color::*, containers::*, layout::*, mutex::MutexGuard, paint::*, wid
|
|||
/// Represents a region of the screen
|
||||
/// with a type of layout (horizontal or vertical).
|
||||
pub struct Ui {
|
||||
/// ID of this ui.
|
||||
/// Generated based on id of parent ui together with
|
||||
/// another source of child identity (e.g. window title).
|
||||
/// Acts like a namespace for child uis.
|
||||
/// Hopefully unique.
|
||||
id: Id,
|
||||
/// Used to seed more StrongId:s.
|
||||
strong_id: StrongId,
|
||||
|
||||
/// For automatic Id generation.
|
||||
auto_id: Id,
|
||||
|
||||
painter: Painter,
|
||||
|
||||
|
@ -49,11 +48,6 @@ pub struct Ui {
|
|||
/// If something has already been added, this will point ot style.spacing.item_spacing beyond the latest child.
|
||||
/// The cursor can thus be style.spacing.item_spacing pixels outside of the min_rect.
|
||||
cursor: Pos2, // TODO: move into Layout?
|
||||
|
||||
/// How many children has been added to us?
|
||||
/// This is only used to create a unique interact ID for some widgets
|
||||
/// that work as long as no other widgets are added/removed while interacting.
|
||||
child_count: usize,
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
|
@ -63,7 +57,7 @@ impl Ui {
|
|||
pub fn new(
|
||||
ctx: Arc<Context>,
|
||||
layer_id: LayerId,
|
||||
id: Id,
|
||||
strong_id: StrongId,
|
||||
max_rect: Rect,
|
||||
clip_rect: Rect,
|
||||
) -> Self {
|
||||
|
@ -73,14 +67,14 @@ impl Ui {
|
|||
let min_size = Vec2::zero(); // TODO: From Style
|
||||
let min_rect = layout.rect_from_cursor_size(cursor, min_size);
|
||||
Ui {
|
||||
id,
|
||||
strong_id,
|
||||
auto_id: strong_id.with("auto"),
|
||||
painter: Painter::new(ctx, layer_id, clip_rect),
|
||||
min_rect,
|
||||
max_rect,
|
||||
style,
|
||||
layout,
|
||||
cursor,
|
||||
child_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +360,7 @@ impl Ui {
|
|||
/// # `Id` creation
|
||||
impl Ui {
|
||||
/// Use this to generate widget ids for widgets that have persistent state in `Memory`.
|
||||
pub fn make_persistent_id<IdSource>(&self, id_source: IdSource) -> Id
|
||||
pub fn make_persistent_id<IdSource>(&self, id_source: IdSource) -> StrongId
|
||||
where
|
||||
IdSource: Hash + std::fmt::Debug,
|
||||
{
|
||||
|
@ -379,15 +373,22 @@ impl Ui {
|
|||
/// Call AFTER allocating new space for your widget.
|
||||
// TODO: return from `allocate_space` ?
|
||||
pub fn make_position_id(&self) -> Id {
|
||||
self.id.with(self.child_count)
|
||||
let id = self.id.with(self.child_count);
|
||||
// self.ctx().register_unique_id(id, self.cursor, "position"); // NO: position may change until we interact
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
/// # Interaction
|
||||
impl Ui {
|
||||
pub fn interact(&self, rect: Rect, id: Id, sense: Sense) -> Response {
|
||||
self.ctx()
|
||||
.interact(self.layer_id(), self.clip_rect(), rect, Some(id), sense)
|
||||
pub fn interact(&self, rect: Rect, id: impl Into<Id>, sense: Sense) -> Response {
|
||||
self.ctx().interact(
|
||||
self.layer_id(),
|
||||
self.clip_rect(),
|
||||
rect,
|
||||
Some(id.into()),
|
||||
sense,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn interact_hover(&self, rect: Rect) -> Response {
|
||||
|
|
Loading…
Reference in a new issue