-
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7a0f14a
commit b60789f
Showing
45 changed files
with
2,493 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# Getting Started | ||
|
||
<div align="center"> | ||
|
||
<figure><img src=".gitbook/assets/Screenshot 2023-02-17 at 21.16.10.png" alt=""><figcaption><p>Screenshot of the example app. (Simple counter app with a text block and two buttons)</p></figcaption></figure> | ||
|
||
</div> | ||
|
||
## Step 1: Empty Console App | ||
|
||
Create a new F# console application targeting .net 6 or higher.  | ||
|
||
## Step 2: Packages | ||
|
||
 Reference the following packages [Avalonia.Desktop](https://www.nuget.org/packages/Avalonia.Desktop/11.0.0-preview5), [Avalonia.Themes.Fluent](https://www.nuget.org/packages/Avalonia.Themes.Fluent/11.0.0-preview5) and [Avalonia.FuncUI](https://www.nuget.org/packages/Avalonia.FuncUI/0.6.0-preview7). | ||
|
||
{% tabs %} | ||
{% tab title="dotnet CLI" %} | ||
Run the following commands in your project directory: | ||
|
||
```bash | ||
dotnet add package Avalonia.Desktop --version 11.0.0 | ||
dotnet add package Avalonia.Themes.Fluent --version 11.0.0 | ||
dotnet add package Avalonia.FuncUI --version 1.0.0 | ||
``` | ||
{% endtab %} | ||
|
||
{% tab title="edit Project file" %} | ||
Paste the following package references to your fsproject file: | ||
|
||
```html | ||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0" /> | ||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0" /> | ||
<PackageReference Include="Avalonia.FuncUI" Version="1.0.0" /> | ||
``` | ||
{% endtab %} | ||
{% endtabs %} | ||
|
||
## Step 3: Add code to `Program.fs` | ||
|
||
```fsharp | ||
namespace CounterApp | ||
open Avalonia | ||
open Avalonia.Controls.ApplicationLifetimes | ||
open Avalonia.Themes.Fluent | ||
open Avalonia.FuncUI.Hosts | ||
open Avalonia.Controls | ||
open Avalonia.FuncUI | ||
open Avalonia.FuncUI.DSL | ||
open Avalonia.Layout | ||
module Main = | ||
let view () = | ||
Component(fun ctx -> | ||
let state = ctx.useState 0 | ||
DockPanel.create [ | ||
DockPanel.children [ | ||
Button.create [ | ||
Button.dock Dock.Bottom | ||
Button.onClick (fun _ -> state.Set(state.Current - 1)) | ||
Button.content "-" | ||
Button.horizontalAlignment HorizontalAlignment.Stretch | ||
Button.horizontalContentAlignment HorizontalAlignment.Center | ||
] | ||
Button.create [ | ||
Button.dock Dock.Bottom | ||
Button.onClick (fun _ -> state.Set(state.Current + 1)) | ||
Button.content "+" | ||
Button.horizontalAlignment HorizontalAlignment.Stretch | ||
Button.horizontalContentAlignment HorizontalAlignment.Center | ||
] | ||
TextBlock.create [ | ||
TextBlock.dock Dock.Top | ||
TextBlock.fontSize 48.0 | ||
TextBlock.verticalAlignment VerticalAlignment.Center | ||
TextBlock.horizontalAlignment HorizontalAlignment.Center | ||
TextBlock.text (string state.Current) | ||
] | ||
] | ||
] | ||
) | ||
type MainWindow() = | ||
inherit HostWindow() | ||
do | ||
base.Title <- "Counter Example" | ||
base.Content <- Main.view () | ||
type App() = | ||
inherit Application() | ||
override this.Initialize() = | ||
this.Styles.Add (FluentTheme()) | ||
this.RequestedThemeVariant <- Styling.ThemeVariant.Dark | ||
override this.OnFrameworkInitializationCompleted() = | ||
match this.ApplicationLifetime with | ||
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime -> | ||
desktopLifetime.MainWindow <- MainWindow() | ||
| _ -> () | ||
module Program = | ||
[<EntryPoint>] | ||
let main(args: string[]) = | ||
AppBuilder | ||
.Configure<App>() | ||
.UsePlatformDetect() | ||
.UseSkia() | ||
.StartWithClassicDesktopLifetime(args) | ||
``` | ||
|
||
## Step 4: build and run 🎉 | ||
|
||
```bash | ||
dotnet run | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Table of contents | ||
|
||
* [Getting Started](README.md) | ||
* [View Basics](view-basics/README.md) | ||
* [Creating views](view-basics/creating-views.md) | ||
* [Lifetime](view-basics/lifetime.md) | ||
* [Attributes](view-basics/attributes.md) | ||
* [How to create bindings](view-basics/how-to-create-bindings.md) | ||
* [Components](components/README.md) | ||
* [Component basics](components/component-basics.md) | ||
* [Component lifetime](components/component-lifetime.md) | ||
* [Hooks](components/hooks.md) | ||
* [Common Questions](common-questions.md) | ||
* [Controls](controls/README.md) | ||
* [Button](controls/button.md) | ||
* [Border](controls/border.md) | ||
* [Calendar](controls/calendar.md) | ||
* [CalendarDatePicker](controls/calendardatepicker.md) | ||
* [CheckBox](controls/checkbox.md) | ||
* [DatePicker](controls/datepicker.md) | ||
* [DockPanel](controls/dockpanel.md) | ||
* [Expander](controls/expander.md) | ||
* [ListBox](controls/listbox.md) | ||
* [Menu](controls/menu.md) | ||
* [NativeMenu](controls/nativemenu.md) | ||
* [NumericUpDown](controls/numericupdown.md) | ||
* [ProgressBar](controls/progressbar.md) | ||
* [RadioButton](controls/radiobutton.md) | ||
* [RepeatButton](controls/repeatbutton.md) | ||
* [Slider](controls/slider.md) | ||
* [StackPanel](controls/stackpanel.md) | ||
* [Tabs](controls/tabs.md) | ||
* [TextBlock](controls/textblock.md) | ||
* [TextBox](controls/textbox.md) | ||
* [TimePicker](controls/timepicker.md) | ||
* [ToggleButton](controls/togglebutton.md) | ||
* [ToggleSwitch](controls/toggleswitch.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Common Questions | ||
|
||
## How do I obtain the reference of a Control? | ||
|
||
There are 2 recommended ways of obtaining the reference of an underlaying control. \ | ||
|
||
|
||
### 1. Execute code on control creation | ||
|
||
Use the Control.init attribute to run code on control creation. | ||
|
||
```fsharp | ||
ListBox.create [ | ||
ListBox.init (fun listBox -> | ||
listBox.Items <- [ 1 .. 3 ] | ||
) | ||
] | ||
``` | ||
|
||
### 2. Obtain a view reference via an outlet | ||
|
||
Calls the `listBox.Set` function when the control is created. | ||
|
||
```fsharp | ||
Component(fun ctx -> | ||
let listBox = ctx.useState<ListBox>(null) | ||
ctx.useEffect ( | ||
handler = (fun _ -> | ||
listBox.Current.Items <- [ 1 .. 3 ] | ||
), | ||
triggers = [ EffectTrigger.AfterInit ] | ||
) | ||
View.createWithOutlet listBox.Set ListBox.create [ ] | ||
) | ||
``` | ||
|
||
## How do I obtain the reference of a Component? | ||
|
||
The Component reference can be accessed via `ctx.control`. | ||
|
||
```fsharp | ||
Component(fun ctx -> | ||
ctx.useEffect ( | ||
handler = (fun _ -> | ||
ctx.control.Tag <- 0 | ||
), | ||
triggers = [ EffectTrigger.AfterInit ] | ||
) | ||
Button.create [] | ||
) | ||
``` | ||
|
||
## How to set attributes on Component level? | ||
|
||
```fsharp | ||
Component(fun ctx -> | ||
ctx.attrs [ | ||
Component.background "transparent" | ||
Component.borderThickness 1 | ||
] | ||
Button.create [] | ||
) | ||
``` | ||
|
||
|
||
|
||
## How do I restrict what a user can input in a TextBox / AutoCompleteBox / InputElement ? | ||
|
||
This is possible by intercepting the [TextInputEvent](https://reference.avaloniaui.net/api/Avalonia.Input/InputElement/FEA4DB21) and modifying its event args. It's important to attache the handler to the tunnelled event. More details about event routing can be found [here](https://docs.avaloniaui.net/docs/input/routed-events#routing-strategies). \ | ||
\ | ||
In the example below whatever a user types in a TextBox will end up as uppercase text.  | ||
|
||
```fsharp | ||
TextBox.create [ | ||
TextBox.init (fun control -> | ||
control.AddHandler( | ||
TextBox.TextInputEvent, | ||
(fun sender args -> | ||
args.Text <- args.Text.ToUpper() | ||
), | ||
RoutingStrategies.Tunnel | ||
) | ||
) | ||
] | ||
``` | ||
|
||
Here another example that prevents users from entering anything but numbers. | ||
|
||
```fsharp | ||
TextBox.create [ | ||
TextBox.init (fun control -> | ||
control.AddHandler( | ||
TextBox.TextInputEvent, | ||
(fun sender args -> args.Text <- String.filter Char.IsNumber args.Text), | ||
RoutingStrategies.Tunnel | ||
) | ||
) | ||
] | ||
``` | ||
|
||
## How to render a Control to an Image? | ||
|
||
```fsharp | ||
let renderToFile (target : Control, path : string) = | ||
let pixelSize = PixelSize(int target.Bounds.Width, int target.Bounds.Height) | ||
let size = Size(target.Bounds.Width, target.Bounds.Height) | ||
use bitmap = new RenderTargetBitmap(pixelSize, new Vector(96.0, 96.0)) | ||
target.Measure(size) | ||
target.Arrange(Rect(size)) | ||
bitmap.Render(target) | ||
bitmap.Save(path) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Components | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Component basics | ||
|
||
FuncUI offers a Component inspired by ReactJS. Components allow you to organize views into reusable pieces.  | ||
|
||
There are two ways of creating a component.  | ||
|
||
## Component (fun ctx -> ...) | ||
|
||
Creating a component using the regular constructor of the `Component` class. `Component` inherits from `Border` and therefor can be used like any other Avalonia control. | ||
|
||
```fsharp | ||
// create a Component that can be directly used in a Avalonia app | ||
let component: Component = Component (fun ctx -> | ||
TextBlock.create [ | ||
TextBlock.text "Hello World!" | ||
] | ||
) | ||
// use component as main view of an app | ||
type MainWindow() as this = | ||
inherit HostWindow() | ||
do | ||
this.Content <- component | ||
// embedd component in avalonia app | ||
let control: ContentControl = .. | ||
control.Content <- component | ||
// Creating a component using the View DSL. | ||
// The resulting IView can be used inside other components and with the View DSL. | ||
``` | ||
|
||
## Component.create ("key", fun ctx -> ...) | ||
|
||
Declaratlvely describes a component. Can be embedded in other views as this returns an `IView` | ||
|
||
```fsharp | ||
let greetingView (): IView = | ||
Component.create ("greetingView", fun ctx -> | ||
TextBlock.create [ | ||
TextBlock.text "Hello World!" | ||
] | ||
) | ||
let view (): IView = | ||
Component.create ("mainView", fun ctx -> | ||
DockPanel.create [ | ||
DockPanel.children [ | ||
// use other component | ||
greetingView () | ||
] | ||
] | ||
) | ||
``` |
Oops, something went wrong.