• Stars
    star
    384
  • Rank 111,726 (Top 3 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An experimental GUI framework for Rust, backed by per-platform native widgets. React, AppKit/UIKit inspired. EXPERIMENTAL, runs on Cocoa right now. ;P

Notice

This project is on indefinite hiatus for right now. I appreciate the Rust community's interest in GUI frameworks, but this project is personal for me - I worked on it extensively during a time when my younger brother was battling Leukemia, and so returning to it brings up a lot of things that I prefer to take time dealing with.

If you're interested in following work I'm doing in the GUI space with regards to Rust, feel free to follow appkit-rs, which would end up being one of the underlying layers of this anyway (much the same way that gtk-rs would need to back, well, Gtk).

Potion

Alchemy - A Rust GUI Framework

Crates.io

Homepage • API Documentation

Alchemy is an experimental Rust GUI Framework, backed by native widgets on each platform it supports, with an API that's a blend of those found in AppKit, UIKit, and React Native. It aims to provide an API that feels at home in Rust, while striving to provide a visual appearance that's easy to scan and parse. It does not, and will never, require nightly. It's still early stages, but feedback and contributions are welcome.

Supported Platforms

Alchemy will, ideally, support the platforms listed below. At the moment, the Cocoa backend is the most complete, as I develop on a Mac and know the framework more than I'd care to admit. This list will be updated as more frameworks are added.

  • cocoa, which provides backing widgets, windows and assorted frameworks for macOS.
  • cocoa-touch, which provides backing widgets, windows and assorted frameworks for iOS.
  • gtk, which affords a GTK layer. This is mostly intended for GNOME users; if you'd like to run it elsewhere, you're on your own.
  • uwp, which affords a "UWP" layer for Microsoft platforms that support it. This will be a bit of a hack, provided by linking into the microsoft/WinObjC framework, originally intended for porting iOS applications to UWP. Down the road, if or when a proper UWP library for Rust surfaces, I'd be happy to look at replacing this.

Support for more platforms is desired - for example, I think an OrbTk or Piston backend could be cool to see. A web backend would be awesome to support. A winapi-rs backend could be cool, too!

What Currently Works...?

At the moment, the following is implemented:

  • A basic cocoa API, which implements the Application and Window lifecycles. <View />, <Text />, and <Fragment /> are supported as well.
  • A basic reconciliation module, which handles computing changes to the widget tree and applying them as necessary. It currently follows a design similar to React pre-16; I'm open to changing this if someone wants to collaborate.
  • A CSS parser, based on the work done over in servo/servo. It doesn't support cascading, and follows an API closer to that of React Native's. This is intentional.
  • An RSX system, based on work done in bodil/typed-html by Bodil Stokke. This was actually the project that made me circle back to the entire thing, too.
  • Macros for easy UI construction - rsx! {}, which transforms JSX-ish syntax into element trees for the reconciler to work with, and styles! {}, which pre-process CSS into their styles.
  • A CSS layout system, based off the work done over in vislyhq/stretch. At the moment, this project includes a fork with a newer underlying API by msiglreith. Once the API is merged upstream, it's likely the dependency would change to stretch proper.

You can clone this repo and cargo run from the root to see the example app.

What's it look like?

use alchemy::{AppDelegate, Error, RSX, rsx, styles, View, Window, WindowDelegate};

struct AppState {
    window: Window
}

impl AppDelegate for AppState {
    fn did_finish_launching(&mut self) {
        self.window.set_title("Test");
        self.window.set_dimensions(10., 10., 600., 600.);
        self.window.show();
    }
}

struct WindowState;

impl WindowDelegate for WindowState {
    fn render(&self) -> Result<RSX, Error> {
        Ok(rsx! {
            <View styles=["box"]>
                <View styles=["innerbox"] />
            </View>
        })
    }
}

fn main() {
    let app = alchemy::shared_app();

    app.register_styles("default", styles! {
        box {
            background-color: #307ace;
            width: 300;
            height: 300;
            margin-top: 10;
            padding-top: 10;
        }

        innerbox {
            background-color: #003366;
            width: 200;
            height: 200;
        }
    });

    app.run(AppState {
        window: Window::new(WindowState {
        
        })
    });
}

Does it support custom Components?

Yes. Alchemy implements the React component lifecycle - although it does not (currently) implement Hooks, and may or may not implement them in the future. The class-based lifecycle maps fairly well to Rust idioms already, as you really never wanted to subclass in React anyway.

A custom component would look like the following:

use alchemy::{Component, ComponentKey, Error, Props, rsx, RSX};

#[derive(Default)]
pub struct MySpecialWidgetProps;

#[derive(Props)]
pub struct MySpecialWidget {
    props: MySpecialWidgetProps
}

impl Component for MySpecialWidget {
    fn new(key: ComponentKey) -> MySpecialWidget {
        MySpecialWidget {}
    }
    
    fn component_did_mount(&mut self) {
        // Do whatever you want. Fire a network request or something, I dunno.
    }

    fn render(&self, children: Vec<RSX>) -> Result<RSX, Error> {
        Ok(RSX::None)
    }
}

Rust allows the lifecycle to have a few cool guarantees that you can't really get in JavaScript - for instance, props don't actually belong to you... but it was a weird aspect of class-based components in JavaScript where you'd be able to arbitrarily call this.props.whatever. Function based components actually communicated it better, in that they were passed in - with Rust, it's very clear that you just get a reference.

Alchemy follows this diagram of React's lifecycle methods to a T for the most part. What's cool is that methods that shouldn't have side effects, we can call as straight up borrows... and the ones that are allowed to have mutable side effects, we can call them as &mut self. You can, of course, still incur side effects by doing something else, but being able to imply the intention directly in the API is kind of cool.

License

I'm dual licensing this, due to the licenses that some of the projects it depends on being that. If there's some other (more appropriate) way to do this, please feel free to open an issue.

Contributing

Before contributing, please read the contributors guide for useful information about setting up Alchemy locally, coding style and common abbreviations.

Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in the work, should be dual-licensed as above, without any additional terms or conditions.

Notes

  • Major thanks to David McNeil for graciously allowing me to take the alchemy name on crates.io. Hot take, if we had user namespacing, this wouldn't be an issue!
  • Cheers to diesel-rs/diesel, who have a very well laid out repository that a bunch of this structure was cribbed from.
  • Questions or comments that you don't think warrant an issue? Feel free to poke me over on Twitter or email me ([email protected]).

More Repositories

1

twython

Actively maintained, pure Python wrapper for the Twitter API. Supports both normal and streaming Twitter APIs.
Python
1,849
star
2

cacao

Rust bindings for AppKit (macOS) and UIKit (iOS/tvOS). Experimental, but working!
Rust
1,560
star
3

wrench-js

Recursive file operations in Node.js
JavaScript
438
star
4

wii-js

A sane, documented, (hopefully) performant event-based library for Wiimote webpage interaction.
JavaScript
154
star
5

jelly

User authentication/sessions/etc for Actix-Web. More of a sample project than a crate, but probably useful to some people.
Rust
89
star
6

twython-django

An example Django application to showcase how to use OAuth with Twitter in Django using Twython.
Python
73
star
7

1.1.1.1-macOS

Experimenting with cloning CloudFlare's 1.1.1.1 app as a macOS status bar app.
Swift
34
star
8

cloudkit-sane-sharing

A dump of code that illustrates a better way to share CloudKit resources.
Swift
29
star
9

react-iconpack

A React Component for handling SVG icons, coupled with Babel and Browserify plugins to only bundle the icons you use.
JavaScript
25
star
10

django-rednoise

An opinionated addon for WhiteNoise, with a focus on Django environments.
Python
18
star
11

pythentic_jobs

A pure Python wrapper around the Authentic Jobs (http://www.authenticjobs.com) API.
Python
18
star
12

svgalib-1

It's not svgalib "dash" 1, it's svgalib negative 1, because if you still use this library there's probably something wrong with you. That said, this is a 'fork' of the most recent (haha) version found on the internets, with a ton of patches from various people around the internet cobbled together. I have not and will not make any outlandish efforts to credit people, but if you see something here you wrote and you want credit, message me. Should fix a lot of compiling issues under recent issues of Linux.
C
16
star
13

webpack-babel-react-setup-lesson

Walking through setting up Webpack, Babel, and React.
JavaScript
15
star
14

memelee

An unofficial smash.gg app, read-only.
JavaScript
13
star
15

node-utf8

utf8 encoding and decoding in Node.js
JavaScript
12
star
16

drinkkitcom

A Foursquare clone written in Django to let Redditors broadcast DC bar crawls.
Python
11
star
17

gitstatus

A Github-repository widget to display most recent commits on a given repository.
JavaScript
8
star
18

jTransliterate

Transliterate [Hirag/Katak]ana to Latin/English and back with Python. Convert half/full-width Japanese text.
Python
7
star
19

holidaycalendar

A demo holiday calendar, which shows how to make NSCollectionViewItem's swipeable.
Swift
6
star
20

franz

Client side color swatches.
JavaScript
4
star
21

beyond-react

Session 4, going beyond React and integrating with other libraries.
JavaScript
3
star
22

activity-scraper

A social media scraper written in Rust. Used for the data on my personal site.
Rust
3
star
23

shinekit

iOS/macOS/Windows UI in Rust. Highly experimental.
Rust
3
star
24

rubeclosures

Ruby wrapper for the foreclosurelistings.com API
Ruby
2
star
25

splash

A programming language aimed at kids. Builds on their existing writing skills and doesn't try to reinvent arcane logic.
JavaScript
2
star
26

react-flux-redux-lesson

Walkthrough guide for React session #2 via Codementor.
JavaScript
2
star
27

react-router-lesson

React Router & co.
JavaScript
1
star
28

jsmag

Random JSMag Code Samplings
JavaScript
1
star
29

katakana

An Android application that aims to teach people Katakana through a basic brain-timing-calculation/algorithmic method.
Java
1
star
30

redditimages

Reddit: Images in Comments hack
JavaScript
1
star
31

takeoff

A Chrome extension to randomly load up one of your bookmarks on new windows/tabs, built for user "hokku". Enjoy.
1
star
32

smashgg-upcoming-tournaments

A scraper example for finding upcoming tournaments on smash.gg. From an unreleased side project, might be fun for some people.
Rust
1
star