[go: up one dir, main page]

egui 0.3.0

Simple, portable immediate mode GUI library for Rust
Documentation
//! Traits and helper for writing Egui apps.
//!
//! This module is very experimental, and you don't need to use it.
//!
//! Egui can be used as a library, but you can also use it as a framework to write apps in.
//! This module defined the `App` trait that can be implemented and used with the `egui_web` and `egui_glium` crates.

// 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 {
    /// 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>) {}

    /// 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<'_>,
    );

    /// Called once on shutdown. Allows you to save state.
    fn on_exit(&mut self, _storage: &mut dyn Storage) {}
}

pub struct IntegrationContext<'a> {
    /// Information about the integration.
    pub info: IntegrationInfo,
    /// A way to allocate textures (on integrations that support it).
    pub tex_allocator: Option<&'a mut dyn TextureAllocator>,
    /// Where the app can issue commands back to the integration.
    pub output: AppOutput,
}

#[derive(Clone, Debug)]
pub struct WebInfo {
    /// e.g. "#fragment" part of "www.example.com/index.html#fragment"
    pub web_location_hash: String,
}

/// Information about the integration passed to the use app each frame.
#[derive(Clone, Debug)]
pub struct IntegrationInfo {
    /// If the app is running in a Web context, this returns information about the environment.
    pub web_info: Option<WebInfo>,

    /// Seconds of cpu usage (in seconds) of UI code on the previous frame.
    /// `None` if this is the first frame.
    pub cpu_usage: Option<f32>,

    /// Local time. Used for the clock in the demo app.
    /// Set to `None` if you don't know.
    pub seconds_since_midnight: Option<f64>,

    /// The OS native pixels-per-point
    pub native_pixels_per_point: Option<f32>,
}

/// Action that can be taken by the user app.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct AppOutput {
    /// Set to `true` to stop the app.
    /// This does nothing for web apps.
    pub quit: bool,

    /// Set to some size to resize the outer window (e.g. glium window) to this size.
    pub window_size: Option<crate::Vec2>,

    /// If the app sets this, change the `pixels_per_point` of Egui to this next frame.
    pub pixels_per_point: Option<f32>,
}

pub trait TextureAllocator {
    /// Allocate a user texture (EXPERIMENTAL!)
    fn new_texture_srgba_premultiplied(
        &mut self,
        size: (usize, usize),
        pixels: &[crate::Srgba],
    ) -> crate::TextureId;
}

/// A place where you can store custom data in a way that persists when you restart the app.
///
/// On the web this is backed by [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
/// On desktop this is backed by the file system.
pub trait Storage {
    fn get_string(&self, key: &str) -> Option<&str>;
    fn set_string(&mut self, key: &str, value: String);

    /// write-to-disk or similar
    fn flush(&mut self);
}

/// Stores nothing.
#[derive(Clone, Default)]
pub struct DummyStorage {}

impl Storage for DummyStorage {
    fn get_string(&self, _key: &str) -> Option<&str> {
        None
    }
    fn set_string(&mut self, _key: &str, _value: String) {}
    fn flush(&mut self) {}
}

#[cfg(feature = "serde_json")]
pub fn get_value<T: serde::de::DeserializeOwned>(storage: &dyn Storage, key: &str) -> Option<T> {
    storage
        .get_string(key)
        .and_then(|value| serde_json::from_str(value).ok())
}

#[cfg(feature = "serde_json")]
pub fn set_value<T: serde::Serialize>(storage: &mut dyn Storage, key: &str, value: &T) {
    storage.set_string(key, serde_json::to_string(value).unwrap());
}

/// storage key used for app
pub const APP_KEY: &str = "app";