Repository navigation
Browser
ZeppelinForms.Browser runs the same forms in WebAssembly, drawn into a canvas with
SkiaSharp. The showcase is such an application —
examples/ZF Wasm in the repository.
public static class Program
{
static Task Main()
{
// characters the font lacks: added before RunAsync, which downloads them
FontFallbacks.Add("/fonts/NotoSansHebrew-Regular.ttf");
FontFallbacks.Add("/fonts/NotoSansJP-Regular.otf");
return BrowserApp.RunAsync(
() => new MainForm(),
font: "/fonts/Inter-Regular.ttf",
preload: ["/Assets/Logo.png"]);
}
}| Parameter | |
|---|---|
mainForm |
A factory: a form measures text in its constructor, and the text measurer exists only once the platform is made |
font |
The font file — also its address on the server. Becomes Font.Default
|
preload |
Files needed synchronously later — pictures for Image.LoadAsset and the like |
fontFamily, fontSize
|
The default font's family (from the file name by default) and size |
canvasId |
The canvas to draw into, zf-canvas by default |
theme |
The theme to start with |
The browser has no file system: BrowserApp downloads font, preload and the
FontFallbacks into a virtual one before the first form is built, after which
Image.LoadAsset and Font.WithFile work as on the desktop. A file the server doesn't have
fails the start with a message in the browser's console.
wwwroot/index.html:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover, interactive-widget=resizes-content" />
</head>
<body>
<canvas id="zf-canvas"></canvas>
<script type="module" src="main.js"></script>
</body>wwwroot/main.js:
import { dotnet } from "./_framework/dotnet.js";
import * as zf from "./zf.js";
const runtime = await dotnet.create();
runtime.setModuleImports("zf", { ...zf });
const exports = await runtime.getAssemblyExports("ZeppelinForms.Browser");
globalThis.zfExports = exports.ZeppelinForms.Browser.Interop;
await runtime.runMain();zf.js ships with ZeppelinForms.Browser; copy it into the application's wwwroot. A
project made by dotnet new zf-app has these three files already, zf.js of the
templates' version.
viewport-fit=cover lets the page go under a phone's notch and gesture bar and tells the
form where they are (Form.SafeAreaInsets); interactive-widget=resizes-content makes the
page shorter when the on-screen keyboard opens, so the focused field is lifted above it.
A NavigationHost makes its pages entries of the page's history: the back and forward
buttons go through the stack, the address after the # is the stack's location, and a
link with a route opens the page it names. See
Mobile and navigation.
A browser gives Skia no fonts at all. The text is drawn with the one font given to
BrowserApp, and a character it lacks — Hebrew, Arabic, CJK, emoji in a Latin font — is
drawn as an empty box unless a fallback has it:
- Put the font file in
wwwroot/fonts/(with its license — the Noto fonts are under the SIL Open Font License,OFL.txt). - Add it with
FontFallbacks.Add("/fonts/…")beforeBrowserApp.RunAsync.
Fallbacks are searched in the order added. CJK fonts are large — several megabytes — and every visitor downloads them on the first visit: a subset with the characters the application needs is lighter.
-
Dialogs are async-only: there is no nested loop, so
ShowDialogAsync,MessageBox.ShowAsync,InputBox.ShowAsync. - No system drag and drop — drag and drop inside the application works.
-
No windows: one form fills the canvas;
Position,TopMostand the size limits are accepted and do nothing. -
File pickers are the browser's own, through
IFilePicker. A picked file is read from the copy the page was given;FileDialog.PickSaveFileAsyncwrites through the browser's save dialog (Chromium) or as a download (elsewhere) — see Picked files. - Trimmed publishing (
PublishTrimmed) is supported: the framework is annotated for the trimmer.
dotnet publish -c Release and serve publish/wwwroot. The showcase's workflow
(yd359team.github.io/.github/workflows/showcase.yml) builds examples/ZF Wasm from the
framework's master by default; run it by hand with another ref to see a branch before
it is merged.
ZeppelinForms — fully free, for everyone. This wiki is generated from
docs/wiki:
edit it there, not here.
Start
Building the UI
Looks
Behaviour
Tooling