Add separate serialize feature and better persitence control (#753)

* Rename epaint feature "persistence" to "serialize"

* Add separate "serialize" feature to egui

* egui_demo_lib: separate serialize and persistence features

* Add App::persist_native_window and App::persist_egui_memory

Controls what gets persisted
This commit is contained in:
Emil Ernerfeldt 2021-09-29 08:45:13 +02:00 committed by GitHub
parent f2dd3dfdd9
commit 5539dbe620
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 226 additions and 194 deletions

View file

@ -11,13 +11,14 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`eg
* Add horizontal scrolling support to `ScrollArea` and `Window` (opt-in).
* `TextEdit::layouter`: Add custom text layout for e.g. syntax highlighting or WYSIWYG.
* `Fonts::layout_job*`: New text layout engine allowing mixing fonts, colors and styles, with underlining and strikethrough.
* Add feature `"serialize"` separatedly from `"persistence"`.
### Changed 🔧
* Label text will now be centered, right-aligned and/or justified based on the layout.
* `Hyperlink` will now word-wrap just like a `Label`.
* All `Ui`:s must now have a finite `max_rect`.
* Deprecated: `max_rect_finite`, `available_size_before_wrap_finite` and `available_rect_before_wrap_finite`.
* `Painter`/`Fonts`: text layout now expect color when creating a `Galley`. You may override that color with `Painter::galley_with_color`.
* `Painter`/`Fonts`: text layout now expect a color when creating a `Galley`. You may override that color with `Painter::galley_with_color`.
* MSRV (Minimum Supported Rust Version) is now `1.54.0`.
* By default, `DragValue`:s no longer show a tooltip when hovered. Change with `Style::explanation_tooltips`.

View file

@ -1,11 +1,12 @@
# Changelog for eframe
All notable changes to the `eframe` crate.
All notable changes to the `eframe` and `epi` crates.
## Unreleased
* `Frame` now provides `set_decorations` to set whether to show window decorations.
* Remove "http" feature (use https://github.com/emilk/ehttp instead!).
* Increase native scroll speed.
* Add `App::persist_native_window` and `App::persist_egui_memory` to control what gets persisted.
## 0.14.0 - 2021-08-24

View file

@ -30,6 +30,9 @@ ron = { version = "0.6.4", optional = true }
[features]
default = ["default_fonts", "single_threaded"]
# add compatibility with https://crates.io/crates/cint
cint = ["epaint/cint"]
# If set, egui will use `include_bytes!` to bundle some fonts.
# If you plan on specifying your own fonts you may disable this feature.
default_fonts = ["epaint/default_fonts"]
@ -42,10 +45,11 @@ extra_asserts = ["epaint/extra_asserts"]
# Add compatability with https://github.com/kvark/mint
mint = ["epaint/mint"]
# add compatibility with https://crates.io/crates/cint
cint = ["epaint/cint"]
# enable persistence of memory (window positions etc).
persistence = ["serde", "epaint/serialize", "ron"]
persistence = ["serde", "epaint/persistence", "ron"]
# implement serde on most types.
serialize = ["serde", "epaint/serialize"]
# multi_threaded is only needed if you plan to use the same egui::Context
# from multiple threads. It comes with a minor performance impact.

View file

@ -2,7 +2,7 @@ use std::any::Any;
/// We need this because `TypeId` can't be deserialized or serialized directly, but this can be done using hashing. However, there is a small possibility that different types will have intersection by hashes of their type ids.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TypeId(u64);
impl TypeId {

View file

@ -8,7 +8,7 @@ use crate::*;
/// State that is persisted between frames
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub(crate) struct State {
/// Last known pos
pub pos: Pos2,

View file

@ -4,8 +4,8 @@ use crate::{widgets::Label, *};
use epaint::{Shape, TextStyle};
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub(crate) struct State {
open: bool,

View file

@ -18,7 +18,7 @@ use std::ops::RangeInclusive;
use crate::*;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct PanelState {
rect: Rect,
}

View file

@ -1,7 +1,7 @@
use crate::*;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub(crate) struct State {
/// This is the size that the user has picked by dragging the resize handles.
/// This may be smaller and/or larger than the actual size.

View file

@ -8,8 +8,8 @@
use crate::*;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub(crate) struct State {
/// Positive offset means scrolling down/right
offset: Vec2,
@ -17,7 +17,7 @@ pub(crate) struct State {
show_scroll: [bool; 2],
/// Momentum, used for kinetic scrolling
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
pub vel: Vec2,
/// Mouse offset relative to the top of the handle when started moving the handle.

View file

@ -11,7 +11,7 @@ use crate::emath::*;
///
/// All coordinates are in points (logical pixels) with origin (0, 0) in the top left corner.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct RawInput {
/// How many points (logical pixels) the user scrolled
pub scroll_delta: Vec2,
@ -132,7 +132,7 @@ impl RawInput {
/// A file about to be dropped into egui.
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct HoveredFile {
/// Set by the `egui-winit` backend.
pub path: Option<std::path::PathBuf>,
@ -142,7 +142,7 @@ pub struct HoveredFile {
/// A file dropped into egui.
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct DroppedFile {
/// Set by the `egui-winit` backend.
pub path: Option<std::path::PathBuf>,
@ -158,7 +158,7 @@ pub struct DroppedFile {
///
/// This only covers events that egui cares about.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Event {
/// The integration detected a "copy" event (e.g. Cmd+C).
Copy,
@ -217,7 +217,7 @@ pub enum Event {
/// Mouse button (or similar for touch input)
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum PointerButton {
/// The primary mouse button is usually the left one.
Primary = 0,
@ -233,7 +233,7 @@ pub const NUM_POINTER_BUTTONS: usize = 3;
/// State of the modifier keys. These must be fed to egui.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Modifiers {
/// Either of the alt keys are down (option ⌥ on Mac).
pub alt: bool,
@ -276,7 +276,7 @@ impl Modifiers {
/// Many keys are omitted because they are not always physical keys (depending on keyboard language), e.g. `;` and `§`,
/// and are therefor unsuitable as keyboard shortcuts if you want your app to be portable.
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Key {
ArrowDown,
ArrowLeft,
@ -383,19 +383,19 @@ impl RawInput {
/// this is a `u64` as values of this kind can always be obtained by hashing
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TouchDeviceId(pub u64);
/// Unique identification of a touch occurrence (finger or pen or ...).
/// A Touch ID is valid until the finger is lifted.
/// A new ID is used for the next touch.
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TouchId(pub u64);
/// In what phase a touch event is in.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum TouchPhase {
/// User just placed a touch point on the touch surface
Start,

View file

@ -5,7 +5,7 @@ use crate::WidgetType;
/// What egui emits each frame.
/// The backend should use this.
#[derive(Clone, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Output {
/// Set the cursor to this icon.
pub cursor_icon: CursorIcon,
@ -89,7 +89,7 @@ impl Output {
}
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct OpenUrl {
pub url: String,
/// If `true`, open the url in a new tab.
@ -122,7 +122,7 @@ impl OpenUrl {
///
/// Loosely based on <https://developer.mozilla.org/en-US/docs/Web/CSS/cursor>.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum CursorIcon {
/// Normal cursor icon, whatever that is.
Default,
@ -244,7 +244,7 @@ impl Default for CursorIcon {
///
/// In particular, these events may be useful for accessability, i.e. for screen readers.
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum OutputEvent {
// A widget was clicked.
Clicked(WidgetInfo),
@ -272,7 +272,7 @@ impl std::fmt::Debug for OutputEvent {
/// Describes a widget such as a [`crate::Button`] or a [`crate::TextEdit`].
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WidgetInfo {
/// The type of widget this is.
pub typ: WidgetType,

View file

@ -1,7 +1,7 @@
use crate::*;
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub(crate) struct State {
col_widths: Vec<f32>,
row_heights: Vec<f32>,

View file

@ -26,7 +26,7 @@
/// Then there are widgets that need no identifiers at all, like labels,
/// because they have no state nor are interacted with.
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Id(u64);
impl Id {

View file

@ -9,7 +9,7 @@ use std::sync::Arc;
/// Different layer categories
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Order {
/// Painted behind all floating windows
Background,
@ -65,7 +65,7 @@ impl Order {
/// An identifier for a paint layer.
/// Also acts as an identifier for [`Area`]:s.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LayerId {
pub order: Order,
pub id: Id,

View file

@ -76,8 +76,8 @@ impl Region {
/// Layout direction, one of `LeftToRight`, `RightToLeft`, `TopDown`, `BottomUp`.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Direction {
LeftToRight,
RightToLeft,
@ -115,7 +115,7 @@ impl Direction {
/// });
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
// #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
// #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Layout {
/// Main axis direction
main_dir: Direction,

View file

@ -527,7 +527,7 @@ pub mod special_emojis {
/// The different types of built-in widgets in egui
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum WidgetType {
Label, // TODO: emit Label events
Hyperlink,

View file

@ -14,8 +14,8 @@ use crate::{any, area, window, Id, InputState, LayerId, Pos2, Rect, Style};
/// If you want to store data for your widgets, you should look at `data`/`data_temp` and
/// `id_data`/`id_data_temp` fields, and read the documentation of [`any`] module.
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Memory {
pub options: Options,
@ -53,23 +53,23 @@ pub struct Memory {
/// new fonts that will be applied at the start of the next frame
pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
pub(crate) interaction: Interaction,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
pub(crate) window_interaction: Option<window::WindowInteraction>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
pub(crate) drag_value: crate::widgets::drag_value::MonoState,
pub(crate) areas: Areas,
/// Which popup-window is open (if any)?
/// Could be a combo box, color picker, menu etc.
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
popup: Option<Id>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
everything_is_visible: bool,
}
@ -77,11 +77,11 @@ pub struct Memory {
/// Some global options that you can read and write.
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Options {
/// The default style for new `Ui`:s.
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
pub(crate) style: std::sync::Arc<Style>,
/// Controls the tessellator.
@ -432,8 +432,8 @@ impl Memory {
/// Keeps track of `Area`s, which are free-floating `Ui`s.
/// These `Area`s can be in any `Order`.
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Areas {
areas: HashMap<Id, area::State>,
/// Back-to-front. Top is last.

View file

@ -20,8 +20,8 @@ use epaint::Stroke;
/// What is saved between frames.
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub(crate) struct BarState {
open_menu: Option<Id>,
}

View file

@ -1,6 +1,6 @@
/// What sort of interaction is a widget sensitive to?
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
// #[cfg_attr(feature = "persistence", derive(serde::Serialize))]
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Sense {
/// buttons, sliders, windows ...
pub click: bool,

View file

@ -12,8 +12,8 @@ use epaint::{Shadow, Stroke, TextStyle};
///
/// If you want to change fonts, use [`crate::Context::set_fonts`] instead.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Style {
/// Default `TextStyle` for normal text (i.e. for `Label` and `TextEdit`).
pub body_text_style: TextStyle,
@ -81,8 +81,8 @@ impl Style {
/// Controls the sizes and distances between widgets.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Spacing {
/// Horizontal and vertical spacing between widgets.
///
@ -151,8 +151,8 @@ impl Spacing {
/// How and when interaction happens.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Interaction {
/// Mouse must be the close to the side of a window to resize
pub resize_grab_radius_side: f32,
@ -171,8 +171,8 @@ pub struct Interaction {
///
/// If you want to change fonts, use [`crate::Context::set_fonts`] instead.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Visuals {
/// If true, the visuals are overall dark with light text.
/// If false, the visuals are overall light with dark text.
@ -270,8 +270,8 @@ impl Visuals {
/// Selected text, selected elements etc
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Selection {
pub bg_fill: Color32,
pub stroke: Stroke,
@ -279,8 +279,8 @@ pub struct Selection {
/// The visuals of widgets for different states of interaction.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Widgets {
/// The style of a widget that you cannot interact with.
/// * `noninteractive.bg_stroke` is the outline of windows.
@ -313,7 +313,7 @@ impl Widgets {
/// bg = background, fg = foreground.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WidgetVisuals {
/// Background color of widget.
pub bg_fill: Color32,
@ -342,7 +342,7 @@ impl WidgetVisuals {
/// Options for help debug egui by adding extra visualization
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct DebugOptions {
/// However over widgets to see their rectangles
pub debug_on_hover: bool,

View file

@ -1,7 +1,7 @@
use std::collections::VecDeque;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Settings {
/// Maximum number of undos.
/// If your state is resource intensive, you should keep this low.
@ -48,7 +48,7 @@ impl Default for Settings {
/// Rule 1) will make sure an undo point is not created until you _stop_ dragging that slider.
/// Rule 2) will make sure that you will get some undo points even if you are constantly changing the state.
#[derive(Clone, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Undoer<State> {
settings: Settings,
@ -57,7 +57,7 @@ pub struct Undoer<State> {
/// The latest undo point may (often) be the current state.
undos: VecDeque<State>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
flux: Option<Flux<State>>,
}

View file

@ -21,7 +21,7 @@ use color::Hsva;
// ----------------------------------------------------------------------------
/// Information about the plot that has to persist between frames.
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone)]
struct PlotMemory {
bounds: Bounds,

View file

@ -6,7 +6,7 @@ use crate::*;
/// 2D bounding box of f64 precision.
/// The range of data values we show.
#[derive(Clone, Copy, PartialEq, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub(crate) struct Bounds {
pub min: [f64; 2],
pub max: [f64; 2],

View file

@ -4,25 +4,25 @@ use std::ops::Range;
use std::sync::Arc;
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub(crate) struct State {
cursorp: Option<CursorPair>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
undoer: Undoer<(CCursorPair, String)>,
// If IME candidate window is shown on this text edit.
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
has_ime: bool,
// Visual offset when editing singleline text bigger than the width.
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
singleline_offset: f32,
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct CursorPair {
/// When selecting with a mouse, this is where the mouse was released.
/// When moving with e.g. shift+arrows, this is what moves.
@ -86,7 +86,7 @@ impl CursorPair {
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct CCursorPair {
/// When selecting with a mouse, this is where the mouse was released.
/// When moving with e.g. shift+arrows, this is what moves.

View file

@ -42,15 +42,17 @@ criterion = { version = "0.3", default-features = false }
[features]
default = []
http = ["ehttp", "image"]
persistence = ["egui/persistence", "epi/persistence", "serde"]
syntax_highlighting = ["syntect"]
# Enable additional checks if debug assertions are enabled (debug builds).
extra_debug_asserts = ["egui/extra_debug_asserts"]
# Always enable additional checks.
extra_asserts = ["egui/extra_asserts"]
http = ["ehttp", "image"]
persistence = ["egui/persistence", "epi/persistence", "serde"]
serialize = ["egui/serialize", "serde"]
syntax_highlighting = ["syntect"]
[[bench]]
name = "benchmark"
harness = false

View file

@ -9,9 +9,9 @@ const RED: Color32 = Color32::RED;
const TRANSPARENT: Color32 = Color32::TRANSPARENT;
const WHITE: Color32 = Color32::WHITE;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ColorTest {
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
tex_mngr: TextureManager,
vertex_gradients: bool,
texture_gradients: bool,

View file

@ -3,8 +3,8 @@
/// Implements `epi::App` so it can be used with
/// [`egui_glium`](https://crates.io/crates/egui_glium) and [`egui_web`](https://crates.io/crates/egui_web).
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct DemoApp {
demo_windows: super::DemoWindows,
}
@ -14,14 +14,14 @@ impl epi::App for DemoApp {
"✨ Demos"
}
#[cfg(feature = "persistence")]
fn setup(
&mut self,
_ctx: &egui::CtxRef,
_frame: &mut epi::Frame<'_>,
storage: Option<&dyn epi::Storage>,
_storage: Option<&dyn epi::Storage>,
) {
if let Some(storage) = storage {
#[cfg(feature = "persistence")]
if let Some(storage) = _storage {
*self = epi::get_value(storage, epi::APP_KEY).unwrap_or_default()
}
}

View file

@ -1,11 +1,11 @@
use egui::text::LayoutJob;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct CodeEditor {
code: String,
language: String,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
highlighter: MemoizedSyntaxHighlighter,
}

View file

@ -1,8 +1,8 @@
use egui::{containers::*, *};
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct DancingStrings {}
impl super::Demo for DancingStrings {

View file

@ -4,10 +4,10 @@ use std::collections::BTreeSet;
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct Demos {
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
demos: Vec<Box<dyn Demo>>,
open: BTreeSet<String>,
@ -67,10 +67,10 @@ impl Demos {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct Tests {
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
demos: Vec<Box<dyn Demo>>,
open: BTreeSet<String>,
@ -136,8 +136,8 @@ fn set_open(open: &mut BTreeSet<String>, key: &'static str, is_open: bool) {
/// A menu bar in which you can select different demo windows to show.
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct DemoWindows {
demos: Demos,
tests: Tests,

View file

@ -1,7 +1,7 @@
use egui::*;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct LayoutTest {
// Identical to contents of `egui::Layout`
layout: LayoutSettings,
@ -22,8 +22,8 @@ impl Default for LayoutTest {
}
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct LayoutSettings {
// Similar to the contents of `egui::Layout`
main_dir: Direction,

View file

@ -2,8 +2,8 @@ use super::*;
use egui::{color::*, *};
/// Showcase some ui code
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct MiscDemoWindow {
num_columns: usize,
@ -115,8 +115,8 @@ impl View for MiscDemoWindow {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Widgets {
angle: f32,
password: String,
@ -194,8 +194,8 @@ impl Widgets {
// ----------------------------------------------------------------------------
#[derive(PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct ColorWidgets {
srgba_unmul: [u8; 4],
srgba_premul: [u8; 4],
@ -264,8 +264,8 @@ impl ColorWidgets {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct BoxPainting {
size: Vec2,
corner_radius: f32,
@ -315,7 +315,7 @@ enum Action {
}
#[derive(Clone, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct Tree(String, SubTree);
impl Tree {
@ -334,7 +334,7 @@ impl Tree {
}
#[derive(Clone, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct SubTree(Vec<SubTree>);
impl SubTree {

View file

@ -1,7 +1,7 @@
use egui::*;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Painting {
/// in 0-1 normalized coordinates
lines: Vec<Vec<Pos2>>,

View file

@ -1,6 +1,6 @@
use egui::{color::*, *};
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug, PartialEq)]
enum ScrollDemo {
ScrollTo,
@ -14,8 +14,8 @@ impl Default for ScrollDemo {
}
}
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, PartialEq)]
pub struct Scrolling {
demo: ScrollDemo,
@ -124,8 +124,8 @@ fn huge_content_painter(ui: &mut egui::Ui) {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(PartialEq)]
struct ScrollTo {
track_item: usize,

View file

@ -3,8 +3,8 @@ use std::f64::INFINITY;
/// Showcase sliders
#[derive(PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Sliders {
pub min: f64,
pub max: f64,

View file

@ -303,7 +303,7 @@ impl super::View for TableTest {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Default)]
pub struct InputTest {
info: String,

View file

@ -1,5 +1,5 @@
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
enum Enum {
First,
Second,
@ -7,7 +7,7 @@ enum Enum {
}
/// Shows off one example of each major type of widget.
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WidgetGallery {
enabled: bool,
visible: bool,

View file

@ -1,5 +1,5 @@
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WindowOptions {
title: String,
title_bar: bool,

View file

@ -1,5 +1,5 @@
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WindowWithPanels {}
impl super::Demo for WindowWithPanels {

View file

@ -2,8 +2,8 @@ use egui::{containers::*, widgets::*, *};
use std::f32::consts::TAU;
#[derive(PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct FractalClock {
paused: bool,
time: f64,

View file

@ -38,13 +38,13 @@ impl Resource {
}
#[derive(Debug, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
enum Method {
Get,
Post,
}
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct HttpApp {
url: String,
@ -52,13 +52,13 @@ pub struct HttpApp {
request_body: String,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
in_progress: Option<Receiver<Result<ehttp::Response, String>>>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
result: Option<Result<Resource, String>>,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
tex_mngr: TexMngr,
}

View file

@ -41,12 +41,12 @@ impl Default for RunMode {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct BackendPanel {
pub open: bool,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
// go back to `Reactive` mode each time we start
run_mode: RunMode,
@ -57,10 +57,10 @@ pub struct BackendPanel {
max_size_points_ui: egui::Vec2,
pub max_size_points_active: egui::Vec2,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
frame_history: crate::frame_history::FrameHistory,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
output_event_history: std::collections::VecDeque<egui::output::OutputEvent>,
egui_windows: EguiWindows,
@ -286,7 +286,7 @@ impl BackendPanel {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct EguiWindows {
// egui stuff:
settings: bool,

View file

@ -1,13 +1,13 @@
use egui::*;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct EasyMarkEditor {
code: String,
highlight_editor: bool,
show_rendered: bool,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
highlighter: crate::easy_mark::MemoizedEasymarkHighlighter,
}

View file

@ -1,7 +1,7 @@
/// All the different demo apps.
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Apps {
demo: crate::apps::DemoApp,
easy_mark_editor: crate::easy_mark::EasyMarkEditor,
@ -27,13 +27,13 @@ impl Apps {
/// Wraps many demo/test apps into one.
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct WrapApp {
selected_anchor: String,
apps: Apps,
backend_panel: super::backend_panel::BackendPanel,
#[cfg_attr(feature = "persistence", serde(skip))]
#[cfg_attr(feature = "serde", serde(skip))]
dropped_files: Vec<egui::DroppedFile>,
}
@ -42,15 +42,14 @@ impl epi::App for WrapApp {
"egui demo apps"
}
#[allow(unused_variables)]
fn setup(
&mut self,
_ctx: &egui::CtxRef,
_frame: &mut epi::Frame<'_>,
storage: Option<&dyn epi::Storage>,
_storage: Option<&dyn epi::Storage>,
) {
#[cfg(feature = "persistence")]
if let Some(storage) = storage {
if let Some(storage) = _storage {
*self = epi::get_value(storage, epi::APP_KEY).unwrap_or_default()
}
}

View file

@ -361,12 +361,16 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: &epi::NativeOptions) {
if let Some(storage) = &mut storage {
let now = Instant::now();
if now - last_auto_save > app.auto_save_interval() {
if app.persist_native_window() {
epi::set_value(
storage.as_mut(),
WINDOW_KEY,
&WindowSettings::from_display(&display),
);
}
if app.persist_egui_memory() {
epi::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*egui.ctx().memory());
}
app.save(storage.as_mut());
storage.flush();
last_auto_save = now;
@ -379,12 +383,16 @@ pub fn run(mut app: Box<dyn epi::App>, native_options: &epi::NativeOptions) {
#[cfg(feature = "persistence")]
if let Some(storage) = &mut storage {
if app.persist_native_window() {
epi::set_value(
storage.as_mut(),
WINDOW_KEY,
&WindowSettings::from_display(&display),
);
}
if app.persist_egui_memory() {
epi::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*egui.ctx().memory());
}
app.save(storage.as_mut());
storage.flush();
}

View file

@ -194,7 +194,9 @@ impl AppRunner {
let time_since_last_save = now - self.last_save_time;
if time_since_last_save > self.app.auto_save_interval().as_secs_f64() {
if self.app.persist_egui_memory() {
save_memory(&self.web_backend.egui_ctx);
}
self.app.save(&mut self.storage);
self.last_save_time = now;
}

View file

@ -50,7 +50,8 @@ extra_asserts = ["emath/extra_asserts"]
# Add compatability with https://github.com/kvark/mint
mint = ["emath/mint"]
persistence = ["serde", "emath/serde"]
# implement serde on most types.
serialize = ["serde", "emath/serde"]
single_threaded = ["atomic_refcell"]

View file

@ -14,7 +14,7 @@
/// Internally this uses 0-255 gamma space `sRGBA` color with premultiplied alpha.
/// Alpha channel is in linear space.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Color32(pub(crate) [u8; 4]);
impl std::ops::Index<usize> for Color32 {
@ -184,7 +184,7 @@ impl Color32 {
/// 0-1 linear space `RGBA` color with premultiplied alpha.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Rgba(pub(crate) [f32; 4]);
impl std::ops::Index<usize> for Rgba {

View file

@ -109,7 +109,7 @@ pub const WHITE_UV: emath::Pos2 = emath::pos2(0.0, 0.0);
/// What texture to use in a [`Mesh`] mesh.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum TextureId {
/// The egui font texture.
/// If you don't want to use a texture, pick this and the [`WHITE_UV`] for uv-coord.
@ -142,7 +142,7 @@ pub struct ClippedShape(
///
/// Everything is using logical points.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ClippedMesh(
/// Clip / scissor rectangle.
/// Only show the part of the [`Mesh`] that falls within this.

View file

@ -6,7 +6,7 @@ use emath::*;
/// Should be friendly to send to GPU as is.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Vertex {
/// Logical pixel coordinates (points).
/// (0,0) is the top left corner of the screen.
@ -23,7 +23,7 @@ pub struct Vertex {
/// Textured triangles in two dimensions.
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Mesh {
/// Draw as triangles (i.e. the length is always multiple of three).
///

View file

@ -3,7 +3,7 @@ use super::*;
/// The color and fuzziness of a fuzzy shape.
/// Can be used for a rectangular shadow with a soft penumbra.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Shadow {
/// The shadow extends this much outside the rect.
/// The size of the fuzzy penumbra.

View file

@ -129,7 +129,7 @@ impl Shape {
/// How to paint a circle.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct CircleShape {
pub center: Pos2,
pub radius: f32,
@ -170,7 +170,7 @@ impl From<CircleShape> for Shape {
/// A path which can be stroked and/or filled (if closed).
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PathShape {
pub points: Vec<Pos2>,
/// If true, connect the first and last of the points together.
@ -239,7 +239,7 @@ impl From<PathShape> for Shape {
/// How to paint a rectangle.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct RectShape {
pub rect: Rect,
/// How rounded the corners are. Use `0.0` for no rounding.

View file

@ -6,7 +6,7 @@ use super::*;
///
/// The default stroke is the same as [`Stroke::none`].
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Stroke {
pub width: f32,
pub color: Color32,

View file

@ -254,8 +254,8 @@ pub enum PathType {
/// Tessellation quality options
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct TessellationOptions {
/// Size of a point in pixels, e.g. 2.0. Used to snap text to pixel boundaries.
pub pixels_per_point: f32,

View file

@ -2,7 +2,7 @@
/// Character cursor
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct CCursor {
/// Character offset (NOT byte offset!).
pub index: usize,
@ -65,7 +65,7 @@ impl std::ops::SubAssign<usize> for CCursor {
/// Row Cursor
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct RCursor {
/// 0 is first row, and so on.
/// Note that a single paragraph can span multiple rows.
@ -80,7 +80,7 @@ pub struct RCursor {
/// Paragraph Cursor
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PCursor {
/// 0 is first paragraph, and so on.
/// Note that a single paragraph can span multiple rows.
@ -112,7 +112,7 @@ impl PartialEq for PCursor {
/// pcursor/rcursor can also point to after the end of the paragraph/row.
/// Does not implement `PartialEq` because you must think which cursor should be equivalent.
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Cursor {
pub ccursor: CCursor,
pub rcursor: RCursor,

View file

@ -12,8 +12,8 @@ use crate::{
// TODO: rename
/// One of a few categories of styles of text, e.g. body, button or heading.
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum TextStyle {
/// Used when small text is needed.
Small,
@ -43,8 +43,8 @@ impl TextStyle {
/// Which style of font: [`Monospace`][`FontFamily::Monospace`] or [`Proportional`][`FontFamily::Proportional`].
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(rename_all = "snake_case"))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum FontFamily {
/// A font where each character is the same width (`w` is the same width as `i`).
Monospace,
@ -106,8 +106,8 @@ fn ab_glyph_font_from_font_data(name: &str, data: &FontData) -> ab_glyph::FontAr
/// ctx.set_fonts(fonts);
/// ```
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct FontDefinitions {
/// List of font names and their definitions.
/// The definition must be the contents of either a `.ttf` or `.otf` font file.

View file

@ -13,7 +13,7 @@ use emath::*;
///
/// Pass this to [`Fonts::layout_job]` or [`crate::text::layout`].
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LayoutJob {
/// The complete text of this job, referenced by `LayoutSection`.
pub text: String, // TODO: Cow<'static, str>
@ -137,7 +137,7 @@ impl std::hash::Hash for LayoutJob {
// ----------------------------------------------------------------------------
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LayoutSection {
/// Can be used for first row indentation.
pub leading_space: f32,
@ -163,7 +163,7 @@ impl std::hash::Hash for LayoutSection {
// ----------------------------------------------------------------------------
#[derive(Copy, Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TextFormat {
pub style: TextStyle,
/// Text color

View file

@ -94,7 +94,7 @@ pub trait App {
/// Allows you to do setup code, e.g to call `[egui::Context::set_fonts]`,
/// `[egui::Context::set_visuals]` etc.
///
/// Also allows you to restore state, if there is a storage.
/// Also allows you to restore state, if there is a storage (required the "persistence" feature).
fn setup(
&mut self,
_ctx: &egui::CtxRef,
@ -113,6 +113,8 @@ pub trait App {
/// Called on shutdown, and perhaps at regular intervals. Allows you to save state.
///
/// Only called when the "persistence" feature is enabled.
///
/// On web the states is stored to "Local Storage".
/// On native the path is picked using [`directories_next::ProjectDirs::data_dir`](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir) which is:
/// * Linux: `/home/UserName/.local/share/APPNAME`
@ -150,6 +152,18 @@ pub trait App {
// `transparent()` option they get immediate results.
egui::Color32::from_rgba_unmultiplied(12, 12, 12, 180).into()
}
/// Controls wether or not the native window position and size will be
/// persisted (only if the "persistence" feature is enabled).
fn persist_native_window(&self) -> bool {
true
}
/// Controls wether or not the egui memory (window positions etc) will be
/// persisted (only if the "persistence" feature is enabled).
fn persist_egui_memory(&self) -> bool {
true
}
}
/// Options controlling the behavior of a native window