diff --git a/crates/masonry/CONTRIBUTING.md b/crates/masonry/CONTRIBUTING.md deleted file mode 100644 index b064a1c5..00000000 --- a/crates/masonry/CONTRIBUTING.md +++ /dev/null @@ -1,30 +0,0 @@ -# How to contribute - -Issues and PRs are welcome. See [help-wanted issues](https://github.com/PoignardAzur/masonry-rs/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) if you don't know where to begin. - -## Issues - -Issues don't have a specific format. - -If you submit one, please be polite, remember that most Masonry contributors are unpaid volunteers, and include detailed steps to reproduce any problem. - - -## Pull requests - -All submissions, including submissions by project members, require review. We use GitHub Pull Requests for this purpose. Consult GitHub Help for more information on using pull requests. - -Before making a PR, please follow these steps: - -- Run `cargo test --all-targets` on your code. -- Run `cargo test --doc`. -- Run `cargo clippy --all-targets`. - -Masonry doesn't keep a changelog for now, but might in the future. Make sure your commit messages and pull request titles explain what you have changed. -How to maintain - - -## Preparing for a new release - -Before a new release, make sure to update every dependency to their last version. - -You can use `cargo upgrade` from the `cargo-edit` tool to help with the process. diff --git a/crates/masonry/Cargo.toml b/crates/masonry/Cargo.toml index f7ece0e1..e6f6ef35 100644 --- a/crates/masonry/Cargo.toml +++ b/crates/masonry/Cargo.toml @@ -8,6 +8,7 @@ edition.workspace = true license.workspace = true repository.workspace = true homepage.workspace = true +exclude = ["/doc/", ".gitignore"] [package.metadata.docs.rs] all-features = true diff --git a/crates/masonry/README.md b/crates/masonry/README.md index 83ca372a..d9744a39 100644 --- a/crates/masonry/README.md +++ b/crates/masonry/README.md @@ -1,157 +1,44 @@ -## Masonry +
-Masonry is a framework that aims to provide the foundation for Rust GUI libraries. +# Masonry -Masonry gives you a platform to create windows (using [Glazier](https://github.com/linebender/glazier) as a backend) each with a tree of widgets. It also gives you tools to inspect that widget tree at runtime, write unit tests on it, and generally have an easier time debugging and maintaining your app. +**Foundational framework for Rust GUI libraries** + +[![Latest published version.](https://img.shields.io/crates/v/masonry.svg)](https://crates.io/crates/masonry) +[![Documentation build status.](https://img.shields.io/docsrs/masonry.svg)](https://docs.rs/masonry) +[![Apache 2.0 license.](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](#license) + +[![Linebender Zulip chat.](https://img.shields.io/badge/Linebender-%23masonry-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/stream/317477-masonry) +[![GitHub Actions CI status.](https://img.shields.io/github/actions/workflow/status/linebender/xilem/ci.yml?logo=github&label=CI)](https://github.com/linebender/xilem/actions) +[![Dependency staleness status.](https://deps.rs/crate/masonry/latest/status.svg)](https://deps.rs/crate/masonry) + +
+ +Masonry gives you a platform to create a window (using [winit] as a backend) with a tree of widgets. +It also gives you tools to inspect that widget tree at runtime, write unit tests on it, and generally have an easier time debugging and maintaining your app. The framework is not opinionated about what your user-facing abstraction will be: you can implement immediate-mode GUI, the Elm architecture, functional reactive GUI, etc, on top of Masonry. +See [Xilem] as an example of reactive UI built on top of Masonry. -This project was originally a fork of [Druid](https://github.com/linebender/druid) that emerged from discussions I had with Raph Levien and Colin Rofls about what it would look like to turn Druid into a foundational library. +Masonry was originally a fork of [Druid] that emerged from discussions with Druid authors Raph Levien and Colin Rofls about what it would look like to turn Druid into a foundational library. -## Installing +Masonry can currently be considered to be in an alpha state. +Lots of things need improvements, e.g. text input is janky and snapshot testing is not consistent across platforms. -```sh -cargo add masonry -``` +## Community -### Linux +Discussion of Masonry development happens in the [Linebender Zulip](https://xi.zulipchat.com/), specifically the [#masonry stream](https://xi.zulipchat.com/#narrow/stream/317477-masonry). +All public content can be read without logging in. -On Linux, Masonry requires gtk+3; see [GTK installation page](https://www.gtk.org/docs/installations/linux/). -(On ubuntu-based distro, running `sudo apt-get install libgtk-3-dev` from the terminal will do the job.) +Contributions are welcome by pull request. The [Rust code of conduct] applies. -### OpenBSD +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache 2.0 license, shall be licensed as noted in the [License](#license) section, without any additional terms or conditions. -On OpenBSD, Masonry requires gtk+3; install from packages: -```sh -pkg_add gtk+3 -``` +## License -## Example +Licensed under the Apache License, Version 2.0 ([LICENSE](LICENSE) or ) -The todo-list example looks like this: - -```rust -use masonry::widget::{prelude::*, TextBox}; -use masonry::widget::{Button, Flex, Label, Portal, WidgetMut}; -use masonry::Action; -use masonry::{AppDelegate, AppLauncher, DelegateCtx, WindowDescription, WindowId}; - -const VERTICAL_WIDGET_SPACING: f64 = 20.0; - -struct Delegate { - next_task: String, -} - -impl AppDelegate for Delegate { - fn on_action( - &mut self, - ctx: &mut DelegateCtx, - _window_id: WindowId, - _widget_id: WidgetId, - action: Action, - ) { - match action { - Action::ButtonPressed => { - let mut root: WidgetMut> = ctx.get_root(); - let mut flex = root.child_mut(); - flex.add_child(Label::new(self.next_task.clone())); - } - Action::TextChanged(new_text) => { - self.next_task = new_text.clone(); - } - _ => {} - } - } -} - -fn main() { - // The main button with some space below, all inside a scrollable area. - let root_widget = Portal::new( - Flex::column() - .with_child( - Flex::row() - .with_child(TextBox::new("")) - .with_child(Button::new("Add task")), - ) - .with_spacer(VERTICAL_WIDGET_SPACING), - ); - - let main_window = WindowDescription::new(root_widget) - .title("To-do list") - .window_size((400.0, 400.0)); - - AppLauncher::with_window(main_window) - .with_delegate(Delegate { - next_task: String::new(), - }) - .log_to_console() - .launch() - .expect("Failed to launch application"); -} -``` - -As you can see, compared to crates like Druid or Iced, Masonry takes a fairly low-level approach to GUI: there is no complex reconciliation logic or dataflow going on behind the scenes; if you want to add a widget to the flex container, you call `flex.add_child(your_widget)`. - -This simplicity makes Masonry somewhat painful if you want to use it to actually build GUI applications. The hope is that, by being low-level and straightforward, developers can easily build GUI frameworks on top of it. - -(Well, in theory. The first stress-test will be porting [Panoramix](https://github.com/PoignardAzur/panoramix), a React-style GUI in Rust, to Masonry.) - - -## Unit tests - -Masonry is designed to make unit tests easy to write, as if the test function were a mouse-and-keyboard user. Tests look like this: - -```rust -#[test] -fn some_test_with_a_button() { - let [button_id] = widget_ids(); - let widget = Button::new("Hello").with_id(button_id); - - let mut harness = TestHarness::create(widget); - - // Make a snapshot test of the visual contents of the window - assert_render_snapshot!(harness, "hello"); - - harness.edit_root_widget(|mut button, _| { - let mut button = button.downcast::