Browse Source

Improve documentation

pull/193/head
Emil Ernerfeldt 4 years ago
parent
commit
82350a2f1e
  1. 50
      ARCHITECTURE.md
  2. 50
      CONTRIBUTING.md
  3. 10
      check.sh
  4. 84
      egui/src/lib.rs
  5. 4
      egui/src/widgets/mod.rs
  6. 2
      egui/src/widgets/selected_label.rs
  7. 2
      egui_glium/src/painter.rs
  8. 11
      emath/src/rect.rs
  9. 10
      start_server.sh

50
ARCHITECTURE.md

@ -0,0 +1,50 @@
# Arcitecture
This document describes how the crates that make up egui are all connected.
Also see `CONTRIBUTING.md` for what to do before opening a PR.
## Crate overview
The crates in this repository are: `egui, emath, epaint, egui, epi, egui_web, egui_glium, egui_demo_lib, egui_demo_app`.
### `egui`: The main GUI library.
Example code: `if ui.button("Click me").clicked() { … }`
This is the crate where the bulk of the code is at. `egui` depends only on `emath` and `epaint`.
### `emath`: minimal 2D math library
Examples: `Vec2, Pos2, Rect, lerp, remap`
### `epaint`
2d shapes and text that can be turned into textured triangles.
Example: `Shape::Circle { center, radius, fill, stroke }`
Depends on `emath`, [`rusttype`](https://crates.io/crates/rusttype), [`atomic_refcell`](https://crates.io/crates/atomic_refcell), [`ahash`](https://crates.io/crates/ahash).
### `epi`
Depends only on `egui`.
Adds a thin application level wrapper around `egui` for hosting an `egui` app inside of `eframe`.
### `egui_web`
Puts an egui app inside the web browser by compiling to WASM and binding to the web browser with [`js-sys`](https://crates.io/crates/js-sys) and [`wasm-bindgen`](https://crates.io/crates/wasm-bindgen). Paints the triangles that egui outputs using WebGL.
### `egui_glium`
Puts an egui app inside a native window on your laptop. Paints the triangles that egui outputs using [glium](https://github.com/glium/glium).
### `eframe`
A wrapper around `egui_web` + `egui_glium`, so you can compile the same app for either web or native.
The demo that you can see at <https://emilk.github.io/egui/index.html> is using `eframe` to host the `egui`. The demo code is found in:
### `egui_demo_lib`
Depends on `egui` + `epi`.
This contains a bunch of uses of `egui` and looks like the ui code you would write for an `egui` app.
### `egui_demo_app`
Thin wrapper around `egui_demo_lib` so we can compile it to a web site or a native app executable.
Depends on `egui_demo_lib` + `eframe`.
### Other integrations
There are also many great integrations for game engines such as `bevy` and `miniquad` which you can find at <https://github.com/emilk/egui#integrations>.

50
CONTRIBUTING.md

@ -1,26 +1,62 @@
# Contributing guidelines
You are welcome to contribute to egui via discussions, issues, pull requests and by publishing egui integrations.
## Introduction
`egui` has been an on-and-off weekend project of mine since late 2018. I am grateful to any help I can get, but bare in mind that sometimes I can be slow to respond because I am busy with other things!
/ Emil
## Discussion
You can ask questions, share screenshots and more at GitHub Discussions: https://github.com/emilk/egui/discussions
You can ask questions, share screenshots and more at [GitHub Discussions](https://github.com/emilk/egui/discussions).
There is also an `egui` channel on the Embark discord at <https://discord.gg/vY8ZGS292W> (NOTE: I work at [Embark](https://www.embark-studios.com/), but `egui` is my hobby project).
There is also an egui channel on the Embark discord at <https://discord.gg/vY8ZGS292W> (NOTE: I work at [Embark](https://www.embark-studios.com/), but egui is my hobby project).
## Filing an issue
Issues are for bug reports and feature requests. Issues are not for asking questions (use [Discussions](https://github.com/emilk/egui/discussions) for that).
[Issues](https://github.com/emilk/egui/issues) are for bug reports and feature requests. Issues are not for asking questions (use [Discussions](https://github.com/emilk/egui/discussions) for that).
Always make sure there is not already a similar issue to the one you are creating.
If you are filing a bug, please provide a way to reproduce it.
## Making a PR
Always file an issue (or find an existing one) and get feedback before you start working on a non-trivial pull request!
First file an issue (or find an existing one) and announce that you plan to work on something. That way we will avoid having several people doing double work. Please ask for feedback before you start working on something non-trivial!
Browse through [`ARCHITECTURE.md`](https://github.com/emilk/egui/blob/master/ARCHITECTURE.md) to get a sense of how all pieces connects.
When you have something that works, open a draft PR. You may get some helpful feedback early!
When you feel the PR is ready to go, do a self-review of the code, and then open it for review.
## Creating an integration for egui
If you make an integration for egui for some engine or renderer, please share it with the world!
I will add a link to it from the egui README.md so others can easily find it.
If you make an integration for `egui` for some engine or renderer, please share it with the world!
I will add a link to it from the `egui` README.md so others can easily find it.
Read the section on integrations at <https://github.com/emilk/egui#integrations>.
## Code Conventions
Conventions unless otherwise specified:
* angles are in radians
* `Vec2::X` is right and `Vec2::Y` is down.
* `Pos2::ZERO` is left top.
While using an immediate mode gui is simple, implementing one is a lot more tricky. There are many subtle corner-case you need to think through. The `egui` source code is a bit messy, partially because it is still evolving.
* read some code before writing your own
* follow the `egui` code style
* write idiomatic rust
* avoid `unsafe`
* avoid code that can cause panics
* use good names for everything
* add docstrings to types, `struct` fields and all `pub fn`.
* add some example code (doc-tests)
* before making a function longer, consider adding a helper function
* break the above rules when it makes sense

10
check.sh

@ -1,19 +1,25 @@
#!/bin/bash
set -eu
# Checks all tests, lints etc.
# Basically does what the CI does.
cargo check --workspace --all-targets
cargo test --workspace --doc
cargo check --workspace --all-targets --all-features
cargo check -p egui_demo_app --lib --target wasm32-unknown-unknown
cargo check -p egui_demo_app --lib --target wasm32-unknown-unknown --all-features
cargo fmt --all -- --check
CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::all
cargo test --workspace --all-targets --all-features
cargo test --workspace --doc
cargo fmt --all -- --check
# TODO: doesn't error, but at least prints a warning.
cargo doc -p emath -p epaint -p egui -p eframe -p epi -p egui_web -p egui_glium --lib --no-deps
cargo doc -p egui_web --target wasm32-unknown-unknown --lib --no-deps
# ------------------------------------------------------------
#
# For finding bloat:
# cargo bloat --release --bin demo_glium -n 200 | rg egui

84
egui/src/lib.rs

@ -1,8 +1,6 @@
//! egui: an easy-to-use GUI in pure Rust
//! `egui`: an easy-to-use GUI in pure Rust!
//!
//! Try the live web demo: <https://emilk.github.io/egui/index.html>.
//!
//! Read more about egui at <https://github.com/emilk/egui>.
//! Try the live web demo: <https://emilk.github.io/egui/index.html>. Read more about egui at <https://github.com/emilk/egui>.
//!
//! To quickly get started with egui, you can take a look at [`egui_template`](https://github.com/emilk/egui_template)
//! which uses [`eframe`](https://docs.rs/eframe).
@ -45,6 +43,10 @@
//!
//! To see what is possible to build we egui you can check out the online demo at <https://emilk.github.io/egui/#demo>.
//!
//! If you like the "learning by doing" approach, clone <https://github.com/emilk/egui_template> and get started using egui right away.
//!
//! ### Getting a [`Ui`]
//!
//! Use one of [`SidePanel`], [`TopPanel`], [`CentralPanel`], [`Window`] or [`Area`] to
//! get access to an [`Ui`] where you can put widgets. For example:
//!
@ -60,6 +62,80 @@
//! });
//! ```
//!
//! ## Conventions
//!
//! Conventions unless otherwise specified:
//!
//! * angles are in radians
//! * `Vec2::X` is right and `Vec2::Y` is down.
//! * `Pos2::ZERO` is left top.
//!
//!
//! ## Understanding immediate mode
//!
//! `egui` is an immediate mode GUI library. It is useful to fully grok what "immediate mode" implies.
//!
//! Here is an example to illustrate it:
//!
//! ```
//! # let ui = &mut egui::Ui::__test();
//! if ui.button("click me").clicked() { take_action() }
//! # fn take_action() {}
//! ```
//!
//! This code is being executed each frame at maybe 60 frames per second.
//! Each frame egui does these things:
//!
//! * lays out the letters `click me` in order to figure out the size of the button
//! * decides where on screen to place the button
//! * check if the mouse is hovering or clicking that location
//! * chose button colors based on if it is being hovered or clicked
//! * add a [`Shape::Rect`] and [`Shape::Text`] to the list of shapes to be painted later this frame
//! * return a [`Response`] with the `clicked` member so the user can check for interactions
//!
//! There is no button being created and stored somewhere.
//! The only output of this call is some colored shapes, and a [`Response`].
//!
//! Read more about the pros and cons of immediate mode at <https://github.com/emilk/egui#why-immediate-mode>.
//!
//! ## How widgets works
//!
//! ```
//! # let ui = &mut egui::Ui::__test();
//! if ui.button("click me").clicked() { take_action() }
//! # fn take_action() {}
//! ```
//!
//! is short for
//!
//! ```
//! # let ui = &mut egui::Ui::__test();
//! let button = egui::Button::new("click me");
//! if ui.add(button).clicked() { take_action() }
//! # fn take_action() {}
//! ```
//!
//! which is short for
//!
//! ```
//! # use egui::Widget;
//! # let ui = &mut egui::Ui::__test();
//! let button = egui::Button::new("click me");
//! let response = button.ui(ui);
//! if response.clicked() { take_action() }
//! # fn take_action() {}
//! ```
//!
//! [`Button`] uses the builder pattern to create the data required to show it. The [`Button`] is then discarded.
//!
//! [`Button`] implements `trait` [`Widget`], which looks like this:
//! ```
//! # use egui::*;
//! pub trait Widget {
//! /// Allocate space, interact, paint, and return a [`Response`].
//! fn ui(self, ui: &mut Ui) -> Response;
//! }
//! ```
//!
//! # Code snippets
//!

4
egui/src/widgets/mod.rs

@ -29,6 +29,10 @@ pub use {button::*, drag_value::DragValue, image::Image, slider::*, text_edit::*
// ----------------------------------------------------------------------------
/// Anything implementing Widget can be added to a [`Ui`] with [`Ui::add`].
///
/// Examples include `[Button]`, `[Label]` and [`Slider`].
///
/// `|ui: &mut Ui| -> Response { … }` also implemented `Widget`.
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
pub trait Widget {
/// Allocate space, interact, paint, and return a [`Response`].

2
egui/src/widgets/selected_label.rs

@ -1,7 +1,7 @@
use crate::*;
/// One out of several alternatives, either selected or not.
/// Will mark selected items with a different background color
/// Will mark selected items with a different background color.
/// An alternative to [`RadioButton`] and [`Checkbox`].
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
#[derive(Debug)]

2
egui_glium/src/painter.rs

@ -200,7 +200,7 @@ impl Painter {
let clip_max_x = pixels_per_point * clip_rect.max.x;
let clip_max_y = pixels_per_point * clip_rect.max.y;
// Make sure clip rect can fit withing an `u32`:
// Make sure clip rect can fit within a `u32`:
let clip_min_x = clamp(clip_min_x, 0.0..=width_in_pixels as f32);
let clip_min_y = clamp(clip_min_y, 0.0..=height_in_pixels as f32);
let clip_max_x = clamp(clip_max_x, clip_min_x..=width_in_pixels as f32);

11
emath/src/rect.rs

@ -20,10 +20,17 @@ impl Rect {
max: pos2(INFINITY, INFINITY),
};
/// The inverse of [`Self::EVERYTHING`]: streches from positive infinity to negative infinity.
/// The inverse of [`Self::EVERYTHING`]: stretches from positive infinity to negative infinity.
/// Contains no points.
///
/// This is useful as the seed for boulding bounding boxes.
/// This is useful as the seed for bounding bounding boxes.
///
/// ```
/// # use emath::*;
/// let inf = f32::INFINITY;
/// assert!(Rect::NOTHING.size() == Vec2::splat(-inf));
/// assert!(Rect::NOTHING.contains(pos2(0.0, 0.0)) == false);
/// ```
///
/// # Example:
/// ```

10
start_server.sh

@ -1,6 +1,12 @@
#!/bin/bash
set -eu
cd docs
# Starts a local web-server that servs the contents of the `doc/` folder,
# i.e. the web-version of `egui_demo_app`.
cargo install basic-http-server
echo "open http://localhost:8888"
python3 -m http.server 8888 --bind 127.0.0.1
(cd docs && basic-http-server --addr 127.0.0.1:8888 .)
# (cd docs && python3 -m http.server 8888 --bind 127.0.0.1)

Loading…
Cancel
Save