Skip to content

Commit

Permalink
Merge branch 'main' into feat/flex
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 authored Oct 13, 2024
2 parents 531d14b + 672a6b4 commit 9ac867e
Show file tree
Hide file tree
Showing 40 changed files with 454 additions and 154 deletions.
Binary file added .github/overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Cargo.lock
.idea
snapshot_before.png
snapshot_after.png
documents_example
documents_example
bacon.toml
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ cargo +nightly fmt --all -- --error-on-unformatted --unstable-features
Freya is split in various crates, each with it's own meaning and purpose, here is the list sorted by their importance:

- `freya`: Entrypoint to the library used by end users, mainly reexports the other crates and contains the launch methods.
- `renderer`: GUI Renderer using Winit and a Skia Canvas to render the app.
- `core`: Core logic for events, DOM processing, accessibility integration and text layout measurement is located here.
- `native-core`: DOM tree-like data structure to hold all the nodes with their attribute values and registered event handlers.
- `renderer`: Provides a winit event loop based execution for the app.
- `core`: Core logic for events, DOM processing, accessibility integration, element rendering and text layout measurement is located here.
- `native-core`: DOM data structure to hold all the nodes with their attribute values and registered event handlers.
- `torin`: UI layout library specifically made for Freya, although it's agnostic.
- `hooks`: Various Dioxus hooks to be used in Freya apps (text editing, animation, theming, etc)
- `components`: Collection of built-in Dioxus components to be used out of the box with in Freya apps (Button, Switch, Slider, Table, ScrollView, etc)
Expand All @@ -38,6 +38,8 @@ Freya is split in various crates, each with it's own meaning and purpose, here i
- `native-core-macro`: Just some internal macros to be used in `states` so it can be integrated with `native-core`.
- `common`: Some simple utilities used across the different Freya crates.

![Overview](./.github/overview.png)

## Examples
All important examples are located in the `./examples` folder although you might also find some in the form of docs comments in the code itself.

Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ dioxus-signals = { version = "0.5" }
dioxus-core = { version = "0.5" }
dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-features = false }
dioxus-router = { version = "0.5", default-features = false }
dioxus-sdk = { version = "0.5", features = ["clipboard"]}
dioxus-clipboard = "0.1"

skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] }

Expand Down Expand Up @@ -96,7 +96,7 @@ tree-sitter-highlight = "0.23.0"
tree-sitter-rust = "0.23.0"
rfd = "0.14.1"
bytes = "1.5.0"
dioxus-sdk = { workspace = true }
dioxus-clipboard = { workspace = true }
winit = { workspace = true }

[profile.release]
Expand Down
39 changes: 25 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

