1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
//! Panoramix is an experimental GUI framework for the Rust programming language. //! //! This framework is **data-driven and declarative**, drawing some inspiration from [React](https://github.com/facebook/react), and implemented on top of the [Druid](https://github.com/linebender/druid) toolkit. //! //! It aims to use **simple, idiomatic Rust**: Panoramix doesn't use unsafe code, cells, mutexes, or DSL macros. //! //! //! ## Getting started //! //! Here is our "hello world" example: //! //! ```no_run //! use panoramix::elements::{Button, Label}; //! use panoramix::{component, Column, CompCtx, Element, NoEvent, RootHandler}; //! //! #[component] //! fn HelloBox(_ctx: &CompCtx, _props: ()) -> impl Element { //! Column!( //! Label::new("Hello world!"), //! Button::new("Say hello").on_click(|_, _| { //! println!("Hello world"); //! }) //! ) //! } //! //! fn main() -> Result<(), panoramix::PlatformError> { //! RootHandler::new(HelloBox) //! .with_tracing(true) //! .launch() //! } //! ``` //! //! To understand this example, let's define a few terms: //! //! - A **Widget** is the fundamental unit of GUI; for instance, a text field and a label are both widgets. You've probably seen the term if you've used other GUI frameworks. //! - An **Element** is a lightweight description of a Widget. In our example, [`Button::new`](elements::Button::new) and [`Label::new`](elements::Label::new) both return elements. The [`Column`] macro is similar to `vec` - it takes an arbitrary number of elements and returns a container element. //! - Some elements have builder methods. Eg: [`Button::on_click`](elements::Button::on_click). //! - A **Component** is a user-written function that takes **Props** as parameters and returns a tree of elements (or, more accurately, an arbitrary element that may or may not contain other elements). In our example, `HelloBox` is a component. By convention, components always have a CamelCase name. //! //! In Panoramix, you don't directly manipulate **widgets**; instead, you write **components** that return **elements**. The framework calls your components, gets a tree of elements, and builds a matching widget tree for you. When some event changes the application state, the framework calls your components again, gets a new element tree, and edits the widget tree accordingly. //! //! As such, the root of your Panoramix application will usually look like: //! //! ```no_run //! // main.rs //! //! use panoramix::elements::{Button, ButtonClick}; //! use panoramix::{component, CompCtx, Element, NoEvent, RootHandler}; //! //! #[derive(Debug, Default, Clone, PartialEq)] //! struct ApplicationState { //! // ... //! } //! //! #[component] //! fn MyRootComponent(ctx: &CompCtx, _props: ()) -> impl Element<NoEvent, ApplicationState> { //! // ... //! # panoramix::elements::EmptyElement::new() //! } //! //! fn main() -> Result<(), panoramix::PlatformError> { //! let initial_state = ApplicationState { //! // ... //! }; //! //! RootHandler::new(MyRootComponent) //! .with_initial_state(initial_state) //! .with_tracing(true) //! .launch() //! } //! ``` //! //! For information on how to write a component, see [this document on Github](https://github.com/PoignardAzur/panoramix/blob/main/misc_docs/writing_a_component.md). mod element_tree; mod glue; mod root_handler; mod widget_sequence; pub mod elements; pub mod widgets; pub mod flex; pub use panoramix_derive::component; pub use element_tree::{CompCtx, Element, ElementExt, NoEvent}; pub use root_handler::{PlatformError, RootHandler, RootWidget}; /// Traits and type used internally to compute the GUI pub mod backend { // Note: These items are declared together in files, but are exported separately here // to have a clean separation in the documentation between the items required to write // a GUI and the items required to create a GUI element. pub use crate::element_tree::{ReconcileCtx, VirtualDom}; pub use crate::glue::{Action, DruidAppData, GlobalEventCx, Id}; pub use crate::widget_sequence::{FlexWidget, WidgetSequence}; // TODO pub use crate::widgets; }