Skip to content

Commit

Permalink
Merge pull request #801 from futurepaul/wasm-example
Browse files Browse the repository at this point in the history
Simple wasm example
  • Loading branch information
futurepaul authored May 31, 2020
2 parents 47eaf1f + cf2e33f commit a4b0762
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,16 @@ jobs:
- name: wasm-pack build examples
run: wasm-pack build --dev --target web druid/examples/wasm

# Clippy and build the hello_wasm_web example
- name: cargo clippy hello_wasm_web example
uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path=druid/examples/hello_wasm_web/Cargo.toml --target wasm32-unknown-unknown -- -D warnings

- name: wasm-pack build hello_wasm_web example
run: wasm-pack build --target web druid/examples/hello_wasm_web

test-nightly:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ members = [
"druid-derive",
"docs/book_examples",
"druid/examples/wasm",
"druid/examples/hello_wasm_web",
]
16 changes: 16 additions & 0 deletions druid/examples/hello_wasm_web/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "hello-wasm-web"
version = "0.1.0"
license = "Apache-2.0"
description = "Minimal wasm example for web"
repository = "https://github.com/xi-editor/druid"
edition = "2018"
publish = false

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
druid = { path="../.."}
wasm-bindgen = "0.2.60"
console_error_panic_hook = { version = "0.1.6" }
29 changes: 29 additions & 0 deletions druid/examples/hello_wasm_web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# druid WASM hello world

This is a minimal example of building a single druid application for the web. To build all the druid examples as wasm, check out the main wasm example.

## Building

You will need `cargo` and `wasm-pack` for building the code and a simple
server like [`http`](https://crates.io/crates/https) for serving the web page.

First build with.

```
> wasm-pack build --target web --dev
```

This generates a JavaScript module that exports the `wasm_main` function that's been annotated with the `#[wasm_bindgen]` macro. Leave off the `--dev` flag if you're doing a release build.

Now run

```
> http
```

which should start serving this folder.

Finally, point your browser to the appropriate localhost url (usually http://localhost:8000) and you
should see your app.

When you make changes to the project, re-run `wasm-pack build --target web --dev` and you can see the changes in your browser when you refresh -- no need to restart `http`.
27 changes: 27 additions & 0 deletions druid/examples/hello_wasm_web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Druid WASM example</title>
<style>
html,
body,
canvas {
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>

<body>
<noscript>This page contains webassembly and javascript content, please enable javascript in your
browser.</noscript>
<canvas id="canvas"></canvas>
<script type="module" src="./index.js" type="application/javascript"></script>
</body>

</html>
8 changes: 8 additions & 0 deletions druid/examples/hello_wasm_web/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import init, { wasm_main } from "./pkg/hello_wasm_web.js";

async function run() {
await init();
wasm_main();
}

run();
72 changes: 72 additions & 0 deletions druid/examples/hello_wasm_web/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2020 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use druid::widget::{Align, Flex, Label, TextBox};
use druid::{AppLauncher, Data, Env, Lens, Widget, WidgetExt, WindowDesc};

use wasm_bindgen::prelude::*;

const VERTICAL_WIDGET_SPACING: f64 = 20.0;
const TEXT_BOX_WIDTH: f64 = 200.0;

#[derive(Clone, Data, Lens)]
struct HelloState {
name: String,
}

// This wrapper function is the primary modification we're making to the vanilla
// hello.rs example.
#[wasm_bindgen]
pub fn wasm_main() {
// This hook is necessary to get panic messages on wasm32
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
main()
}

pub fn main() {
// describe the main window
//
// Window title is set in index.html and window size is ignored on the web,
// so can we leave those off.
let main_window = WindowDesc::new(build_root_widget);

// create the initial app state
let initial_state = HelloState {
name: "World".into(),
};

// start the application
AppLauncher::with_window(main_window)
.launch(initial_state)
.expect("Failed to launch application");
}

fn build_root_widget() -> impl Widget<HelloState> {
// a label that will determine its text based on the current app data.
let label = Label::new(|data: &HelloState, _env: &Env| format!("Hello {}!", data.name));
// a textbox that modifies `name`.
let textbox = TextBox::new()
.with_placeholder("Who are we greeting?")
.fix_width(TEXT_BOX_WIDTH)
.lens(HelloState::name);

// arrange the two widgets vertically, with some padding
let layout = Flex::column()
.with_child(label)
.with_spacer(VERTICAL_WIDGET_SPACING)
.with_child(textbox);

// center the two widgets in the available space
Align::centered(layout)
}

0 comments on commit a4b0762

Please sign in to comment.