[Website](https://freyaui.dev) | [Nightly Docs](https://docs.freyaui.dev/freya) | [Stable Docs](https://docs.rs/freya/latest/freya) | [Book](https://book.freyaui.dev) | [Discord](https://discord.gg/sYejxCdewG)

**Freya** is a cross-paltform GUI library for Rust powered by 🧬 [Dioxus](https://dioxuslabs.com) and 🎨 [Skia](https://skia.org/).
**Freya** is a cross-platform GUI library for Rust powered by 🧬 [Dioxus](https://dioxuslabs.com) and 🎨 [Skia](https://skia.org/).

**It does not use any web tech**, check the [Differences with Dioxus](https://book.freyaui.dev/differences_with_dioxus.html).

⚠️ It's currently work in progress, but you can already play with it! You can join the [Discord](https://discord.gg/sYejxCdewG) server if you have any question or issue.

<br/>
<br/>

<table>
Expand Down Expand Up @@ -66,12 +65,6 @@ fn app() -> Element {
</td>
</table>

### Sponsors 🤗

Thanks to my sponsors for supporting this project! 😄

<!-- sponsors --><a href="https://github.com/piny4man"><img src="https:&#x2F;&#x2F;avatars.githubusercontent.com&#x2F;u&#x2F;8446285?u&#x3D;fd37db4dd9b4ba94dabe0bccc3a95ef2a35376ab&amp;v&#x3D;4" width="60px" alt="" /></a><a href="https://github.com/gqf2008"><img src="https:&#x2F;&#x2F;avatars.githubusercontent.com&#x2F;u&#x2F;2295878?v&#x3D;4" width="60px" alt="高庆丰" /></a><!-- sponsors -->

### Want to try it? 🤔

👋 Make sure to check the [Setup guide](https://book.freyaui.dev/setup.html) first.
Expand All @@ -93,19 +86,21 @@ Add Freya and Dioxus as dependencies:
freya = "0.2"
dioxus = { version = "0.5", features = ["macro", "hooks"], default-features = false }
```
### Contributing 🧙‍♂️

If you are interested in contributing please make sure to have read the [Contributing](CONTRIBUTING.md) guide first!

### Features ✨
- ⛏️ Built-in **components** (button, scroll views, switch and more)
- 🚇 Built-in **hooks** library (animations, text editing and more)
- 🔍 Built-in **devtools** panel
- 🚇 Built-in **hooks** (animations, text editing and more)
- 🔍 Built-in **developer tools** (tree inspection, fps overlay)
- 🧰 Built-in **headless runner** to test UI
- 🎨 **Theming** support (not extensible yet ⚠️)
- 🎨 **Theming** support
- 🛩️ **Cross-platform** (Windows, Linux, MacOS)
- 🖼️ SKSL **Shaders** support
- 🔄️ Dioxus **Hot-reload** support
- 📒 Multi-line **text editing**
- 🦾 Basic **Accessibility** Support (experimental ⚠️)
- 🧩Compatible with dioxus-sdk and other Dioxus renderer-agnostic libraries
- 🦾 **Accessibility** support
- 🧩 Compatible with dioxus-sdk and other Dioxus renderer-agnostic libraries

### Goals 😁
- Performant and low memory usage
Expand All @@ -115,6 +110,22 @@ dioxus = { version = "0.5", features = ["macro", "hooks"], default-features = fa
- Useful testing APIs
- Useful and extensible built-in components and hooks

### Support 🤗

If you are interested in supporting the development of this project feel free to donate to my [Github Sponsor](https://github.com/sponsors/marc2332/) page.

Thanks to my sponsors for supporting this project! 😄

<!-- sponsors --><a href="https://github.com/piny4man"><img src="https:&#x2F;&#x2F;avatars.githubusercontent.com&#x2F;u&#x2F;8446285?u&#x3D;fd37db4dd9b4ba94dabe0bccc3a95ef2a35376ab&amp;v&#x3D;4" width="60px" alt="" /></a><a href="https://github.com/gqf2008"><img src="https:&#x2F;&#x2F;avatars.githubusercontent.com&#x2F;u&#x2F;2295878?v&#x3D;4" width="60px" alt="高庆丰" /></a><!-- sponsors -->

### Special thanks 💪

- [Jonathan Kelley](https://github.com/jkelleyrtp) and [Evan Almloff](https://github.com/ealmloff) for making [Dioxus](https://dioxuslabs.com/) and all their help, specially when I was still creating Freya.
- [Armin](https://github.com/pragmatrix) for making [rust-skia](https://github.com/rust-skia/rust-skia/) and all his help and making the favor of hosting prebuilt binaries of skia for the combo of features use by Freya.
- [geom3trik](https://github.com/geom3trik) for helping me figure out how to add incremental rendering.
- [Tropical](https://github.com/Tropix126) for this contributions to improving accessibility and rendering.
- And to the rest of contributors and anybody who gave me any kind of feedback!

### 🤠 Projects

[Valin](https://github.com/marc2332/valin) ⚒️ is a Work-In-Progress cross-platform code editor, made with Freya 🦀 and Rust, by me.
Expand Down
24 changes: 23 additions & 1 deletion crates/components/src/activable_route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,29 @@ use dioxus_router::{
};
use freya_hooks::ActivableRouteContext;

/// Provide a context to the inner components so they can know whether the passed route is the current router in the Router or not.
/// Sometimes you might want to know if a route is selected so you can style a specific UI element in a different way,
/// like a button with a different color.
/// To avoid cluttering your components with router-specific code you might instead want to wrap your component in an `ActivableRoute`
/// and inside your component call `use_activable_route`.
///
/// This way, your component and all its desdendants will just know whether a route is activated or not, but not which one.
///
/// ```rs
/// Link {
/// to: Route::Home, // Direction route
/// ActivableRoute {
/// route: Route::Home, // Activation route
/// SidebarItem {
/// // `SidebarItem` will now appear "activated" when the route is `Route::Home`
/// // `ActivableRoute` is letting it know whether `Route::Home` is enabled
/// // or not, without the need to add router-specific logic in `SidebarItem`.
/// label {
/// "Go to Hey ! 👋"
/// }
/// },
/// }
/// }
/// ```
#[allow(non_snake_case)]
#[component]
pub fn ActivableRoute<T: Clone + PartialEq + Routable + 'static>(
Expand Down
1 change: 1 addition & 0 deletions crates/components/src/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ pub fn ButtonBase(
corner_radius: "{corner_radius}",
background: "{background}",
text_align: "center",
text_height: "disable-least-ascent",
main_align: "center",
cross_align: "center",
{&children}
Expand Down
8 changes: 7 additions & 1 deletion crates/components/src/native_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ use dioxus::prelude::*;
use freya_core::prelude::EventMessage;
use freya_elements::{
elements as dioxus_elements,
events::KeyboardEvent,
events::{
keyboard::{
Key,
Modifiers,
},
KeyboardEvent,
},
};
use freya_hooks::{
use_init_native_platform,
Expand Down
5 changes: 4 additions & 1 deletion crates/components/src/popup.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use dioxus::prelude::*;
use freya_elements::{
elements as dioxus_elements,
events::KeyboardEvent,
events::{
keyboard::Key,
KeyboardEvent,
},
};
use freya_hooks::{
theme_with,
Expand Down
1 change: 1 addition & 0 deletions crates/components/src/progress_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub fn ProgressBar(
width: "100%",
color: "{color}",
max_lines: "1",
text_height: "disable-least-ascent",
"{progress.floor()}%"
}
}
Expand Down
14 changes: 10 additions & 4 deletions crates/components/src/scroll_views/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,16 @@ pub fn ScrollView(

let direction_is_vertical = direction == "vertical";

let vertical_scrollbar_is_visible =
is_scrollbar_visible(show_scrollbar, size.inner.height, size.area.height());
let horizontal_scrollbar_is_visible =
is_scrollbar_visible(show_scrollbar, size.inner.width, size.area.width());
let vertical_scrollbar_is_visible = is_scrollbar_visible(
show_scrollbar,
size.inner.height.floor(),
size.area.height().floor(),
);
let horizontal_scrollbar_is_visible = is_scrollbar_visible(
show_scrollbar,
size.inner.width.floor(),
size.area.width().floor(),
);

let (container_width, content_width) = get_container_size(
&width,
Expand Down
1 change: 1 addition & 0 deletions crates/components/src/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use dioxus::prelude::*;
use freya_elements::{
elements as dioxus_elements,
events::{
keyboard::Key,
KeyboardEvent,
MouseEvent,
WheelEvent,
Expand Down
2 changes: 2 additions & 0 deletions crates/components/src/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use freya_hooks::{
AnimNum,
Ease,
Function,
OnDepsChange,
SwitchThemeWith,
};
use winit::window::CursorIcon;
Expand Down Expand Up @@ -67,6 +68,7 @@ pub enum SwitchStatus {
pub fn Switch(props: SwitchProps) -> Element {
let theme = use_applied_theme!(&props.theme, switch);
let animation = use_animation_with_dependencies(&theme, |ctx, theme| {
ctx.on_deps_change(OnDepsChange::Run);
(
ctx.with(
AnimNum::new(2., 22.)
Expand Down
3 changes: 1 addition & 2 deletions crates/components/src/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use dioxus::prelude::*;
use freya_elements::{
elements as dioxus_elements,
events::{
keyboard::Key,
KeyboardEvent,
MouseEvent,
},
Expand Down Expand Up @@ -42,8 +43,6 @@ pub fn Tile(
onselect: Option<EventHandler<()>>,
/// Theme override.
theme: Option<TileThemeWith>,

a11y_name: Option<String>,
) -> Element {
let mut status = use_signal(TileStatus::default);
let platform = use_platform();
Expand Down
19 changes: 10 additions & 9 deletions crates/core/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,23 @@ pub fn process_layout(
let mut compositor_dirty_area = fdom.compositor_dirty_area();
let mut buffer = layout.dirty.iter().copied().collect_vec();
while let Some(node_id) = buffer.pop() {
if let Some(area) = Compositor::get_drawing_area(node_id, &layout, rdom, scale_factor) {
// Unite the invalidated area with the dirty area
compositor_dirty_area.unite_or_insert(&area);
if let Some(node) = rdom.get(node_id) {
if let Some(area) =
Compositor::get_drawing_area(node_id, &layout, rdom, scale_factor)
{
// Unite the invalidated area with the dirty area
compositor_dirty_area.unite_or_insert(&area);

// Mark these elements as dirty for the compositor
compositor_dirty_nodes.insert(node_id);
// Mark these elements as dirty for the compositor
compositor_dirty_nodes.insert(node_id);

// Continue iterating in the children of this node
if let Some(node) = rdom.get(node_id) {
// Mark as invalidated this node as its layout has changed
if node.get_accessibility_id().is_some() {
dirty_accessibility_tree.add_or_update(node_id);
}

buffer.extend(node.child_ids());
}
// Continue iterating in the children of this node
buffer.extend(node.child_ids());
}
}
let root_id = fdom.rdom().root_id();
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/render/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ mod test {
use itertools::sorted;

fn run_compositor(
utils: &TestingHandler,
utils: &TestingHandler<()>,
compositor: &mut Compositor,
) -> (Layers, Layers, usize) {
let sdom = utils.sdom();
Expand Down
4 changes: 3 additions & 1 deletion crates/core/src/render/utils/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ pub fn create_label(
paragraph_style.set_text_align(font_style.text_align);
paragraph_style.set_max_lines(font_style.max_lines);
paragraph_style.set_replace_tab_characters(true);
paragraph_style.set_text_height_behavior(font_style.text_height);

if let Some(ellipsis) = font_style.text_overflow.get_ellipsis() {
paragraph_style.set_ellipsis(ellipsis);
}

let text_style = font_style.text_style(default_font_family, scale_factor);
let text_style =
font_style.text_style(default_font_family, scale_factor, font_style.text_height);
paragraph_style.set_text_style(&text_style);

let mut paragraph_builder = ParagraphBuilder::new(&paragraph_style, font_collection);
Expand Down
12 changes: 9 additions & 3 deletions crates/core/src/render/utils/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ pub fn create_paragraph(
paragraph_style.set_text_align(font_style.text_align);
paragraph_style.set_max_lines(font_style.max_lines);
paragraph_style.set_replace_tab_characters(true);
paragraph_style.set_text_height_behavior(font_style.text_height);

if let Some(ellipsis) = font_style.text_overflow.get_ellipsis() {
paragraph_style.set_ellipsis(ellipsis);
}

let mut paragraph_builder = ParagraphBuilder::new(&paragraph_style, font_collection);

let text_style = font_style.text_style(default_font_family, scale_factor);
let text_style =
font_style.text_style(default_font_family, scale_factor, font_style.text_height);
paragraph_builder.push_style(&text_style);

for text_span in node.children() {
Expand All @@ -52,8 +54,12 @@ pub fn create_paragraph(
let text_nodes = text_span.children();
let text_node = *text_nodes.first().unwrap();
let text_node_type = &*text_node.node_type();
let font_style = text_span.get::<FontStyleState>().unwrap();
let text_style = font_style.text_style(default_font_family, scale_factor);
let text_font_style = text_span.get::<FontStyleState>().unwrap();
let text_style = text_font_style.text_style(
default_font_family,
scale_factor,
font_style.text_height,
);
paragraph_builder.push_style(&text_style);

if let NodeType::Text(text) = text_node_type {
Expand Down
22 changes: 22 additions & 0 deletions crates/elements/src/_docs/attributes/text_height.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Specify the text height behavior.

Accepted values:

- `disable-all` (default)
- `all`
- `disable-first-ascent`
- `disable-least-ascent`

### Example

```rust, no_run
# use freya::prelude::*;
fn app() -> Element {
rsx!(
label {
text_height: "disable-all",
"Hello, World!"
}
)
}
```
Loading

0 comments on commit 9ac867e

Please sign in to comment.