mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 21:00:03 -04:00
Store/restore emigui memory state (window positions, sizes etc)
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
use crate::{layout::Direction, *};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[serde(default)]
|
||||
pub(crate) struct State {
|
||||
pub open: bool,
|
||||
pub toggle_time: f64,
|
||||
open: bool,
|
||||
#[serde(skip)] // Times are relative, and we don't want to continue animations anyway
|
||||
toggle_time: f64,
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
open: false,
|
||||
toggle_time: -std::f64::INFINITY,
|
||||
toggle_time: -f64::INFINITY,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +61,7 @@ impl CollapsingHeader {
|
||||
);
|
||||
|
||||
let state = {
|
||||
let mut memory = region.ctx.memory.lock();
|
||||
let mut memory = region.ctx.memory();
|
||||
let mut state = memory.collapsing_headers.entry(id).or_insert(State {
|
||||
open: default_open,
|
||||
..Default::default()
|
||||
|
||||
@@ -7,8 +7,8 @@ use std::{fmt::Debug, hash::Hash, sync::Arc};
|
||||
|
||||
use crate::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct State {
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub(crate) struct State {
|
||||
/// Last known pos
|
||||
pub pos: Pos2,
|
||||
|
||||
@@ -50,7 +50,7 @@ impl Floating {
|
||||
let id = ctx.register_unique_id(self.id, "Floating", default_pos);
|
||||
let layer = Layer::Window(id);
|
||||
|
||||
let (mut state, _is_new) = match ctx.memory.lock().get_floating(id) {
|
||||
let (mut state, _is_new) = match ctx.memory().get_floating(id) {
|
||||
Some(state) => (state, false),
|
||||
None => {
|
||||
let state = State {
|
||||
@@ -90,15 +90,15 @@ impl Floating {
|
||||
state.pos = state.pos.round();
|
||||
|
||||
if move_interact.active || mouse_pressed_on_floating(ctx, id) {
|
||||
ctx.memory.lock().move_floating_to_top(id);
|
||||
ctx.memory().move_floating_to_top(id);
|
||||
}
|
||||
ctx.memory.lock().set_floating_state(id, state);
|
||||
ctx.memory().set_floating_state(id, state);
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_pressed_on_floating(ctx: &Context, id: Id) -> bool {
|
||||
if let Some(mouse_pos) = ctx.input.mouse_pos {
|
||||
ctx.input.mouse_pressed && ctx.memory.lock().layer_at(mouse_pos) == Layer::Window(id)
|
||||
ctx.input.mouse_pressed && ctx.memory().layer_at(mouse_pos) == Layer::Window(id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![allow(unused_variables)] // TODO
|
||||
use crate::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct State {
|
||||
pub size: Vec2,
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub(crate) struct State {
|
||||
size: Vec2,
|
||||
}
|
||||
|
||||
// TODO: auto-shink/grow should be part of another container!
|
||||
@@ -229,7 +229,7 @@ impl Resize {
|
||||
paint_resize_corner(region, &corner_rect, &corner_interact);
|
||||
|
||||
if corner_interact.hovered || corner_interact.active {
|
||||
region.ctx().output.lock().cursor_icon = CursorIcon::ResizeNwSe;
|
||||
region.ctx().output().cursor_icon = CursorIcon::ResizeNwSe;
|
||||
}
|
||||
|
||||
region.memory().resize.insert(id, state);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct State {
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
|
||||
#[serde(default)]
|
||||
pub(crate) struct State {
|
||||
/// Positive offset means scrolling down/right
|
||||
pub offset: Vec2,
|
||||
offset: Vec2,
|
||||
|
||||
pub show_scroll: bool, // TODO: default value?
|
||||
show_scroll: bool, // TODO: default value?
|
||||
}
|
||||
|
||||
// TODO: rename VScroll
|
||||
@@ -49,8 +50,7 @@ impl ScrollArea {
|
||||
|
||||
let scroll_area_id = outer_region.id.with("scroll_area");
|
||||
let mut state = ctx
|
||||
.memory
|
||||
.lock()
|
||||
.memory()
|
||||
.scroll_areas
|
||||
.get(&scroll_area_id)
|
||||
.cloned()
|
||||
@@ -105,7 +105,7 @@ impl ScrollArea {
|
||||
}
|
||||
|
||||
// TODO: check that nothing else is being inteacted with
|
||||
if outer_region.contains_mouse(&outer_rect) && ctx.memory.lock().active_id.is_none() {
|
||||
if outer_region.contains_mouse(&outer_rect) && ctx.memory().active_id.is_none() {
|
||||
state.offset.y -= ctx.input.scroll_delta.y;
|
||||
}
|
||||
|
||||
@@ -194,9 +194,7 @@ impl ScrollArea {
|
||||
state.show_scroll = show_scroll_this_frame;
|
||||
|
||||
outer_region
|
||||
.ctx()
|
||||
.memory
|
||||
.lock()
|
||||
.memory()
|
||||
.scroll_areas
|
||||
.insert(scroll_area_id, state);
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ pub struct Context {
|
||||
/// Raw input from last frame. Use `input()` instead.
|
||||
pub(crate) last_raw_input: RawInput,
|
||||
pub(crate) input: GuiInput,
|
||||
pub(crate) memory: Mutex<Memory>,
|
||||
memory: Mutex<Memory>,
|
||||
pub(crate) graphics: Mutex<GraphicLayers>,
|
||||
|
||||
pub output: Mutex<Output>,
|
||||
output: Mutex<Output>,
|
||||
|
||||
/// Used to debug name clashes of e.g. windows
|
||||
used_ids: Mutex<HashMap<Id, Pos2>>,
|
||||
@@ -51,6 +51,31 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn memory(&self) -> parking_lot::MutexGuard<Memory> {
|
||||
self.memory.lock()
|
||||
}
|
||||
|
||||
pub fn output(&self) -> parking_lot::MutexGuard<Output> {
|
||||
self.output.lock()
|
||||
}
|
||||
|
||||
pub fn input(&self) -> &GuiInput {
|
||||
&self.input
|
||||
}
|
||||
|
||||
/// Raw input from last frame. Use `input()` instead.
|
||||
pub fn last_raw_input(&self) -> &RawInput {
|
||||
&self.last_raw_input
|
||||
}
|
||||
|
||||
pub fn style(&self) -> Style {
|
||||
*self.style.lock()
|
||||
}
|
||||
|
||||
pub fn set_style(&self, style: Style) {
|
||||
*self.style.lock() = style;
|
||||
}
|
||||
|
||||
/// Useful for pixel-perfect rendering
|
||||
pub fn round_to_pixel(&self, point: f32) -> f32 {
|
||||
(point * self.input.pixels_per_point).round() / self.input.pixels_per_point
|
||||
@@ -64,23 +89,6 @@ impl Context {
|
||||
vec2(self.round_to_pixel(vec.x), self.round_to_pixel(vec.y))
|
||||
}
|
||||
|
||||
/// Raw input from last frame. Use `input()` instead.
|
||||
pub fn last_raw_input(&self) -> &RawInput {
|
||||
&self.last_raw_input
|
||||
}
|
||||
|
||||
pub fn input(&self) -> &GuiInput {
|
||||
&self.input
|
||||
}
|
||||
|
||||
pub fn style(&self) -> Style {
|
||||
*self.style.lock()
|
||||
}
|
||||
|
||||
pub fn set_style(&self, style: Style) {
|
||||
*self.style.lock() = style;
|
||||
}
|
||||
|
||||
// TODO: move
|
||||
pub fn begin_frame(&mut self, gui_input: GuiInput) {
|
||||
self.used_ids.lock().clear();
|
||||
|
||||
@@ -12,8 +12,8 @@ struct Stats {
|
||||
/// Encapsulates input, layout and painting for ease of use.
|
||||
/// TODO: merge into Context
|
||||
pub struct Emigui {
|
||||
pub last_input: RawInput,
|
||||
pub ctx: Arc<Context>,
|
||||
last_input: RawInput,
|
||||
ctx: Arc<Context>,
|
||||
stats: Stats,
|
||||
mesher_options: MesherOptions,
|
||||
}
|
||||
@@ -28,13 +28,17 @@ impl Emigui {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ctx(&self) -> &Arc<Context> {
|
||||
&self.ctx
|
||||
}
|
||||
|
||||
pub fn texture(&self) -> &Texture {
|
||||
self.ctx.fonts.texture()
|
||||
}
|
||||
|
||||
pub fn begin_frame(&mut self, new_input: RawInput) {
|
||||
if !self.last_input.mouse_down || self.last_input.mouse_pos.is_none() {
|
||||
self.ctx.memory.lock().active_id = None;
|
||||
self.ctx.memory().active_id = None;
|
||||
}
|
||||
|
||||
let gui_input = GuiInput::from_last_and_new(&self.last_input, &new_input);
|
||||
|
||||
@@ -31,7 +31,7 @@ use std::{collections::hash_map::DefaultHasher, hash::Hash};
|
||||
|
||||
use crate::math::Pos2;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Id(u64);
|
||||
|
||||
impl Id {
|
||||
|
||||
@@ -5,12 +5,15 @@ use crate::{
|
||||
Id, Layer, Pos2, Rect,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct Memory {
|
||||
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
||||
#[serde(skip)]
|
||||
pub(crate) active_id: Option<Id>,
|
||||
|
||||
/// The widget with keyboard focus (i.e. a text input field).
|
||||
#[serde(skip)]
|
||||
pub(crate) kb_focus_id: Option<Id>,
|
||||
|
||||
// states of various types of widgets
|
||||
@@ -24,11 +27,11 @@ pub struct Memory {
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub fn get_floating(&mut self, id: Id) -> Option<floating::State> {
|
||||
pub(crate) fn get_floating(&mut self, id: Id) -> Option<floating::State> {
|
||||
self.floating.get(&id).cloned()
|
||||
}
|
||||
|
||||
pub fn set_floating_state(&mut self, id: Id, state: floating::State) {
|
||||
pub(crate) fn set_floating_state(&mut self, id: Id, state: floating::State) {
|
||||
let did_insert = self.floating.insert(id, state).is_none();
|
||||
if did_insert {
|
||||
self.floating_order.push(id);
|
||||
|
||||
@@ -119,11 +119,11 @@ impl Region {
|
||||
}
|
||||
|
||||
pub fn memory(&self) -> parking_lot::MutexGuard<Memory> {
|
||||
self.ctx.memory.lock()
|
||||
self.ctx.memory()
|
||||
}
|
||||
|
||||
pub fn output(&self) -> parking_lot::MutexGuard<Output> {
|
||||
self.ctx.output.lock()
|
||||
self.ctx.output()
|
||||
}
|
||||
|
||||
pub fn fonts(&self) -> &Fonts {
|
||||
|
||||
@@ -101,10 +101,10 @@ impl Widget for Hyperlink {
|
||||
let (text, text_size) = font.layout_multiline(&self.text, region.available_width());
|
||||
let interact = region.reserve_space(text_size, Some(id));
|
||||
if interact.hovered {
|
||||
region.ctx().output.lock().cursor_icon = CursorIcon::PointingHand;
|
||||
region.ctx().output().cursor_icon = CursorIcon::PointingHand;
|
||||
}
|
||||
if interact.clicked {
|
||||
region.ctx().output.lock().open_url = Some(self.url);
|
||||
region.ctx().output().open_url = Some(self.url);
|
||||
}
|
||||
|
||||
if interact.hovered {
|
||||
|
||||
@@ -57,7 +57,7 @@ impl<'t> Widget for TextEdit<'t> {
|
||||
match event {
|
||||
Event::Copy | Event::Cut => {
|
||||
// TODO: cut
|
||||
region.ctx().output.lock().copied_text = self.text.clone();
|
||||
region.ctx().output().copied_text = self.text.clone();
|
||||
}
|
||||
Event::Text(text) => {
|
||||
if text == "\u{7f}" {
|
||||
|
||||
Reference in New Issue
Block a user