Skip to content

Commit

Permalink
Add F# support
Browse files Browse the repository at this point in the history
Fixes #8
  • Loading branch information
Kir-Antipov committed Nov 29, 2024
1 parent 3a9c2dc commit c27637e
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 0 deletions.
165 changes: 165 additions & 0 deletions src/HotAvalonia.Extensions/AvaloniaHotReloadExtensions.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// <auto-generated>
// This file has been automatically added to your project by the "HotAvalonia.Extensions" NuGet package
// (https://nuget.org/packages/HotAvalonia.Extensions).
//
// Please see https://github.com/Kir-Antipov/HotAvalonia for more information.
// </auto-generated>

//#region License
// MIT License
//
// Copyright (c) 2023-2024 Kir_Antipov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//#endregion

#nowarn

namespace HotAvalonia

open System
open System.Diagnostics
open System.Diagnostics.CodeAnalysis
open System.IO
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
open Avalonia

/// <summary>
/// Indicates that the decorated method should be called whenever the associated Avalonia control is hot reloaded.
/// </summary>
/// <remarks>
/// This attribute is intended to be applied to parameterless instance methods of Avalonia controls.
/// When the control is hot reloaded, the method marked with this attribute is executed.
/// This can be used to refresh or update the control's state in response to hot reload events.
///
/// <br/><br/>
///
/// The method must meet the following requirements:
/// <list type="bullet">
/// <item>It must be an instance method (i.e., not static).</item>
/// <item>It must not have any parameters.</item>
/// </list>
///
/// Example usage:
/// <code>
/// [<AvaloniaHotReload>]
/// let private initialize () =
/// // Code to initialize or refresh
/// // the control during hot reload.
/// ()
/// </code>
/// </remarks>
[<ExcludeFromCodeCoverage>]
[<Conditional("ENABLE_XAML_HOT_RELOAD")>]
[<AttributeUsage(AttributeTargets.Method)>]
type internal AvaloniaHotReloadAttribute() =
inherit Attribute()

/// <summary>
/// Provides extension methods for enabling and disabling hot reload functionality for Avalonia applications.
/// </summary>
[<ExcludeFromCodeCoverage>]
[<Extension>]
type internal AvaloniaHotReloadExtensions =
#if ENABLE_XAML_HOT_RELOAD && !DISABLE_XAML_HOT_RELOAD
/// <summary>
/// A mapping between Avalonia <see cref="Application"/> instances and their associated hot reload context.
/// </summary>
static let s_apps = ConditionalWeakTable<Application, IHotReloadContext>()

/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="appFilePath">The file path of the application's main source file. Optional if the method called within the file of interest.</param>
[<DebuggerStepThrough>]
[<Extension>]
static member EnableHotReload(app: Application, [<CallerFilePath; Optional; DefaultParameterValue("")>] appFilePath: string) =
match s_apps.TryGetValue(app) with
| true, context -> context.EnableHotReload()
| _ ->
if not (String.IsNullOrEmpty(appFilePath) || File.Exists(appFilePath)) then
raise (FileNotFoundException("The corresponding XAML file could not be found.", appFilePath))

if not (String.IsNullOrEmpty(appFilePath)) then
AvaloniaProjectLocator.AddHint(app.GetType(), appFilePath)

let appDomainContext = AvaloniaHotReloadContext.FromAppDomain()
let assetContext = AvaloniaHotReloadContext.ForAssets()
let context = HotReloadContext.Combine(appDomainContext, assetContext)
s_apps.Add(app, context)

context.EnableHotReload()

/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="projectPathResolver">The callback function capable of resolving a project path for a given assembly.</param>
[<DebuggerStepThrough>]
[<Extension>]
static member EnableHotReload(app: Application, projectPathResolver: Assembly -> string) =
AvaloniaProjectLocator.AddHint(projectPathResolver)
app.EnableHotReload(String.Empty)

/// <summary>
/// Disables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be disabled.</param>
[<DebuggerStepThrough>]
[<Extension>]
static member DisableHotReload(app: Application) =
match s_apps.TryGetValue(app) with
| true, context -> context.DisableHotReload()
| _ -> ()
#else
/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="appFilePath">The file path of the application's main source file. Optional if the method called within the file of interest.</param>
[<Conditional("DEBUG")>]
[<DebuggerStepThrough>]
[<Extension>]
static member EnableHotReload(app: Application, [<Optional; DefaultParameterValue("")>] appFilePath: string) =
()

/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="projectPathResolver">The callback function capable of resolving a project path for a given assembly.</param>
[<Conditional("DEBUG")>]
[<DebuggerStepThrough>]
[<Extension>]
static member EnableHotReload(app: Application, projectPathResolver: Assembly -> string) =
()

/// <summary>
/// Disables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be disabled.</param>
[<Conditional("DEBUG")>]
[<DebuggerStepThrough>]
[<Extension>]
static member DisableHotReload(app: Application) =
()
#endif
1 change: 1 addition & 0 deletions src/HotAvalonia.Extensions/HotAvalonia.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ItemGroup>
<None Include="HotAvalonia.Extensions.props" PackagePath="build" Pack="true" />
<None Include="AvaloniaHotReloadExtensions.cs" PackagePath="contentFiles/cs/any/" Pack="true" BuildAction="Compile" />
<None Include="AvaloniaHotReloadExtensions.fs" PackagePath="contentFiles/fs/any/" Pack="true" BuildAction="Compile" />
<None Include="AvaloniaHotReloadExtensions.vb" PackagePath="contentFiles/vb/any/" Pack="true" BuildAction="Compile" />
</ItemGroup>

Expand Down

0 comments on commit c27637e

Please sign in to comment.