Skip to content

Commit

Permalink
Merge pull request #396 from orangebobolink/main
Browse files Browse the repository at this point in the history
Add save as and open example for SukiUi.Dock to SukiUi.Demo
  • Loading branch information
kikipoulet authored Feb 5, 2025
2 parents 0f3f126 + 9748279 commit cf8ebf1
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 54 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageVersion Include="Dock.Model" Version="11.2.0" />
<PackageVersion Include="Dock.Model.Mvvm" Version="11.2.0" />
<PackageVersion Include="Dock.Serializer" Version="11.2.0" />
<PackageVersion Include="Material.Icons.Avalonia" Version="2.1.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="ShowMeTheXaml.Avalonia" Version="1.5.1" />
Expand Down
45 changes: 45 additions & 0 deletions SukiUI.Demo/Common/StorageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.VisualTree;

namespace SukiUI.Demo.Common
{
internal static class StorageService
{
public static FilePickerFileType All { get; } = new("All")
{
Patterns = ["*.*"],
MimeTypes = ["*/*"]
};

public static FilePickerFileType Json { get; } = new("Json")
{
Patterns = ["*.json"],
AppleUniformTypeIdentifiers = ["public.json"],
MimeTypes = ["application/json"]
};

public static IStorageProvider? GetStorageProvider()
{
if (Avalonia.Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } window })
{
return window.StorageProvider;
}

if (Avalonia.Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime
{
MainView: { } mainView
})
{
var visualRoot = mainView.GetVisualRoot();
if (visualRoot is TopLevel topLevel)
{
return topLevel.StorageProvider;
}
}

return null;
}
}
}
18 changes: 7 additions & 11 deletions SukiUI.Demo/Features/ControlsLibrary/DockControls/DockFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

namespace SukiUI.Demo.Features.ControlsLibrary.DockControls
{
public class DockFactory(object context) : Factory
public class DockFactory(DockMvvmViewModel context) : Factory
{
private readonly object _context = context;
private readonly DockMvvmViewModel _context = context;
private IRootDock? _rootDock;
private IDocumentDock? _documentDock;

public override IRootDock CreateLayout()
{
Expand All @@ -37,7 +36,7 @@ public override IRootDock CreateLayout()
{
ActiveDockable = solutionExploreTool,
VisibleDockables = CreateList<IDockable>(solutionExploreTool),
Alignment = Alignment.Left
Alignment = Alignment.Left,
}
)
};
Expand All @@ -64,7 +63,7 @@ public override IRootDock CreateLayout()
{
ActiveDockable = propertiesTool,
VisibleDockables = CreateList<IDockable>(propertiesTool),
Alignment = Alignment.Top,
Alignment = Alignment.Right,
}
)
};
Expand All @@ -80,7 +79,7 @@ public override IRootDock CreateLayout()
{
ActiveDockable = outputTool,
VisibleDockables = CreateList<IDockable>(errorListTool, outputTool),
Alignment = Alignment.Top,
Alignment = Alignment.Bottom,
}
)
};
Expand Down Expand Up @@ -123,8 +122,7 @@ public override IRootDock CreateLayout()
rootDock.ActiveDockable = homeView;
rootDock.DefaultDockable = homeView;
rootDock.VisibleDockables = CreateList<IDockable>(homeView);

_documentDock = documentDock;

_rootDock = rootDock;

