Initial import
This commit is contained in:
Коммит
ce89cde134
|
@ -0,0 +1,159 @@
|
|||
# editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings:
|
||||
# A newline ending every file
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
# New line preferences
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
|
||||
# avoid this. unless absolutely necessary
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
|
||||
# prefer var
|
||||
csharp_style_var_for_built_in_types = true
|
||||
csharp_style_var_when_type_is_apparent = true
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
|
||||
# use language keywords instead of BCL types
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# name all constant fields using PascalCase
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
|
||||
# static fields should have s_ prefix
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
|
||||
|
||||
dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||
|
||||
dotnet_naming_style.static_prefix_style.required_prefix = s_
|
||||
dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||
|
||||
# internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# use accessibility modifiers
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
|
||||
# Code style defaults
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = false
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = false:none
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_operators = false:none
|
||||
csharp_style_expression_bodied_properties = true:none
|
||||
csharp_style_expression_bodied_indexers = true:none
|
||||
csharp_style_expression_bodied_accessors = true:none
|
||||
|
||||
# Pattern matching
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
|
||||
# Null checking preferences
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = do_not_ignore
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Xaml files
|
||||
[*.xaml]
|
||||
indent_size = 4
|
||||
|
||||
# Xml project files
|
||||
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
|
||||
indent_size = 2
|
||||
|
||||
# Xml build files
|
||||
[*.builds]
|
||||
indent_size = 2
|
||||
|
||||
# Xml files
|
||||
[*.{xml,stylecop,resx,ruleset}]
|
||||
indent_size = 2
|
||||
|
||||
# Xml config files
|
||||
[*.{props,targets,config,nuspec}]
|
||||
indent_size = 2
|
||||
|
||||
# Shell scripts
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
[*.{cmd, bat}]
|
||||
end_of_line = crlf
|
|
@ -0,0 +1,17 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
|
@ -0,0 +1,288 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
|
@ -0,0 +1 @@
|
|||
Avalonia.ThemeManager.sln
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Wiesław Šoltés
|
||||
|
||||
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.
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="avalonia-ci" value="https://www.myget.org/F/avalonia-ci/api/v3/index.json" />
|
||||
<add key="avalonia-prs" value="https://www.myget.org/F/avalonia-prs/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
|
@ -0,0 +1,119 @@
|
|||
# Avalonia Theme Manager
|
||||
|
||||
## About
|
||||
|
||||
Theme manager for [Avalonia](https://github.com/AvaloniaUI/Avalonia) applications.
|
||||
|
||||
## Usage
|
||||
|
||||
Theme manager searches user provided themes directory for `*.xaml` theme files otherwise built-in `Light` and `Dark` theme are used.
|
||||
|
||||
The `ThemeSelector` static `Instance` property neeeds to be initalized before using `ThemeSelector` class.
|
||||
|
||||
The `ThemeSelector` uses `Styles[0]` property of `Windows` to insert selected theme `Style`.
|
||||
|
||||
`Program.cs`
|
||||
|
||||
```C#
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.ThemeManager;
|
||||
|
||||
namespace AvaloniaApp
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
BuildAvaloniaApp().Start(AppMain, args);
|
||||
}
|
||||
|
||||
static void AppMain(Application app, string[] args)
|
||||
{
|
||||
ThemeSelector.Instance = new ThemeSelector("Themes");
|
||||
ThemeSelector.Instance.LoadSelectedTheme("AvaloniaApp.theme");
|
||||
|
||||
app.Run(new MainWindow());
|
||||
|
||||
ThemeSelector.Instance.SaveSelectedTheme("AvaloniaApp.theme");
|
||||
}
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`MainWindow.xaml`
|
||||
|
||||
```XAML
|
||||
<Window x:Class="AvaloniaApp.MainWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:Themes="clr-namespace:Avalonia.ThemeManager;assembly=Avalonia.ThemeManager"
|
||||
Title="AvaloniaApp" Width="800" Height="600">
|
||||
<Window.Resources>
|
||||
<Themes:ObjectEqualityMultiConverter x:Key="ObjectEqualityMultiConverter"/>
|
||||
</Window.Resources>
|
||||
<Menu>
|
||||
<MenuItem Header="_View">
|
||||
<MenuItem Header="_Theme" DataContext="{x:Static Themes:ThemeSelector.Instance}" Items="{Binding Themes}">
|
||||
<MenuItem.Styles>
|
||||
<Style Selector="MenuItem">
|
||||
<Setter Property="Header" Value="{Binding Name}"/>
|
||||
<Setter Property="Command" Value="{Binding Selector.ApplyTheme}"/>
|
||||
<Setter Property="CommandParameter" Value="{Binding}"/>
|
||||
<Setter Property="Icon">
|
||||
<Template>
|
||||
<CheckBox>
|
||||
<CheckBox.IsChecked>
|
||||
<MultiBinding Mode="OneWay" Converter="{StaticResource ObjectEqualityMultiConverter}">
|
||||
<Binding Path="DataContext" RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="Selector.SelectedTheme"/>
|
||||
</MultiBinding>
|
||||
</CheckBox.IsChecked>
|
||||
</CheckBox>
|
||||
</Template>
|
||||
</Setter>
|
||||
</Style>
|
||||
</MenuItem.Styles>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Window>
|
||||
```
|
||||
|
||||
`MainWindow.xaml.xs`
|
||||
|
||||
```C#
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ThemeManager;
|
||||
|
||||
namespace AvaloniaApp.Views
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.AttachDevTools();
|
||||
ThemeSelector.Instance.EnableThemes(this);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `ThemeSelector.Instance.EnableThemes(this);` can be used in multiple windows.
|
||||
|
||||
## License
|
||||
|
||||
Avalonia.ThemeManager is licensed under the [MIT license](LICENSE.TXT).
|
|
@ -0,0 +1,69 @@
|
|||
[CmdletBinding()]
|
||||
Param(
|
||||
#[switch]$CustomParam,
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||
[string[]]$BuildArguments
|
||||
)
|
||||
|
||||
Write-Output "Windows PowerShell $($Host.Version)"
|
||||
|
||||
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 }
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
$BuildProjectFile = "$PSScriptRoot\build\build\_build.csproj"
|
||||
$TempDirectory = "$PSScriptRoot\\.tmp"
|
||||
|
||||
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
|
||||
$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1"
|
||||
$DotNetChannel = "Current"
|
||||
|
||||
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
|
||||
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
|
||||
$env:NUGET_XMLDOC_MODE = "skip"
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function ExecSafe([scriptblock] $cmd) {
|
||||
& $cmd
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
}
|
||||
|
||||
# If global.json exists, load expected version
|
||||
if (Test-Path $DotNetGlobalFile) {
|
||||
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
|
||||
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
|
||||
$DotNetVersion = $DotNetGlobal.sdk.version
|
||||
}
|
||||
}
|
||||
|
||||
# If dotnet is installed locally, and expected version is not set or installation matches the expected version
|
||||
if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and `
|
||||
(!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) {
|
||||
$env:DOTNET_EXE = (Get-Command "dotnet").Path
|
||||
}
|
||||
else {
|
||||
$DotNetDirectory = "$TempDirectory\dotnet-win"
|
||||
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
|
||||
|
||||
# Download install script
|
||||
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
|
||||
md -force $TempDirectory > $null
|
||||
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
|
||||
|
||||
# Install by channel or version
|
||||
if (!(Test-Path variable:DotNetVersion)) {
|
||||
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
|
||||
} else {
|
||||
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
|
||||
|
||||
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments }
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo $(bash --version 2>&1 | head -n 1)
|
||||
|
||||
#CUSTOMPARAM=0
|
||||
BUILD_ARGUMENTS=()
|
||||
for i in "$@"; do
|
||||
case $(echo $1 | awk '{print tolower($0)}') in
|
||||
# -custom-param) CUSTOMPARAM=1;;
|
||||
*) BUILD_ARGUMENTS+=("$1") ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
set -eo pipefail
|
||||
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
BUILD_PROJECT_FILE="$SCRIPT_DIR/build/build/_build.csproj"
|
||||
TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
|
||||
|
||||
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
|
||||
DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh"
|
||||
DOTNET_CHANNEL="Current"
|
||||
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
export NUGET_XMLDOC_MODE="skip"
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function FirstJsonValue {
|
||||
perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2}
|
||||
}
|
||||
|
||||
# If global.json exists, load expected version
|
||||
if [ -f "$DOTNET_GLOBAL_FILE" ]; then
|
||||
DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE"))
|
||||
if [ "$DOTNET_VERSION" == "" ]; then
|
||||
unset DOTNET_VERSION
|
||||
fi
|
||||
fi
|
||||
|
||||
# If dotnet is installed locally, and expected version is not set or installation matches the expected version
|
||||
if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then
|
||||
export DOTNET_EXE="$(command -v dotnet)"
|
||||
else
|
||||
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
|
||||
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
|
||||
|
||||
# Download install script
|
||||
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
|
||||
mkdir -p "$TEMP_DIRECTORY"
|
||||
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
|
||||
chmod +x "$DOTNET_INSTALL_FILE"
|
||||
|
||||
# Install by channel or version
|
||||
if [ -z ${DOTNET_VERSION+x} ]; then
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
|
||||
else
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
|
||||
|
||||
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.8.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog" Version="2.5.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.1" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.8.0.2</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>Wiesław Šoltés</Authors>
|
||||
<Company>Wiesław Šoltés</Company>
|
||||
<Description>A multi-platform data driven 2D diagram editor.</Description>
|
||||
<Copyright>Copyright © Wiesław Šoltés 2019</Copyright>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/wieslawsoltes/Core2D</PackageProjectUrl>
|
||||
<PackageTags>2d;editor;data;diagram;graphics;geometry;data;shapes;wysiwyg-editor</PackageTags>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
|
||||
<PropertyGroup>
|
||||
<CoreRT>False</CoreRT>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-x64'">
|
||||
<CoreRT>True</CoreRT>
|
||||
<DefineConstants>$(DefineConstants);_CORERT;_CORERT_WIN_X64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
|
||||
<CoreRT>True</CoreRT>
|
||||
<DefineConstants>$(DefineConstants);_CORERT;_CORERT_LINUX_X64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64'">
|
||||
<CoreRT>True</CoreRT>
|
||||
<DefineConstants>$(DefineConstants);_CORERT;_CORERT_OSX_X64</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net461' and '$(OS)' == 'Unix'">
|
||||
<FrameworkPathOverride>/usr/lib/mono/4.6.1-api</FrameworkPathOverride>
|
||||
<FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api</FrameworkPathOverride>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
|
||||
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.3" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);REACTIVEUI</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="reactiveui" Version="9.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive" Version="4.0.0" />
|
||||
<PackageReference Include="System.Reactive.Core" Version="4.0.0" />
|
||||
<PackageReference Include="System.Reactive.Interfaces" Version="4.0.0" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="4.0.0" />
|
||||
<PackageReference Include="System.Reactive.PlatformServices" Version="4.0.0" />
|
||||
<PackageReference Condition="$(TargetFramework.StartsWith('net4'))" Include="System.Reactive.Windows.Threading" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,126 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nuke.Common;
|
||||
using Nuke.Common.Git;
|
||||
using Nuke.Common.ProjectModel;
|
||||
using Nuke.Common.Tools.DotNet;
|
||||
using static Nuke.Common.EnvironmentInfo;
|
||||
using static Nuke.Common.IO.FileSystemTasks;
|
||||
using static Nuke.Common.IO.PathConstruction;
|
||||
using static Nuke.Common.Tools.DotNet.DotNetTasks;
|
||||
|
||||
class Build : NukeBuild
|
||||
{
|
||||
public static int Main() => Execute<Build>(x => x.Compile);
|
||||
|
||||
[Solution]
|
||||
readonly Solution Solution;
|
||||
|
||||
[GitRepository]
|
||||
readonly GitRepository GitRepository;
|
||||
|
||||
[Parameter("configuration")]
|
||||
public string Configuration { get; set; }
|
||||
|
||||
[Parameter("version-suffix")]
|
||||
public string VersionSuffix { get; set; }
|
||||
|
||||
[Parameter("publish-framework")]
|
||||
public string PublishFramework { get; set; }
|
||||
|
||||
[Parameter("publish-runtime")]
|
||||
public string PublishRuntime { get; set; }
|
||||
|
||||
[Parameter("publish-project")]
|
||||
public string PublishProject { get; set; }
|
||||
|
||||
AbsolutePath SourceDirectory => RootDirectory / "src";
|
||||
|
||||
AbsolutePath TestsDirectory => RootDirectory / "tests";
|
||||
|
||||
AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts";
|
||||
|
||||
protected override void OnBuildInitialized()
|
||||
{
|
||||
Configuration = Configuration ?? "Release";
|
||||
VersionSuffix = VersionSuffix ?? "";
|
||||
}
|
||||
|
||||
private void DeleteDirectories(IReadOnlyCollection<string> directories)
|
||||
{
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
DeleteDirectory(directory);
|
||||
}
|
||||
}
|
||||
|
||||
Target Clean => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj"));
|
||||
DeleteDirectories(GlobDirectories(TestsDirectory, "**/bin", "**/obj"));
|
||||
EnsureCleanDirectory(ArtifactsDirectory);
|
||||
});
|
||||
|
||||
Target Restore => _ => _
|
||||
.DependsOn(Clean)
|
||||
.Executes(() =>
|
||||
{
|
||||
DotNetRestore(s => s
|
||||
.SetProjectFile(Solution));
|
||||
});
|
||||
|
||||
Target Compile => _ => _
|
||||
.DependsOn(Restore)
|
||||
.Executes(() =>
|
||||
{
|
||||
DotNetBuild(s => s
|
||||
.SetProjectFile(Solution)
|
||||
.SetConfiguration(Configuration)
|
||||
.SetVersionSuffix(VersionSuffix)
|
||||
.EnableNoRestore());
|
||||
});
|
||||
|
||||
Target Test => _ => _
|
||||
.DependsOn(Compile)
|
||||
.Executes(() =>
|
||||
{
|
||||
DotNetTest(s => s
|
||||
.SetProjectFile(Solution)
|
||||
.SetConfiguration(Configuration)
|
||||
.SetLogger("trx")
|
||||
.SetResultsDirectory(ArtifactsDirectory / "TestResults")
|
||||
.EnableNoBuild()
|
||||
.EnableNoRestore());
|
||||
});
|
||||
|
||||
Target Pack => _ => _
|
||||
.DependsOn(Test)
|
||||
.Executes(() =>
|
||||
{
|
||||
DotNetPack(s => s
|
||||
.SetProject(Solution)
|
||||
.SetConfiguration(Configuration)
|
||||
.SetVersionSuffix(VersionSuffix)
|
||||
.SetOutputDirectory(ArtifactsDirectory / "NuGet")
|
||||
.EnableNoBuild()
|
||||
.EnableNoRestore());
|
||||
});
|
||||
|
||||
Target Publish => _ => _
|
||||
.DependsOn(Test)
|
||||
.Requires(() => PublishRuntime)
|
||||
.Requires(() => PublishFramework)
|
||||
.Requires(() => PublishProject)
|
||||
.Executes(() =>
|
||||
{
|
||||
DotNetPublish(s => s
|
||||
.SetProject(Solution.GetProject(PublishProject))
|
||||
.SetConfiguration(Configuration)
|
||||
.SetVersionSuffix(VersionSuffix)
|
||||
.SetFramework(PublishFramework)
|
||||
.SetRuntime(PublishRuntime)
|
||||
.SetOutput(ArtifactsDirectory / "Publish" / PublishProject + "-" + PublishFramework + "-" + PublishRuntime));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<RootNamespace></RootNamespace>
|
||||
<IsPackable>False</IsPackable>
|
||||
<NoWarn>CS0649;CS0169</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nuke.Common" Version="0.18.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" />
|
||||
<NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" />
|
||||
<None Remove="*.ref;*.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"tools": {
|
||||
"dotnet": "3.0.100-preview-010184"
|
||||
},
|
||||
"sdk": {
|
||||
"version": "3.0.100-preview-010184"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<OutputType>Library</OutputType>
|
||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\build\Base.props" />
|
||||
<Import Project="..\..\build\Rx.props" />
|
||||
<Import Project="..\..\build\Avalonia.props" />
|
||||
<Import Project="..\..\build\ReactiveUI.props" />
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Avalonia.ThemeManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts multi-binding inputs to a final value.
|
||||
/// </summary>
|
||||
public class ObjectEqualityMultiConverter : IMultiValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts multi-binding inputs to a final value.
|
||||
/// </summary>
|
||||
/// <param name="values">The values to convert.</param>
|
||||
/// <param name="targetType">The type of the target.</param>
|
||||
/// <param name="parameter">A user-defined parameter.</param>
|
||||
/// <param name="culture">The culture to use.</param>
|
||||
/// <returns>The converted value.</returns>
|
||||
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values != null && values.Count == 2 && values[0] != AvaloniaProperty.UnsetValue && values[1] != AvaloniaProperty.UnsetValue)
|
||||
{
|
||||
return values[0].Equals(values[1]);
|
||||
}
|
||||
return AvaloniaProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Avalonia.Styling;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Avalonia.ThemeManager
|
||||
{
|
||||
public class Theme : ReactiveObject
|
||||
{
|
||||
private string _name;
|
||||
private IStyle _style;
|
||||
private ThemeSelector _selector;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => this.RaiseAndSetIfChanged(ref _name, value);
|
||||
}
|
||||
|
||||
public IStyle Style
|
||||
{
|
||||
get => _style;
|
||||
set => this.RaiseAndSetIfChanged(ref _style, value);
|
||||
}
|
||||
|
||||
public ThemeSelector Selector
|
||||
{
|
||||
get => _selector;
|
||||
set => this.RaiseAndSetIfChanged(ref _selector, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Avalonia.Styling;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Avalonia.ThemeManager
|
||||
{
|
||||
public class ThemeSelector : ReactiveObject
|
||||
{
|
||||
public static ThemeSelector Instance;
|
||||
|
||||
private Theme _selectedTheme;
|
||||
private ObservableCollection<Theme> _themes;
|
||||
private ObservableCollection<Window> _windows;
|
||||
|
||||
public Theme SelectedTheme
|
||||
{
|
||||
get => _selectedTheme;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedTheme, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<Theme> Themes
|
||||
{
|
||||
get => _themes;
|
||||
set => this.RaiseAndSetIfChanged(ref _themes, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<Window> Windows
|
||||
{
|
||||
get => _windows;
|
||||
set => this.RaiseAndSetIfChanged(ref _windows, value);
|
||||
}
|
||||
|
||||
public ThemeSelector(string path)
|
||||
{
|
||||
_themes = new ObservableCollection<Theme>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string file in System.IO.Directory.EnumerateFiles(path, "*.xaml"))
|
||||
{
|
||||
_themes.Add(LoadTheme(file));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
if (_themes.Count == 0)
|
||||
{
|
||||
var light = AvaloniaXamlLoader.Parse<StyleInclude>(@"<StyleInclude xmlns='https://github.com/avaloniaui' Source='avares://Avalonia.Themes.Default/Accents/BaseLight.xaml'/>");
|
||||
var dark = AvaloniaXamlLoader.Parse<StyleInclude>(@"<StyleInclude xmlns='https://github.com/avaloniaui' Source='avares://Avalonia.Themes.Default/Accents/BaseDark.xaml'/>");
|
||||
_themes.Add(new Theme() { Name = "Light", Style = light, Selector = this });
|
||||
_themes.Add(new Theme() { Name = "Dark", Style = dark, Selector = this });
|
||||
}
|
||||
|
||||
_selectedTheme = _themes.FirstOrDefault();
|
||||
|
||||
_windows = new ObservableCollection<Window>();
|
||||
}
|
||||
|
||||
public Theme LoadTheme(string file)
|
||||
{
|
||||
var name = System.IO.Path.GetFileNameWithoutExtension(file);
|
||||
var xaml = System.IO.File.ReadAllText(file);
|
||||
var style = AvaloniaXamlLoader.Parse<IStyle>(xaml);
|
||||
return new Theme() { Name = name, Style = style, Selector = this };
|
||||
}
|
||||
|
||||
public void EnableThemes(Window window)
|
||||
{
|
||||
IDisposable disposable = null;
|
||||
|
||||
window.Styles.Add(Instance.SelectedTheme.Style);
|
||||
|
||||
window.Opened += (sender, e) =>
|
||||
{
|
||||
_windows.Add(window);
|
||||
disposable = this.WhenAnyValue(x => x.SelectedTheme).Where(x => x != null).Subscribe(x =>
|
||||
{
|
||||
window.Styles[0] = x.Style;
|
||||
});
|
||||
};
|
||||
|
||||
window.Closing += (sender, e) =>
|
||||
{
|
||||
disposable?.Dispose();
|
||||
_windows.Remove(window);
|
||||
};
|
||||
}
|
||||
|
||||
public void ApplyTheme(Theme theme)
|
||||
{
|
||||
if (theme != null)
|
||||
{
|
||||
SelectedTheme = theme;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadSelectedTheme(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (System.IO.File.Exists(file) == true)
|
||||
{
|
||||
var name = System.IO.File.ReadAllText(file);
|
||||
if (name != null)
|
||||
{
|
||||
var theme = _themes.FirstOrDefault(x => x.Name == name);
|
||||
if (theme != null)
|
||||
{
|
||||
SelectedTheme = theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveSelectedTheme(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IO.File.WriteAllText(file, _selectedTheme?.Name);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче