Skip to content

Commit

Permalink
Add a lot more documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Nov 16, 2023
1 parent 26f0c2a commit 82863f8
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
3 changes: 3 additions & 0 deletions crates/egui/src/containers/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ use super::*;
/// ```
///
/// The previous rectangle used by this window can be obtained through [`crate::Memory::area_rect()`].
///
/// Note that this is NOT a native OS window.
/// To create a new native OS window, use [`crate::Context::show_viewport`].
#[must_use = "You should call .show()"]
pub struct Window<'open> {
title: WidgetText,
Expand Down
14 changes: 9 additions & 5 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2555,14 +2555,14 @@ impl Context {
/// Send a command to the current viewport.
///
/// This lets you affect the current viewport, e.g. resizing the window.
pub fn viewport_command(&self, command: ViewportCommand) {
self.viewport_command_for(self.viewport_id(), command);
pub fn send_viewport_command(&self, command: ViewportCommand) {
self.send_viewport_command_to(self.viewport_id(), command);
}

/// Send a command to a speicfic viewport.
///
/// This lets you affect another viewport, e.g. resizing its window.
pub fn viewport_command_for(&self, id: ViewportId, command: ViewportCommand) {
pub fn send_viewport_command_to(&self, id: ViewportId, command: ViewportCommand) {
self.write(|ctx| ctx.viewport_for(id).commands.push(command));
}

Expand All @@ -2589,7 +2589,9 @@ impl Context {
/// backend does not support multiple viewports), the given callback
/// will be called immediately, embedding the new viewport in the current one.
/// You can check this with the [`ViewportClass`] given in the callback.
/// If you find [`ViewportClass::embedded`], you need to create a new [`crate::Window`] for you content.
/// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
///
/// See [`crate::viewport`] for more information about viewports.
pub fn show_viewport(
&self,
new_viewport_id: ViewportId,
Expand Down Expand Up @@ -2636,7 +2638,9 @@ impl Context {
/// backend does not support multiple viewports), the given callback
/// will be called immediately, embedding the new viewport in the current one.
/// You can check this with the [`ViewportClass`] given in the callback.
/// If you find [`ViewportClass::embedded`], you need to create a new [`crate::Window`] for you content.
/// If you find [`ViewportClass::Embedded`], you need to create a new [`crate::Window`] for you content.
///
/// See [`crate::viewport`] for more information about viewports.
pub fn show_viewport_immediate<T>(
&self,
new_viewport_id: ViewportId,
Expand Down
4 changes: 4 additions & 0 deletions crates/egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
//! # });
//! ```
//!
//! ## Viewports
//! Some egui backends support multiple _viewports_, which is what egui calls the native OS windows it resides in.
//! See [`crate::viewport`] for more information.
//!
//! ## Coordinate system
//! The left-top corner of the screen is `(0.0, 0.0)`,
//! with X increasing to the right and Y increasing downwards.
Expand Down
58 changes: 52 additions & 6 deletions crates/egui/src/viewport.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
//! egui supports multiple viewports, corresponding to multiple native windows.
//!
//! Viewports come in two flavors: "deferred" (the default) and "immediate".
//! Not all egui backends support multiple viewports, but `eframe` native does
//! (but not on web).
//!
//! * Deferred viewports have callbacks that are called multiple
//! times as the viewport receives events, or need repaitning.
//! * Immediate viewports are executed immediately with an [`FnOnce`] callback,
//! locking the parent and child viewports together so that they both must update at the same time.
//! You can spawn a new viewport using [`Context::show_viewport`] and [`Context::show_viewport_immediate`].
//! These needs to be called every frame the viewport should be visible.
//!
//! This is implemented by the native `eframe` backend, but not the web one.
//!
//! ## Viewport classes
//! The viewports form a tree of parent-child relationships.
//!
//! There are different classes of viewports.
//!
//! ### Root viewport
//! The root viewport is the original viewport, and cannot be closed without closing the application.
//!
//! ### Deferred viewports
//! These are created with [`Context::show_viewport`].
//! Deferred viewports take a closure that is called by the integration at a later time, perhaps multiple times.
//! Deferred viewports are repainted independenantly of the parent viewport.
//! This means communication with them need to done via channels, or `Arc/Mutex`.
//!
//! This is the most performant type of child viewport, though a bit more cumbersome to work with compared to immediate viewports.
//!
//! ### Immediate viewports
//! These are created with [`Context::show_viewport_immediate`].
//! Immediate viewports take a `FnOnce` closure, similar to other egui functions, and is called immediately.
//! This makes communication with them much simpler than with deferred viewports, but this simplicity comes at a cost: whenever the parent viewports needs to be repainted, so will the child viewport, and vice versa.
//! This means that if you have `N` viewports you are potentially doing `N` times as much CPU work. However, if all your viewports are showing animations, and thus are repainting constantly anyway, this doesn't matter.
//!
//! In short: immediate viewports are simpler to use, but can waste a lot of CPU time.
//!
//! ### Embedded viewports
//! These are not real, independenant viewports, but is a fallback mode for when the integration does not support real viewports. In your callback is called with [`ViewportClass::Embedded`] it means you need to create an [`crate::Window`] to wrap your ui in, which will then be embedded in the parent viewport, unable to escape it.
//!
//!
//! ## Using the viewports
//! Only one viewport is active at any one time, identified with [`Context::viewport_id`].
//! You can send commands to other viewports using [`Context::send_viewport_command_to`].
//!
//! There is an example in <https://github.com/emilk/egui/tree/master/examples/multiple_viewports/src/main.rs>.
//!
//! ## For integrations
//! * There is a [`crate::RawInput::viewport`] with information about the current viewport.
//! * The repaint callback set by [`Context::set_request_repaint_callback`] points to which viewport should be repainted.
//! * [`crate::FullOutput::viewport_output`] is a list of viewports which should result in their own independent windows.
//! * To support immediate viewports you need to call [`Context::set_immediate_viewport_renderer`].
//! * If you support viewports, you need to call [`Context::set_embed_viewports`] with `false`, or all new viewports will be embedded (the default behavior).
//!
//! ## Future work
//! There are several more things related to viewports that we want to add.
//! Read more at <https://github.com/emilk/egui/issues/3556>.

use std::sync::Arc;

Expand Down Expand Up @@ -609,7 +655,7 @@ pub enum ResizeDirection {
SouthWest,
}

/// You can send a [`ViewportCommand`] to the viewport with [`Context::viewport_command`].
/// You can send a [`ViewportCommand`] to the viewport with [`Context::send_viewport_command`].
///
/// All coordinates are in logical points.
///
Expand Down
2 changes: 1 addition & 1 deletion examples/test_viewports/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ fn generic_ui(ui: &mut egui::Ui, children: &[Arc<RwLock<ViewportState>>]) {
if ctx.viewport_id() != ctx.parent_viewport_id() {
let parent = ctx.parent_viewport_id();
if ui.button("Set parent pos 0,0").clicked() {
ctx.viewport_command_for(
ctx.send_viewport_command_to(
parent,
egui::ViewportCommand::OuterPosition(egui::pos2(0.0, 0.0)),
);
Expand Down

0 comments on commit 82863f8

Please sign in to comment.