return rootDock;
Expand All @@ -146,14 +144,12 @@ public override void InitLayout(IDockable layout)
{
ContextLocator = new Dictionary<string, Func<object?>>
{
["Dashboard"] = () => layout,
["Home"] = () => _context
};

DockableLocator = new Dictionary<string, Func<IDockable?>>()
{
["Root"] = () => _rootDock,
["Documents"] = () => _documentDock
["Home"] = () => _rootDock,
};

HostWindowLocator = new Dictionary<string, Func<IHostWindow?>>
Expand Down
47 changes: 43 additions & 4 deletions SukiUI.Demo/Features/ControlsLibrary/DockMvvmView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,50 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controlsLibrary="clr-namespace:SukiUI.Demo.Features.ControlsLibrary"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="controlsLibrary:DockMvvmViewModel"
x:Class="SukiUI.Demo.Features.ControlsLibrary.DockMvvmView">
<DockControl
x:Name="DockControl"
Layout="{Binding Layout}"
Margin="4"/>
<Grid
Margin="15">
<Grid
ZIndex="1"
VerticalAlignment="Top"
HorizontalAlignment="Left">
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Spacing="5">
<Button
ToolTip.Tip="Open Layout"
Classes="Icon"
Width="30"
Height="30"
x:Name="FileOpenLayout"
Command="{Binding OpenLayoutCommand}">
<avalonia:MaterialIcon
Width="20"
Height="20"
Kind="File"/>
</Button>
<Button
ToolTip.Tip="Save as"
Classes="Icon"
Width="30"
Height="30"
x:Name="FileSaveLayout"
Command="{Binding SaveLayoutCommand}">
<avalonia:MaterialIcon
Width="20"
Height="20"
Kind="ContentSave"/>
</Button>
</StackPanel>
</Grid>
<DockControl
x:Name="DockControl"
Layout="{Binding Layout}"
Margin="4"/>
</Grid>
</UserControl>
128 changes: 90 additions & 38 deletions SukiUI.Demo/Features/ControlsLibrary/DockMvvmViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,119 @@
using System.Diagnostics;
using System.Windows.Input;
using Avalonia.Collections;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Dock.Model.Controls;
using Dock.Model.Core;
using Dock.Serializer;
using Material.Icons;
using SukiUI.Demo.Common;
using SukiUI.Demo.Features.ControlsLibrary.DockControls;

namespace SukiUI.Demo.Features.ControlsLibrary
{
public partial class DockMvvmViewModel : DemoPageBase
{
private readonly IFactory? _factory;
private readonly IDockSerializer _serializer;
private readonly IFactory _factory;
[ObservableProperty] private IRootDock? _layout;

public ICommand NewLayout { get; }

public DockMvvmViewModel() : base("DockMvvm", MaterialIconKind.DockTop)
{
_factory = new DockFactory(new object());

_serializer = new DockSerializer(typeof(AvaloniaList<>));
_factory = new DockFactory(this);
DebugFactoryEvents(_factory);

Layout = _factory?.CreateLayout();
Layout = _factory.CreateLayout();

if (Layout is null)
{
return;
}

_factory.InitLayout(Layout);

if (Layout is { } root)
{
root.Navigate.Execute("Home");
}
}

[RelayCommand]
private async Task SaveLayout()
{
var storageProvider = StorageService.GetStorageProvider();

if (Layout is { })
var file = await storageProvider!.SaveFilePickerAsync(new FilePickerSaveOptions
{
_factory?.InitLayout(Layout);
Title = "Save layout",
FileTypeChoices = GetOpenLayoutFileTypes(),
SuggestedFileName = "layout",
DefaultExtension = "json",
ShowOverwritePrompt = true
});

if (Layout is { } root)
if (file is not null)
{
try
{
await using var stream = await file.OpenWriteAsync();

if (Layout is not null)
{
_serializer.Save(stream, Layout);
}
}
catch (Exception e)
{
root.Navigate.Execute("Home");
Console.WriteLine(e);
}
}
}

[RelayCommand]
private async Task OpenLayout()
{
var storageProvider = StorageService.GetStorageProvider();

var result = await storageProvider!.OpenFilePickerAsync(
new FilePickerOpenOptions
{
Title = "Open layout",
FileTypeFilter = GetOpenLayoutFileTypes(),
AllowMultiple = false
});

var file = result.FirstOrDefault();

if (file is not null)
{
try
{
await using var stream = await file.OpenReadAsync();
using var reader = new StreamReader(stream);

var layout = _serializer.Load<IRootDock?>(stream);

NewLayout = new RelayCommand(ResetLayout);
if (layout is not null)
{
_factory!.InitLayout(layout);
Layout = layout;
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}

private static List<FilePickerFileType> GetOpenLayoutFileTypes()
=>
[
StorageService.Json,
StorageService.All
];

private static void DebugFactoryEvents(IFactory factory)
{
Expand Down Expand Up @@ -136,31 +214,5 @@ private static void DebugFactoryEvents(IFactory factory)
$"[WindowMoveDragEnd] Title='{args.Window?.Title}', X='{args.Window?.X}', Y='{args.Window?.Y}");
};
}

public void CloseLayout()
{
if (Layout is IDock dock && dock.Close.CanExecute(null))
{
dock.Close.Execute(null);
}
}

public void ResetLayout()
{
if (Layout is not null && Layout.Close.CanExecute(null))
{
Layout.Close.Execute(null);
}

var layout = _factory?.CreateLayout();

if (layout is null)
{
return;
}

Layout = layout;
_factory?.InitLayout(layout);
}
}
}
5 changes: 4 additions & 1 deletion SukiUI.Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ public static AppBuilder BuildAvaloniaApp()
.UseXamlDisplay();

if (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
app.UseManagedSystemDialogs();
{
//app.UseManagedSystemDialogs();
}

return app;
}
}
1 change: 1 addition & 0 deletions SukiUI.Demo/SukiUI.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<PackageReference Include="Dock.Model" />
<PackageReference Include="Dock.Model.Avalonia" />
<PackageReference Include="Dock.Model.Mvvm" />
<PackageReference Include="Dock.Serializer" />
<PackageReference Include="Material.Icons.Avalonia" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="ShowMeTheXaml.Avalonia" />
Expand Down

0 comments on commit cf8ebf1

Please sign in to comment.