├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── PleasantUI.sln
├── PleasantUIIcon.png
├── README.md
├── build
└── Package.props
├── designer
└── PleasantUI.Designer
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── PleasantUI.Designer.csproj
│ ├── Program.cs
│ └── app.manifest
├── generators
└── PleasantUI.MaterialIcons.SourceGenerator
│ ├── MaterialIconsSourceGenerator.cs
│ ├── PleasantUI.MaterialIcons.SourceGenerator.csproj
│ ├── Properties
│ └── launchSettings.json
│ └── StringExtensions.cs
├── global.json
├── samples
├── PleasantUI.Example.Android
│ ├── AndroidManifest.xml
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── Assets
│ │ └── Icons.axaml
│ ├── Icon.png
│ ├── MainActivity.cs
│ ├── PleasantMainView.axaml
│ ├── PleasantMainView.axaml.cs
│ ├── PleasantUI.Example.Android.csproj
│ ├── Properties
│ │ └── AndroidManifest.xml
│ └── Resources
│ │ ├── AboutResources.txt
│ │ ├── drawable-night-v31
│ │ └── avalonia_anim.xml
│ │ ├── drawable-v31
│ │ └── avalonia_anim.xml
│ │ ├── drawable
│ │ └── splash_screen.xml
│ │ ├── values-night
│ │ └── colors.xml
│ │ ├── values-v31
│ │ └── styles.xml
│ │ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
├── PleasantUI.Example.Browser
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── PleasantMainView.axaml
│ ├── PleasantMainView.axaml.cs
│ ├── PleasantUI.Example.Browser.csproj
│ ├── Program.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── launchSettings.json
│ ├── runtimeconfig.template.json
│ └── wwwroot
│ │ ├── app.css
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── main.js
├── PleasantUI.Example.Desktop
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── MainWindow.axaml
│ ├── MainWindow.axaml.cs
│ ├── PleasantUI.Example.Desktop.csproj
│ ├── PleasantUIIcon.ico
│ ├── Program.cs
│ └── app.manifest
└── PleasantUI.Example
│ ├── Assets
│ └── Images.axaml
│ ├── DataTemplates
│ └── ControlPageCardItemTemplate.axaml
│ ├── Factories
│ └── ControlPageCardsFactory.cs
│ ├── Interfaces
│ └── IPage.cs
│ ├── Logging
│ └── Logging
│ │ ├── LoggerExtensions.cs
│ │ ├── PleasantLogger.cs
│ │ └── SerilogSink.cs
│ ├── MainView.axaml
│ ├── MainView.axaml.cs
│ ├── Models
│ ├── ControlPageCard.cs
│ └── DataModel.cs
│ ├── Pages
│ ├── BasicControls
│ │ ├── ButtonPage.cs
│ │ ├── CalendarPage.cs
│ │ ├── CarouselPage.cs
│ │ ├── CheckBoxPage.cs
│ │ ├── ComboBoxPage.cs
│ │ ├── DataGridPage.cs
│ │ ├── HomePage.cs
│ │ ├── ProgressBarPage.cs
│ │ ├── SliderPage.cs
│ │ └── TextBoxPage.cs
│ ├── PleasantControls
│ │ ├── InformationBlockPage.cs
│ │ ├── OptionsDisplayItemPage.cs
│ │ ├── PleasantSnackbarPage.cs
│ │ ├── PleasantTabViewPage.cs
│ │ └── ProgressPage.cs
│ └── ToolKit
│ │ └── MessageBoxPage.cs
│ ├── PleasantUI.Example.csproj
│ ├── PleasantUIExampleApp.cs
│ ├── Properties
│ └── Localizations
│ │ ├── App.Designer.cs
│ │ ├── App.resx
│ │ ├── App.ru.resx
│ │ ├── Library.Designer.cs
│ │ ├── Library.resx
│ │ └── Library.ru.resx
│ ├── Structures
│ └── Language.cs
│ ├── ViewModels
│ ├── AppViewModel.cs
│ └── Pages
│ │ ├── ControlPages
│ │ ├── DataGridViewModel.cs
│ │ └── ProgressRingViewModel.cs
│ │ └── SettingsViewModel.cs
│ └── Views
│ ├── AboutView.axaml
│ ├── AboutView.axaml.cs
│ ├── HomeView.axaml
│ ├── HomeView.axaml.cs
│ ├── Pages
│ ├── ControlPages
│ │ ├── ButtonPageView.axaml
│ │ ├── ButtonPageView.axaml.cs
│ │ ├── CalendarPageView.axaml
│ │ ├── CalendarPageView.axaml.cs
│ │ ├── CarouselPageView.axaml
│ │ ├── CarouselPageView.axaml.cs
│ │ ├── CheckBoxPageView.axaml
│ │ ├── CheckBoxPageView.axaml.cs
│ │ ├── ComboBoxPageView.axaml
│ │ ├── ComboBoxPageView.axaml.cs
│ │ ├── DataGridPageView.axaml
│ │ ├── DataGridPageView.axaml.cs
│ │ ├── ProgressBarPageView.axaml
│ │ ├── ProgressBarPageView.axaml.cs
│ │ ├── SliderPageView.axaml
│ │ ├── SliderPageView.axaml.cs
│ │ ├── TextBoxPageView.axaml
│ │ └── TextBoxPageView.axaml.cs
│ ├── HomePageView.axaml
│ ├── HomePageView.axaml.cs
│ ├── PleasantControlPages
│ │ ├── InformationBlockPageView.axaml
│ │ ├── InformationBlockPageView.axaml.cs
│ │ ├── OptionsDisplayItemPageView.axaml
│ │ ├── OptionsDisplayItemPageView.axaml.cs
│ │ ├── PleasantSnackbarPageView.axaml
│ │ ├── PleasantSnackbarPageView.axaml.cs
│ │ ├── PleasantTabViewPageView.axaml
│ │ ├── PleasantTabViewPageView.axaml.cs
│ │ ├── ProgressRingPageView.axaml
│ │ └── ProgressRingPageView.axaml.cs
│ └── ToolKitPages
│ │ ├── MessageBoxPageView.axaml
│ │ └── MessageBoxPageView.axaml.cs
│ ├── SettingsView.axaml
│ └── SettingsView.axaml.cs
└── src
├── PleasantUI.DataGrid
├── DataGrid.axaml
└── PleasantUI.DataGrid.csproj
├── PleasantUI.MaterialIcons
├── MaterialIcons.cs
├── PleasantUI.MaterialIcons.csproj
└── Properties
│ └── AssemblyInfo.cs
├── PleasantUI.ToolKit
├── ColorPickerWindow.axaml
├── ColorPickerWindow.axaml.cs
├── Commands
│ ├── IEditorCommand.cs
│ └── ThemeEditor
│ │ ├── ColorChangeCommand.cs
│ │ ├── ThemeChangeCommand.cs
│ │ └── ThemeNameChangeCommand.cs
├── Controls
│ └── PleasantColorView
│ │ └── PleasantColorView.cs
├── Converters
│ └── ColorPickerConverters.cs
├── DataTemplates
│ └── ThemeColorItemTemplate.axaml
├── MessageBox.axaml
├── MessageBox.axaml.cs
├── Messages
│ ├── AsyncClipboardSetColorMessage.cs
│ ├── AsyncRequestClipboardColorMessage.cs
│ ├── AsyncRequestColorMessage.cs
│ └── ColorChangedMessage.cs
├── Models
│ └── ThemeColor.cs
├── PleasantUI.ToolKit.csproj
├── PleasantUIToolKit.axaml
├── Styling
│ └── ControlThemes
│ │ └── BasicControls
│ │ ├── ColorPreviewer.axaml
│ │ ├── ColorSlider.axaml
│ │ ├── ColorSpectrum.axaml
│ │ └── ColorView.axaml
├── ThemeEditorWindow.axaml
├── ThemeEditorWindow.axaml.cs
├── UserControls
│ ├── ThemePreview.axaml
│ └── ThemePreview.axaml.cs
└── ViewModels
│ └── ThemeEditorViewModel.cs
└── PleasantUI
├── Assets
└── IconGeometries.axaml
├── Behaviors
└── ShadowBehavior.cs
├── Controls
├── BackdropBlurControl
│ └── BackdropBlurControl.cs
├── Chrome
│ ├── PleasantCaptionButtons.cs
│ └── PleasantTitleBar.cs
├── ContentDialog
│ └── ContentDialog.cs
├── Flyout
│ ├── PleasantFlyout.cs
│ ├── PleasantMenuFlyout.cs
│ └── Presenters
│ │ ├── PleasantFlyoutPresenter.cs
│ │ └── PleasantMenuFlyoutPresenter.cs
├── InformationBlock
│ └── InformationBlock.cs
├── MarkedNumericUpDown
│ └── MarkedNumericUpDown.cs
├── MarkedTextBox
│ └── MarkedTextBox.cs
├── ModalWindowHost
│ └── ModalWindowHost.cs
├── NavigationView
│ ├── NavigationView.cs
│ └── NavigationViewItem.cs
├── OptionsDisplayItem
│ └── OptionsDisplayItem.cs
├── PleasantBorder
│ └── PleasantBorder.cs
├── PleasantMiniWindow
│ └── PleasantMiniWindow.cs
├── PleasantModalWindow
│ └── PleasantPopupElement.cs
├── PleasantTabView
│ ├── PleasantTabItem.cs
│ └── PleasantTabView.cs
├── PleasantView
│ └── PleasantView.cs
├── PleasantWindow
│ ├── PleasantWindow.cs
│ └── PleasantWindowBase.cs
├── ProgressRing
│ └── ProgressRing.cs
├── Ripple
│ ├── Ripple.cs
│ ├── RippleEffect.cs
│ └── RippleHandler.cs
├── SmoothScrollViewer
│ ├── SmoothScrollContentPresenter.cs
│ └── SmoothScrollViewer.cs
├── Snackbar
│ ├── PleasantSnackbar.cs
│ ├── PleasantSnackbarOptions.cs
│ └── SnackbarQueueManager.cs
├── ThemePreviewVariantScope
│ └── ThemePreviewVariantScope.cs
└── VirtualizingWrapPanel
│ ├── Utils
│ ├── RealizedWrappedElements.cs
│ └── UVSize.cs
│ └── VirtualizingWrapPanel.cs
├── Converters
├── BindingTranslateConverter.cs
├── ColorConverters.cs
├── ColorToTransparentConverter.cs
├── ColorToUIntConverter.cs
├── CornerRadiusFilterConverters.cs
├── FitSquarelyWithinAspectRatioConverter.cs
├── ForegroundBasedAccentConverter.cs
├── IntToColumnDefinitionWidthConverter.cs
├── MenuConverters.cs
├── OtherConverters.cs
├── ThicknessConverters.cs
├── TranslateConverter.cs
└── TreeViewItemMarginConverters.cs
├── Core
├── Collections
│ └── EventQueue.cs
├── Constants
│ ├── PleasantDirectories.cs
│ ├── PleasantFileNames.cs
│ ├── PleasantThemes.cs
│ └── ShadowDepths.cs
├── Extensions
│ ├── LogicalExtensions.cs
│ ├── Markup
│ │ ├── ColorToTransparentExtension.cs
│ │ ├── ForegroundBasedAccentExtension.cs
│ │ ├── KeyGestureExtension.cs
│ │ └── LocalizeExtension.cs
│ ├── Media
│ │ └── ColorExtensions.cs
│ ├── MiscExtensions.cs
│ ├── PropertyChangedExtensions.cs
│ ├── ResourceDictionaryExtensions.cs
│ ├── ResourceExtensions.cs
│ ├── StringToNumberExtensions.cs
│ ├── TabViewExtensions.cs
│ └── WindowIconExtensions.cs
├── GenerationContexts
│ └── PleasantSettingsGenerationContext.cs
├── Globalization.cs
├── Helpers
│ ├── ApplicationHelper.cs
│ └── ColorHelper.cs
├── Interfaces
│ ├── IPleasantWindow.cs
│ └── ISettingsProvider.cs
├── Localization
│ ├── ILocalizer.cs
│ ├── LocalizeObservable.cs
│ ├── Localizer.cs
│ └── RemoveLocalizeObserver.cs
├── Models
│ ├── CustomTheme.cs
│ └── Theme.cs
├── PleasantSettings.cs
├── PleasantThemesLoader.cs
├── Settings
│ ├── AppPleasantUISettingsProvider.cs
│ ├── RenderSettings.cs
│ └── WindowSettings.cs
├── SettingsBase.cs
├── Structures
│ └── MessageBoxButton.cs
└── ViewModelBase.cs
├── PleasantTheme.axaml
├── PleasantTheme.axaml.cs
├── PleasantUI.csproj
├── Properties
└── AssemblyInfo.cs
├── Reactive
├── AnonymousObserver.cs
├── CompositeDisposable.cs
├── Disposable.cs
├── Observable.cs
└── Operators
│ ├── CombineLatest.cs
│ └── Sink.cs
├── Styling
├── BaseColorsPalette.axaml
├── ControlThemes
│ ├── BasicControls
│ │ ├── AdornerLayer.axaml
│ │ ├── AutoCompleteBox.axaml
│ │ ├── Button.axaml
│ │ ├── ButtonSpinner.axaml
│ │ ├── Calendar.axaml
│ │ ├── CalendarButton.axaml
│ │ ├── CalendarDatePicker.axaml
│ │ ├── CalendarDayButton.axaml
│ │ ├── CalendarItem.axaml
│ │ ├── Carousel.axaml
│ │ ├── CheckBox.axaml
│ │ ├── ComboBox.axaml
│ │ ├── ComboBoxItem.axaml
│ │ ├── ContentControl.axaml
│ │ ├── ContextMenu.axaml
│ │ ├── DataValidationErrors.axaml
│ │ ├── DatePicker.axaml
│ │ ├── DateTimePickerShared.axaml
│ │ ├── DropDownButton.axaml
│ │ ├── EmbeddableControlRoot.axaml
│ │ ├── Expander.axaml
│ │ ├── FlyoutPresenter.axaml
│ │ ├── GridSplitter.axaml
│ │ ├── HeaderedContentControl.axaml
│ │ ├── ItemsControl.axaml
│ │ ├── Label.axaml
│ │ ├── ListBox.axaml
│ │ ├── ListBoxItem.axaml
│ │ ├── Menu.axaml
│ │ ├── MenuItem.axaml
│ │ ├── NativeMenuBar.axaml
│ │ ├── NotificationCard.axaml
│ │ ├── NumericUpDown.axaml
│ │ ├── OverlayPopupHost.axaml
│ │ ├── PathIcon.axaml
│ │ ├── PopupRoot.axaml
│ │ ├── ProgressBar.axaml
│ │ ├── RadioButton.axaml
│ │ ├── RefreshContainer.axaml
│ │ ├── RefreshVisualizer.axaml
│ │ ├── RepeatButton.axaml
│ │ ├── ScrollBar.axaml
│ │ ├── ScrollViewer.axaml
│ │ ├── SelectableTextBlock.axaml
│ │ ├── Separator.axaml
│ │ ├── Slider.axaml
│ │ ├── SplitView.axaml
│ │ ├── TabControl.axaml
│ │ ├── TabItem.axaml
│ │ ├── TabStrip.axaml
│ │ ├── TabStripItem.axaml
│ │ ├── TextBlock.axaml
│ │ ├── TextBox.axaml
│ │ ├── ThemeVariantScope.axaml
│ │ ├── TimePicker.axaml
│ │ ├── ToggleButton.axaml
│ │ ├── ToggleSwitch.axaml
│ │ ├── ToolTip.axaml
│ │ ├── TransitioningContentControl.axaml
│ │ ├── TreeView.axaml
│ │ ├── TreeViewItem.axaml
│ │ ├── Window.axaml
│ │ └── WindowNotificationManager.axaml
│ ├── Controls.axaml
│ └── PleasantControls
│ │ ├── ContentDialog.axaml
│ │ ├── InformationBlock.axaml
│ │ ├── MarkedNumericUpDown.axaml
│ │ ├── MarkedTextBox.axaml
│ │ ├── NavigationView.axaml
│ │ ├── NavigationViewItem.axaml
│ │ ├── OptionsDisplayItem.axaml
│ │ ├── PleasantBorder.axaml
│ │ ├── PleasantCaptionButtons.axaml
│ │ ├── PleasantFlyoutPresenter.axaml
│ │ ├── PleasantMiniWindow.axaml
│ │ ├── PleasantSnackbar.axaml
│ │ ├── PleasantTabItem.axaml
│ │ ├── PleasantTabView.axaml
│ │ ├── PleasantTitleBar.axaml
│ │ ├── PleasantWindow.axaml
│ │ ├── ProgressRing.axaml
│ │ ├── RippleEffect.axaml
│ │ └── SmoothScrollViewer.axaml
├── PleasantThemes.axaml
└── UnifiedResources.axaml
└── Transitions
└── PleasantPageSlide.cs
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: onebeld # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: ['https://boosty.to/onebeld'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-2023 Dmitry Zhutkov (Onebeld)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PleasantUIIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onebeld/PleasantUI/08100a52e29a967b936735886644d81e08c1e757/PleasantUIIcon.png
--------------------------------------------------------------------------------
/build/Package.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | enable
5 | enable
6 | default
7 | 5.0.0-alpha3
8 | Dmitry Zhutkov (Onebeld)
9 | Dmitry Zhutkov (Onebeld)
10 | theme, design, xaml, library, ui, gui, control, csharp, styled-components, interface, dotnet, nuget, style, avalonia, controls, user-interface, styles, avaloniaui, pleasant, graphical-user-interface
11 | UI library for Avalonia
12 | Onebeld
13 | 5.0.0
14 | 5.0.0
15 | true
16 | https://github.com/Onebeld/PleasantUI
17 | true
18 | Graphical user interface library for Avalonia with its own controls
19 | MIT
20 | README.md
21 | Public
22 | PleasantUIIcon.png
23 | true
24 | https://github.com/Onebeld/PleasantUI
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | True
35 | .\
36 | PleasantUIIcon.png
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/designer/PleasantUI.Designer/App.axaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/designer/PleasantUI.Designer/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls.ApplicationLifetimes;
3 | using Avalonia.Markup.Xaml;
4 | using PleasantUI.Controls;
5 |
6 | namespace PleasantUI.Designer;
7 |
8 | public partial class App : Application
9 | {
10 | public override void Initialize() => AvaloniaXamlLoader.Load(this);
11 |
12 | public override void OnFrameworkInitializationCompleted()
13 | {
14 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
15 | desktop.MainWindow = new PleasantWindow();
16 |
17 | base.OnFrameworkInitializationCompleted();
18 | }
19 | }
--------------------------------------------------------------------------------
/designer/PleasantUI.Designer/PleasantUI.Designer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net9.0
5 | enable
6 | true
7 | app.manifest
8 | true
9 | Full
10 |
11 |
12 |
13 | embedded
14 | true
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/designer/PleasantUI.Designer/Program.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using System;
3 |
4 | namespace PleasantUI.Designer;
5 |
6 | class Program
7 | {
8 | // Initialization code. Don't use any Avalonia, third-party APIs or any
9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
10 | // yet and stuff might break.
11 | [STAThread]
12 | public static void Main(string[] args) => BuildAvaloniaApp()
13 | .StartWithClassicDesktopLifetime(args);
14 |
15 | // Avalonia configuration, don't remove; also used by visual designer.
16 | public static AppBuilder BuildAvaloniaApp()
17 | => AppBuilder.Configure()
18 | .UsePlatformDetect()
19 | .LogToTrace();
20 | }
--------------------------------------------------------------------------------
/designer/PleasantUI.Designer/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/generators/PleasantUI.MaterialIcons.SourceGenerator/MaterialIconsSourceGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net.Http;
4 | using System.Text;
5 | using Microsoft.CodeAnalysis;
6 | using System.Text.Json.Nodes;
7 | using System.Threading.Tasks;
8 |
9 | namespace PleasantUI.MaterialIcons.SourceGenerator;
10 |
11 | [Generator]
12 | public class MaterialIconsSourceGenerator : IIncrementalGenerator
13 | {
14 | const string MaterialIconsFetchApi = "https://dev.materialdesignicons.com/api/package/38EF63D0-4744-11E4-B3CF-842B2B6CFE1B";
15 |
16 | private JsonNode? _json;
17 |
18 | public void Initialize(IncrementalGeneratorInitializationContext context)
19 | {
20 | HttpClient httpClient = new();
21 |
22 | Task task = Task.Run(() => httpClient.GetStreamAsync(MaterialIconsFetchApi));
23 | task.Wait();
24 |
25 | Stream? dataStream = task.Result;
26 | JsonNode? json = JsonNode.Parse(dataStream);
27 |
28 | _json = json ?? throw new Exception("Unable to load JSON");
29 |
30 | if (_json is null)
31 | throw new NullReferenceException("JSON is null");
32 |
33 | JsonArray icons = _json.Root["icons"]!.AsArray();
34 |
35 | const string generated = """
36 | //
37 | using Avalonia.Media;
38 |
39 | namespace PleasantUI;
40 |
41 | public static partial class MaterialIcons
42 | {
43 | """;
44 |
45 | StringBuilder stringBuilder = new(generated);
46 |
47 | foreach (JsonNode? icon in icons)
48 | {
49 | string name = icon!["name"]!.GetValue().Underscore().Pascalize();
50 | string data = icon["data"]!.GetValue();
51 |
52 | stringBuilder.Append($"\tpublic static Geometry {name} = Geometry.Parse(\"{data}\");\n");
53 | }
54 |
55 | stringBuilder.Append("}\n");
56 |
57 | context.RegisterPostInitializationOutput(ctx => ctx.AddSource("MaterialIcons.g.cs", stringBuilder.ToString()));
58 | }
59 | }
--------------------------------------------------------------------------------
/generators/PleasantUI.MaterialIcons.SourceGenerator/PleasantUI.MaterialIcons.SourceGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | false
5 | enable
6 | latest
7 |
8 | true
9 | true
10 |
11 | PleasantUI.MaterialIcons.SourceGenerator
12 | PleasantUI.MaterialIcons.SourceGenerator
13 |
14 |
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/generators/PleasantUI.MaterialIcons.SourceGenerator/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "DebugRoslynSourceGenerator": {
5 | "commandName": "DebugRoslynComponent",
6 | "targetProject": "../../src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/generators/PleasantUI.MaterialIcons.SourceGenerator/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Text.RegularExpressions;
2 |
3 | namespace PleasantUI.MaterialIcons.SourceGenerator;
4 |
5 | public static class StringExtensions
6 | {
7 | public static string Underscore(this string input) {
8 | return Regex.Replace(
9 | Regex.Replace(
10 | Regex.Replace(input, @"([\p{Lu}]+)([\p{Lu}][\p{Ll}])", "$1_$2"), @"([\p{Ll}\d])([\p{Lu}])", "$1_$2"), @"[-\s]", "_").ToLower();
11 | }
12 |
13 | public static string Pascalize(this string input)
14 | {
15 | return Regex.Replace(input, "(?:^|_| +)(.)", match => match.Groups[1].Value.ToUpper());
16 | }
17 | }
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.0",
4 | "rollForward": "latestMajor",
5 | "allowPrerelease": true
6 | }
7 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/App.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/App.axaml.cs:
--------------------------------------------------------------------------------
1 | namespace PleasantUI.Example.Android;
2 |
3 | public partial class App : PleasantUIExampleApp
4 | {
5 |
6 | public override void Initialize() => AvaloniaXamlLoader.Load(this);
7 |
8 | public override void OnFrameworkInitializationCompleted()
9 | {
10 | PleasantTheme = Styles[0] as PleasantTheme ?? throw new NullReferenceException("PleasantTheme is null");
11 |
12 | if (ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
13 | {
14 | lifetime.MainView = new PleasantMainView
15 | {
16 | DataContext = ViewModel
17 | };
18 | }
19 |
20 | base.OnFrameworkInitializationCompleted();
21 | }
22 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onebeld/PleasantUI/08100a52e29a967b936735886644d81e08c1e757/samples/PleasantUI.Example.Android/Icon.png
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using PleasantUI.Core;
2 |
3 | namespace PleasantUI.Example.Android;
4 |
5 | [Activity(
6 | Label = "PleasantUI.Example",
7 | Theme = "@style/MyTheme.NoActionBar",
8 | Icon = "@drawable/icon",
9 | MainLauncher = true,
10 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
11 | public class MainActivity : AvaloniaMainActivity
12 | {
13 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
14 | {
15 | return base.CustomizeAppBuilder(builder);
16 | }
17 |
18 | protected override void OnStop()
19 | {
20 | PleasantSettings.Save();
21 |
22 | base.OnStop();
23 | }
24 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/PleasantMainView.axaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/PleasantMainView.axaml.cs:
--------------------------------------------------------------------------------
1 | using PleasantUI.Controls;
2 | using PleasantUI.Core;
3 |
4 | namespace PleasantUI.Example.Android;
5 |
6 | public partial class PleasantMainView : PleasantView
7 | {
8 | public PleasantMainView()
9 | {
10 | InitializeComponent();
11 | }
12 |
13 | private void OnUnloaded(object? sender, RoutedEventArgs e)
14 | {
15 | PleasantSettings.Save();
16 | }
17 |
18 | protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
19 | {
20 | base.OnApplyTemplate(e);
21 |
22 | /*App.ViewModel.NotificationManager = new PleasantNotificationManager(this)
23 | {
24 | Position = NotificationPosition.TopRight,
25 | MaxItems = 3,
26 | ZIndex = 1
27 | };*/
28 | }
29 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/PleasantUI.Example.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net8.0-android
5 | 26
6 | enable
7 | com.Onebeld.PleasantUI.Example
8 | 1
9 | 1.0
10 | apk
11 | true
12 |
13 |
14 |
16 |
17 |
18 |
19 | true
20 | true
21 |
22 |
23 |
24 |
25 | Resources\drawable\Icon.png
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/drawable/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #212121
4 |
5 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/values-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
16 |
20 |
21 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
5 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/App.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | #E4000000
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Controls.ApplicationLifetimes;
3 | using Avalonia.Markup.Xaml;
4 |
5 | namespace PleasantUI.Example.Browser;
6 |
7 | public partial class App : PleasantUiExampleApp
8 | {
9 | public override void Initialize() => AvaloniaXamlLoader.Load(this);
10 |
11 | public override void OnFrameworkInitializationCompleted()
12 | {
13 | PleasantTheme = Styles[0] as PleasantTheme ?? throw new NullReferenceException("PleasantTheme is null");
14 |
15 | if (ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
16 | {
17 | lifetime.MainView = new PleasantMainView
18 | {
19 | DataContext = ViewModel
20 | };
21 | }
22 |
23 | base.OnFrameworkInitializationCompleted();
24 | }
25 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/PleasantMainView.axaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/PleasantMainView.axaml.cs:
--------------------------------------------------------------------------------
1 | using PleasantUI.Controls;
2 |
3 | namespace PleasantUI.Example.Browser;
4 |
5 | public partial class PleasantMainView : PleasantView
6 | {
7 | public PleasantMainView()
8 | {
9 | InitializeComponent();
10 | }
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/PleasantUI.Example.Browser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-browser
4 | Exe
5 | true
6 | enable
7 | 5
8 | false
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Threading.Tasks;
3 | using Avalonia;
4 | using Avalonia.Browser;
5 | using PleasantUI.Example.Browser;
6 |
7 | internal sealed partial class Program
8 | {
9 | private static Task Main(string[] args)
10 | {
11 | Trace.Listeners.Add(new ConsoleTraceListener());
12 |
13 | return BuildAvaloniaApp()
14 | .LogToTrace()
15 | .StartBrowserAppAsync("out");
16 | }
17 |
18 | public static AppBuilder BuildAvaloniaApp()
19 | => AppBuilder.Configure();
20 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")]
2 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "PleasantUI.Example.Browser": {
4 | "commandName": "Project",
5 | "launchBrowser": true,
6 | "environmentVariables": {
7 | "ASPNETCORE_ENVIRONMENT": "Development"
8 | },
9 | "applicationUrl": "https://localhost:7169;http://localhost:5235",
10 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/runtimeconfig.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "wasmHostProperties": {
3 | "perHostConfig": [
4 | {
5 | "name": "browser",
6 | "host": "browser"
7 | }
8 | ]
9 | }
10 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/wwwroot/app.css:
--------------------------------------------------------------------------------
1 | /* HTML styles for the splash screen */
2 | .avalonia-splash {
3 | position: absolute;
4 | height: 100%;
5 | width: 100%;
6 | background: white;
7 | font-family: 'Outfit', sans-serif;
8 | justify-content: center;
9 | align-items: center;
10 | display: flex;
11 | pointer-events: none;
12 | }
13 |
14 | /* Light theme styles */
15 | @media (prefers-color-scheme: light) {
16 | .avalonia-splash {
17 | background: white;
18 | }
19 |
20 | .avalonia-splash h2 {
21 | color: #1b2a4e;
22 | }
23 |
24 | .avalonia-splash a {
25 | color: #0D6EFD;
26 | }
27 | }
28 |
29 | @media (prefers-color-scheme: dark) {
30 | .avalonia-splash {
31 | background: #1b2a4e;
32 | }
33 |
34 | .avalonia-splash h2 {
35 | color: white;
36 | }
37 |
38 | .avalonia-splash a {
39 | color: white;
40 | }
41 | }
42 |
43 | .avalonia-splash h2 {
44 | font-weight: 400;
45 | font-size: 1.5rem;
46 | }
47 |
48 | .avalonia-splash a {
49 | text-decoration: none;
50 | font-size: 2.5rem;
51 | display: block;
52 | }
53 |
54 | .avalonia-splash.splash-close {
55 | transition: opacity 200ms, display 200ms;
56 | display: none;
57 | opacity: 0;
58 | }
59 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onebeld/PleasantUI/08100a52e29a967b936735886644d81e08c1e757/samples/PleasantUI.Example.Browser/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Browser/wwwroot/main.js:
--------------------------------------------------------------------------------
1 | import { dotnet } from './_framework/dotnet.js'
2 |
3 | const is_browser = typeof window != "undefined";
4 | if (!is_browser) throw new Error(`Expected to be running in a browser`);
5 |
6 | const dotnetRuntime = await dotnet
7 | .withDiagnosticTracing(false)
8 | .withApplicationArgumentsFromQuery()
9 | .create();
10 |
11 | const config = dotnetRuntime.getConfig();
12 |
13 | await dotnetRuntime.runMain(config.mainAssemblyName, [globalThis.location.href]);
14 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/App.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | #E4000000
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using Avalonia.Controls.ApplicationLifetimes;
3 | using Avalonia.Markup.Xaml;
4 | using PleasantUI.Controls;
5 |
6 | namespace PleasantUI.Example.Desktop;
7 |
8 | public partial class App : PleasantUiExampleApp
9 | {
10 | public override void Initialize() => AvaloniaXamlLoader.Load(this);
11 |
12 | public override void OnFrameworkInitializationCompleted()
13 | {
14 | if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
15 | return;
16 |
17 | if (Design.IsDesignMode)
18 | {
19 | desktop.MainWindow = new PleasantWindow();
20 |
21 | base.OnFrameworkInitializationCompleted();
22 | return;
23 | }
24 |
25 | PleasantTheme = Styles[0] as PleasantTheme ?? throw new NullReferenceException("PleasantTheme is null");
26 |
27 | Main = new MainWindow
28 | {
29 | DataContext = ViewModel
30 | };
31 |
32 | TopLevel = TopLevel.GetTopLevel(Main as PleasantWindow) ?? throw new NullReferenceException("TopLevel is null");
33 |
34 | desktop.MainWindow = Main as PleasantWindow;
35 |
36 | base.OnFrameworkInitializationCompleted();
37 | }
38 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/MainWindow.axaml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/MainWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | using PleasantUI.Controls;
2 |
3 | namespace PleasantUI.Example.Desktop;
4 |
5 | public partial class MainWindow : PleasantWindow
6 | {
7 | public MainWindow() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/PleasantUI.Example.Desktop.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net9.0
5 | enable
6 | enable
7 | true
8 | app.manifest
9 | true
10 | true
11 | Dmitry Zhutkov (Onebeld)
12 | PleasantUIIcon.ico
13 | true
14 |
15 |
16 |
17 | embedded
18 | true
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/PleasantUIIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onebeld/PleasantUI/08100a52e29a967b936735886644d81e08c1e757/samples/PleasantUI.Example.Desktop/PleasantUIIcon.ico
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using Avalonia;
3 | using PleasantUI.Example.Logging.Logging;
4 | using Serilog;
5 |
6 | namespace PleasantUI.Example.Desktop;
7 |
8 | class Program
9 | {
10 | private static readonly string PathToLog = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
11 | private static readonly string FileName = Path.Combine(PathToLog,
12 | $"{AppDomain.CurrentDomain.FriendlyName}_{DateTime.Now:dd.MM.yyyy}.log");
13 |
14 | [STAThread]
15 | public static void Main(string[] args)
16 | {
17 | if (!Directory.Exists(PathToLog))
18 | Directory.CreateDirectory(PathToLog);
19 |
20 | bool createLogFile = !File.Exists(FileName);
21 |
22 | using PleasantLogger logger = new(
23 | new LoggerConfiguration().WriteTo.File(FileName, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level}] | {Message:lj}{NewLine}{Exception}")
24 | );
25 |
26 | if (createLogFile)
27 | WriteDeviceInformation();
28 |
29 | BuildAvaloniaApp()
30 | .StartWithClassicDesktopLifetime(args);
31 | }
32 |
33 | private static void WriteDeviceInformation()
34 | {
35 | StringBuilder stringBuilder = new();
36 |
37 | stringBuilder.AppendLine($"OS: {Environment.OSVersion}");
38 | stringBuilder.AppendLine($"CPU: {Environment.ProcessorCount} cores");
39 |
40 | Log.Information("Device information:\n" + stringBuilder);
41 | }
42 |
43 | public static AppBuilder BuildAvaloniaApp()
44 | {
45 | AppBuilder appBuilder = AppBuilder.Configure();
46 | appBuilder.UsePlatformDetect();
47 |
48 | appBuilder
49 | .With(new Win32PlatformOptions
50 | {
51 | OverlayPopups = false
52 | })
53 | .With(new MacOSPlatformOptions
54 | {
55 | DisableDefaultApplicationMenuItems = true,
56 | ShowInDock = false,
57 | DisableNativeMenus = true
58 | })
59 | .With(new X11PlatformOptions
60 | {
61 | OverlayPopups = true
62 | });
63 |
64 | appBuilder.LogToSerilog();
65 |
66 | return appBuilder;
67 | }
68 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example.Desktop/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/DataTemplates/ControlPageCardItemTemplate.axaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Interfaces/IPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Interfaces;
4 |
5 | public interface IPage
6 | {
7 | string Title { get; }
8 |
9 | bool ShowTitle { get; }
10 |
11 | Control Content { get; }
12 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Logging/Logging/LoggerExtensions.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Logging;
3 |
4 | namespace PleasantUI.Example.Logging.Logging;
5 |
6 | ///
7 | /// Extensions for to log to Serilog.
8 | ///
9 | public static class LoggerExtensions
10 | {
11 | ///
12 | /// Logs to Serilog with the given log level and areas.
13 | ///
14 | /// The .
15 | /// The level of the log messages to be written to Serilog.
16 | /// The areas to log.
17 | /// The same instance of the .
18 | public static AppBuilder LogToSerilog(this AppBuilder builder, LogEventLevel level = LogEventLevel.Warning,
19 | params string[] areas)
20 | {
21 | Avalonia.Logging.Logger.Sink = new SerilogSink(level, areas);
22 | return builder;
23 | }
24 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Logging/Logging/PleasantLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Runtime.ExceptionServices;
3 | using Serilog;
4 |
5 | namespace PleasantUI.Example.Logging.Logging;
6 |
7 | ///
8 | /// A logger that handles unhandled exceptions and first chance exceptions.
9 | ///
10 | public class PleasantLogger : IDisposable
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | /// The logger configuration.
16 | public PleasantLogger(LoggerConfiguration loggerConfiguration)
17 | {
18 | Log.Logger = loggerConfiguration.CreateLogger();
19 |
20 | AppDomain.CurrentDomain.FirstChanceException += CurrentDomainOnFirstChanceException;
21 | AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
22 |
23 | Log.Information("The logger has been initialized");
24 | }
25 |
26 | ///
27 | public void Dispose()
28 | {
29 | Log.Information("The logger has been disposed");
30 |
31 | AppDomain.CurrentDomain.FirstChanceException -= CurrentDomainOnFirstChanceException;
32 | AppDomain.CurrentDomain.UnhandledException -= CurrentDomainOnUnhandledException;
33 |
34 | Log.CloseAndFlush();
35 | }
36 |
37 | private static void CurrentDomainOnFirstChanceException(object? sender, FirstChanceExceptionEventArgs e)
38 | {
39 | StackTrace stackTrace = new(1, true);
40 | Log.Error($"An handled exception occurred\n{e.Exception.GetType()}: {e.Exception.Message}\n{stackTrace}");
41 | }
42 |
43 | private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
44 | {
45 | if (e.ExceptionObject is Exception ex)
46 | Log.Fatal(ex, "An unhandled exception occurred");
47 |
48 | Log.CloseAndFlush();
49 | }
50 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/MainView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Views;
3 |
4 | namespace PleasantUI.Example;
5 |
6 | public partial class MainView : UserControl
7 | {
8 | public MainView()
9 | {
10 | InitializeComponent();
11 |
12 | HomeView.FuncControl += () => new HomeView { DataContext = DataContext };
13 | SettingsView.FuncControl += () => new SettingsView();
14 | AboutView.FuncControl += () => new AboutView();
15 | }
16 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Models/ControlPageCard.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Media;
2 | using CommunityToolkit.Mvvm.Input;
3 | using CommunityToolkit.Mvvm.Messaging;
4 | using CommunityToolkit.Mvvm.Messaging.Messages;
5 | using PleasantUI.Example.Interfaces;
6 |
7 | namespace PleasantUI.Example.Models;
8 |
9 | public partial class ControlPageCard
10 | {
11 | public string Title { get; set; }
12 |
13 | public Geometry Icon { get; set; }
14 |
15 | public string Description { get; set; }
16 |
17 | public IPage Page { get; set; }
18 |
19 | public ControlPageCard(string title, Geometry icon, string description, IPage page)
20 | {
21 | Title = title;
22 | Icon = icon;
23 | Description = description;
24 | Page = page;
25 | }
26 |
27 | [RelayCommand]
28 | public void OpenPage()
29 | {
30 | WeakReferenceMessenger.Default.Send(new ValueChangedMessage(Page));
31 | }
32 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Models/DataModel.cs:
--------------------------------------------------------------------------------
1 | namespace PleasantUI.Example.Models;
2 |
3 | public class DataModel
4 | {
5 | public string Name { get; set; }
6 |
7 | public int Age { get; set; }
8 |
9 | public bool IsNew { get; set; }
10 |
11 | public DataModel(string name, int age, bool isNew)
12 | {
13 | Name = name;
14 | Age = age;
15 | IsNew = isNew;
16 | }
17 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/ButtonPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | namespace PleasantUI.Example.Pages.BasicControls;
6 |
7 | public class ButtonPage : IPage
8 | {
9 | public string Title { get; } = "Button";
10 |
11 | public bool ShowTitle { get; } = true;
12 |
13 | public Control Content
14 | {
15 | get { return new ButtonPageView(); }
16 | }
17 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/CalendarPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class CalendarPage : IPage
7 | {
8 | public string Title { get; } = "Calendar";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/CarouselPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class CarouselPage : IPage
7 | {
8 | public string Title { get; } = "Carousel";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/CheckBoxPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | namespace PleasantUI.Example.Pages.BasicControls;
6 |
7 | public class CheckBoxPage : IPage
8 | {
9 | public string Title { get; } = "CheckBox";
10 |
11 | public bool ShowTitle { get; } = true;
12 |
13 | public Control Content
14 | {
15 | get { return new CheckBoxPageView(); }
16 | }
17 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/ComboBoxPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class ComboBoxPage : IPage
7 | {
8 | public string Title { get; } = "ComboBox";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/DataGridPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | namespace PleasantUI.Example.Pages.BasicControls;
6 |
7 | public class DataGridPage : IPage
8 | {
9 | public string Title { get; } = "DataGrid";
10 | public bool ShowTitle { get; } = true;
11 |
12 | public Control Content => new DataGridPageView();
13 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/HomePage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages;
4 |
5 | namespace PleasantUI.Example.Pages.BasicControls;
6 |
7 | public class HomePage : IPage
8 | {
9 | public string Title { get; } = "Home";
10 |
11 | public bool ShowTitle { get; } = false;
12 |
13 | public Control Content
14 | {
15 | get { return new HomePageView(); }
16 | }
17 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/ProgressBarPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class ProgressBarPage : IPage
7 | {
8 | public string Title { get; } = "ProgressBar";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/SliderPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class SliderPage : IPage
7 | {
8 | public string Title { get; } = "Slider";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/BasicControls/TextBoxPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.BasicControls;
5 |
6 | public class TextBoxPage : IPage
7 | {
8 | public string Title { get; } = "TextBox";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/PleasantControls/InformationBlockPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.PleasantControls;
5 |
6 | public class InformationBlockPage : IPage
7 | {
8 | public string Title { get; } = "InformationBlock";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/PleasantControls/OptionsDisplayItemPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.PleasantControls;
5 |
6 | public class OptionsDisplayItemPage : IPage
7 | {
8 | public string Title { get; } = "OptionsDisplayItem";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/PleasantControls/PleasantSnackbarPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.PleasantControlPages;
4 |
5 | namespace PleasantUI.Example.Pages.PleasantControls;
6 |
7 | public class PleasantSnackbarPage : IPage
8 | {
9 | public string Title { get; } = "PleasantSnackbar";
10 | public bool ShowTitle { get; } = true;
11 |
12 | public Control Content
13 | {
14 | get
15 | {
16 | return new PleasantSnackbarPageView();
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/PleasantControls/PleasantTabViewPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 |
4 | namespace PleasantUI.Example.Pages.PleasantControls;
5 |
6 | public class PleasantTabViewPage : IPage
7 | {
8 | public string Title { get; } = "PleasantTabView";
9 | public bool ShowTitle { get; } = true;
10 | public Control Content { get; } = null!;
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/PleasantControls/ProgressPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.PleasantControlPages;
4 |
5 | namespace PleasantUI.Example.Pages.PleasantControls;
6 |
7 | public class ProgressPage : IPage
8 | {
9 | public string Title { get; } = "Progress";
10 | public bool ShowTitle { get; } = true;
11 | public Control Content
12 | {
13 | get => new ProgressRingPageView();
14 | }
15 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Pages/ToolKit/MessageBoxPage.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.Interfaces;
3 | using PleasantUI.Example.Views.Pages.ToolkitPages;
4 |
5 | namespace PleasantUI.Example.Pages.Toolkit;
6 |
7 | public class MessageBoxPage : IPage
8 | {
9 | public string Title { get; } = "MessageBox";
10 | public bool ShowTitle { get; } = true;
11 |
12 | public Control Content => new MessageBoxPageView();
13 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/PleasantUIExampleApp.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using Avalonia;
3 | using Avalonia.Controls;
4 | using PleasantUI.Core.Interfaces;
5 | using PleasantUI.Core.Localization;
6 | using PleasantUI.Example.Structures;
7 | using PleasantUI.Example.ViewModels;
8 |
9 | namespace PleasantUI.Example;
10 |
11 | public class PleasantUiExampleApp : Application
12 | {
13 | public static PleasantTheme PleasantTheme { get; protected set; } = null!;
14 |
15 | public static IPleasantWindow Main { get; protected set; } = null!;
16 |
17 | public static AppViewModel ViewModel { get; } = null!;
18 |
19 | public static TopLevel? TopLevel { get; protected set; }
20 |
21 | static PleasantUiExampleApp()
22 | {
23 | if (!Design.IsDesignMode)
24 | ViewModel = new AppViewModel();
25 | }
26 |
27 | public PleasantUiExampleApp()
28 | {
29 | if (!Design.IsDesignMode)
30 | DataContext = ViewModel;
31 |
32 | Localizer.AddRes(new ResourceManager(typeof(Properties.Localizations.App)));
33 | Localizer.AddRes(new ResourceManager(typeof(Properties.Localizations.Library)));
34 |
35 | Localizer.ChangeLang("en");
36 | }
37 |
38 | public static string LanguageKey { get; set; } = "en";
39 |
40 | public static readonly Language[] Languages =
41 | [
42 | new("English (English)", "en"),
43 | new("Русский (Russian)", "ru")
44 | ];
45 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Structures/Language.cs:
--------------------------------------------------------------------------------
1 | namespace PleasantUI.Example.Structures;
2 |
3 | public readonly struct Language(string name, string key)
4 | {
5 | public string Name { get; } = name;
6 |
7 | public string Key { get; } = key;
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/ViewModels/Pages/ControlPages/DataGridViewModel.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Collections;
2 | using CommunityToolkit.Mvvm.ComponentModel;
3 | using PleasantUI.Example.Models;
4 |
5 | namespace PleasantUI.Example.ViewModels.Pages.ControlPages;
6 |
7 | public class DataGridViewModel : ObservableObject
8 | {
9 | public AvaloniaList DataModels { get; }
10 |
11 | public DataGridViewModel()
12 | {
13 | DataModels = new AvaloniaList
14 | {
15 | new("John", 23, true),
16 | new("Jane", 24, false),
17 | new("Jack", 25, true),
18 | new("Jill", 26, false),
19 | new("Joe", 27, true),
20 | };
21 | }
22 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/ViewModels/Pages/ControlPages/ProgressRingViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace PleasantUI.Example.ViewModels.Pages.ControlPages;
4 |
5 | public partial class ProgressRingViewModel : ObservableObject
6 | {
7 | [ObservableProperty]
8 | private double _value = 25;
9 |
10 | [ObservableProperty]
11 | private bool _isIndeterminate;
12 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/ViewModels/Pages/SettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using CommunityToolkit.Mvvm.Input;
3 | using PleasantUI.Core;
4 | using PleasantUI.Core.Localization;
5 | using PleasantUI.Core.Models;
6 | using PleasantUI.Example.Structures;
7 | using PleasantUI.ToolKit;
8 |
9 | namespace PleasantUI.Example.ViewModels.Pages;
10 |
11 | public partial class SettingsViewModel : ObservableObject
12 | {
13 | public Language SelectedLanguage
14 | {
15 | get => PleasantUiExampleApp.Languages.First(language => language.Key == PleasantUiExampleApp.LanguageKey);
16 | set
17 | {
18 | PleasantUiExampleApp.LanguageKey = value.Key;
19 | Localizer.ChangeLang(value.Key);
20 | }
21 | }
22 |
23 | public Theme? SelectedTheme
24 | {
25 | get => PleasantSettings.Current?.Theme is string themeName
26 | ? PleasantTheme.Themes.FirstOrDefault(theme => theme.Name == themeName)
27 | : null;
28 |
29 | set
30 | {
31 | if (PleasantSettings.Current is not null)
32 | PleasantSettings.Current.Theme = value?.Name ?? "System";
33 | }
34 | }
35 |
36 | public CustomTheme? SelectedCustomTheme
37 | {
38 | get => PleasantTheme.SelectedCustomTheme;
39 | set => PleasantTheme.SelectedCustomTheme = value;
40 | }
41 |
42 | [RelayCommand]
43 | private async Task CreateThemeAsync()
44 | {
45 | CustomTheme? newCustomTheme = await ThemeEditorWindow.EditTheme(PleasantUiExampleApp.Main, null);
46 |
47 | if (newCustomTheme is null)
48 | return;
49 |
50 | PleasantTheme.CustomThemes.Add(newCustomTheme);
51 | }
52 |
53 | [RelayCommand]
54 | private async Task EditThemeAsync(CustomTheme customTheme)
55 | {
56 | CustomTheme? newCustomTheme = await ThemeEditorWindow.EditTheme(PleasantUiExampleApp.Main, customTheme);
57 |
58 | if (newCustomTheme is null)
59 | return;
60 |
61 | PleasantUiExampleApp.PleasantTheme.EditCustomTheme(customTheme, newCustomTheme);
62 | }
63 |
64 | [RelayCommand]
65 | private void DeleteTheme(CustomTheme customTheme)
66 | {
67 | PleasantTheme.CustomThemes.Remove(customTheme);
68 | }
69 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/AboutView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views;
4 |
5 | public partial class AboutView : UserControl
6 | {
7 | public AboutView()
8 | {
9 | InitializeComponent();
10 |
11 | Version pleasantUiVersion = typeof(PleasantTheme).Assembly.GetName().Version!;
12 | VersionTextBlock.Text = $"Version: {pleasantUiVersion.Major}.{pleasantUiVersion.Minor}.{pleasantUiVersion.Build}";
13 | }
14 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/HomeView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views;
4 |
5 | public partial class HomeView : UserControl
6 | {
7 | public HomeView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class ButtonPageView : UserControl
6 | {
7 | public ButtonPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CalendarPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CalendarPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class CalendarPageView : UserControl
6 | {
7 | public CalendarPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CarouselPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CarouselPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class CarouselPageView : UserControl
6 | {
7 | public CarouselPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CheckBoxPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/CheckBoxPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class CheckBoxPageView : UserControl
6 | {
7 | public CheckBoxPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ComboBoxPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ComboBoxPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class ComboBoxPageView : UserControl
6 | {
7 | public ComboBoxPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/DataGridPageView.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/DataGridPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class DataGridPageView : UserControl
6 | {
7 | public DataGridPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ProgressBarPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/ProgressBarPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class ProgressBarPageView : UserControl
6 | {
7 | public ProgressBarPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/SliderPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/SliderPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class SliderPageView : UserControl
6 | {
7 | public SliderPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/TextBoxPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ControlPages/TextBoxPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.ControlPages;
4 |
5 | public partial class TextBoxPageView : UserControl
6 | {
7 | public TextBoxPageView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/HomePageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages;
4 |
5 | public partial class HomePageView : UserControl
6 | {
7 | public HomePageView()
8 | {
9 | DataContext = PleasantUiExampleApp.ViewModel;
10 |
11 | InitializeComponent();
12 | }
13 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/InformationBlockPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/InformationBlockPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.PleasantControlPages;
4 |
5 | public partial class InformationBlockPageView : UserControl
6 | {
7 | public InformationBlockPageView()
8 | {
9 | InitializeComponent();
10 | }
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/OptionsDisplayItemPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/OptionsDisplayItemPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.PleasantControlPages;
4 |
5 | public partial class OptionsDisplayItemPageView : UserControl
6 | {
7 | public OptionsDisplayItemPageView()
8 | {
9 | InitializeComponent();
10 | }
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/PleasantSnackbarPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/PleasantSnackbarPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Controls;
3 |
4 | namespace PleasantUI.Example.Views.Pages.PleasantControlPages;
5 |
6 | public partial class PleasantSnackbarPageView : UserControl
7 | {
8 | public PleasantSnackbarPageView()
9 | {
10 | InitializeComponent();
11 |
12 | SnackbarButton.Click += (sender, args) =>
13 | {
14 | PleasantSnackbar.Show(PleasantUiExampleApp.Main, new PleasantSnackbarOptions("Привет, мир!")
15 | {
16 | Icon = MaterialIcons.Account
17 | });
18 | };
19 | }
20 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/PleasantTabViewPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 | Welcome to Avalonia!
8 |
9 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/PleasantTabViewPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views.Pages.PleasantControlPages;
4 |
5 | public partial class PleasantTabViewPageView : UserControl
6 | {
7 | public PleasantTabViewPageView()
8 | {
9 | InitializeComponent();
10 | }
11 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/ProgressRingPageView.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
14 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/PleasantControlPages/ProgressRingPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.Example.ViewModels.Pages.ControlPages;
3 |
4 | namespace PleasantUI.Example.Views.Pages.PleasantControlPages;
5 |
6 | public partial class ProgressRingPageView : UserControl
7 | {
8 | public ProgressRingPageView()
9 | {
10 | InitializeComponent();
11 | DataContext = new ProgressRingViewModel();
12 | }
13 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ToolKitPages/MessageBoxPageView.axaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/Pages/ToolKitPages/MessageBoxPageView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PleasantUI.ToolKit;
3 |
4 | namespace PleasantUI.Example.Views.Pages.ToolkitPages;
5 |
6 | public partial class MessageBoxPageView : UserControl
7 | {
8 | public MessageBoxPageView()
9 | {
10 | InitializeComponent();
11 |
12 | DefaultMBButton.Click += (_, _) => MessageBox.Show(PleasantUiExampleApp.Main, "Title", "Hello, world!");
13 | }
14 | }
--------------------------------------------------------------------------------
/samples/PleasantUI.Example/Views/SettingsView.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 |
3 | namespace PleasantUI.Example.Views;
4 |
5 | public partial class SettingsView : UserControl
6 | {
7 | public SettingsView() => InitializeComponent();
8 | }
--------------------------------------------------------------------------------
/src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | PleasantUI.DataGrid
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/PleasantUI.MaterialIcons/MaterialIcons.cs:
--------------------------------------------------------------------------------
1 | namespace PleasantUI;
2 |
3 | public partial class MaterialIcons;
--------------------------------------------------------------------------------
/src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | latest
5 | enable
6 | 4.1.0-beta3
7 | 4.1.0
8 | 4.1.0
9 | https://github.com/Onebeld/PleasantUI
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/PleasantUI.MaterialIcons/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Metadata;
2 |
3 | [assembly: XmlnsDefinition("https://github.com/avaloniaui", "PleasantUI")]
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/ColorPickerWindow.axaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/ColorPickerWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Input;
2 | using Avalonia.Media;
3 | using PleasantUI.Controls;
4 | using PleasantUI.Core.Interfaces;
5 |
6 | namespace PleasantUI.ToolKit;
7 |
8 | ///
9 | /// Represents a window that can be used to pick a color.
10 | ///
11 | ///
12 | public partial class ColorPickerWindow : ContentDialog
13 | {
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | public ColorPickerWindow()
18 | {
19 | InitializeComponent();
20 | }
21 |
22 | ///
23 | /// Opens a color picker window for the user to select a color.
24 | ///
25 | /// The parent window to attach the color picker to.
26 | /// The optional default color to pre-select in the color picker.
27 | ///
28 | /// A that represents the asynchronous operation. The task result is
29 | /// the selected color if the user confirms the selection, or null if the user cancels.
30 | ///
31 | public static Task SelectColor(IPleasantWindow parent, uint? defaultColor = null)
32 | {
33 | bool cancel = true;
34 | ColorPickerWindow window = new()
35 | {
36 | ColorView =
37 | {
38 | Color = Color.FromUInt32(defaultColor ?? 0xFFFFFFFF)
39 | }
40 | };
41 |
42 | window.CancelButton.Click += (_, _) => { window.CloseAsync(); };
43 | window.OkButton.Click += (_, _) =>
44 | {
45 | cancel = false;
46 | window.CloseAsync();
47 | };
48 | window.KeyDown += (_, e) =>
49 | {
50 | if (e.Key != Key.Enter) return;
51 |
52 | cancel = false;
53 | window.CloseAsync();
54 | };
55 |
56 | TaskCompletionSource taskCompletionSource = new();
57 |
58 | window.Closed += (_, _) => { taskCompletionSource.TrySetResult(!cancel ? window.ColorView.Color : null); };
59 | window.ShowAsync(parent);
60 |
61 | return taskCompletionSource.Task;
62 | }
63 | }
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/Commands/IEditorCommand.cs:
--------------------------------------------------------------------------------
1 | namespace PleasantUI.ToolKit.Commands;
2 |
3 | ///
4 | /// Represents a command that can be executed and undone/redone in an editor context.
5 | ///
6 | public interface IEditorCommand
7 | {
8 | ///
9 | /// Undoes the command.
10 | ///
11 | void Undo();
12 |
13 | ///
14 | /// Redoes the command.
15 | ///
16 | void Redo();
17 | }
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/Commands/ThemeEditor/ColorChangeCommand.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using Avalonia.Media;
3 | using PleasantUI.ToolKit.Models;
4 |
5 | namespace PleasantUI.ToolKit.Commands.ThemeEditor;
6 |
7 | ///
8 | /// Represents a command that changes the color of a .
9 | ///
10 | public class ColorChangeCommand : IEditorCommand
11 | {
12 | private readonly Color _newColor;
13 |
14 | private readonly Color _previousColor;
15 | private readonly ResourceDictionary _resourceDictionary;
16 | private readonly ThemeColor _themeColor;
17 |
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | /// The theme color that was changed.
22 | /// The resource dictionary that contains the theme color.
23 | /// The previous color of the theme color.
24 | /// The new color of the theme color.
25 | public ColorChangeCommand(ThemeColor themeColor, ResourceDictionary resourceDictionary, Color previousColor,
26 | Color newColor)
27 | {
28 | _themeColor = themeColor;
29 | _resourceDictionary = resourceDictionary;
30 | _previousColor = previousColor;
31 | _newColor = newColor;
32 | }
33 |
34 | ///
35 | public void Undo()
36 | {
37 | _themeColor.Color = _previousColor;
38 |
39 | ChangeColorInResourceDictionary(_themeColor);
40 | }
41 |
42 | ///
43 | public void Redo()
44 | {
45 | _themeColor.Color = _newColor;
46 |
47 | ChangeColorInResourceDictionary(_themeColor);
48 | }
49 |
50 | private void ChangeColorInResourceDictionary(ThemeColor themeColor)
51 | {
52 | _resourceDictionary[themeColor.Name] = themeColor.Color;
53 | }
54 | }
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/Commands/ThemeEditor/ThemeNameChangeCommand.cs:
--------------------------------------------------------------------------------
1 | using PleasantUI.ToolKit.ViewModels;
2 |
3 | namespace PleasantUI.ToolKit.Commands.ThemeEditor;
4 |
5 | ///
6 | /// Represents a command that changes the name of the theme.
7 | ///
8 | ///
9 | public class ThemeNameChangeCommand : IEditorCommand
10 | {
11 | private readonly string _newName;
12 |
13 | private readonly string _previousName;
14 | private readonly ThemeEditorViewModel _viewModel;
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The view model.
20 | /// The previous name of the theme.
21 | /// The new name of the theme.
22 | public ThemeNameChangeCommand(ThemeEditorViewModel viewModel, string previousName, string newName)
23 | {
24 | _viewModel = viewModel;
25 | _previousName = previousName;
26 | _newName = newName;
27 | }
28 |
29 | ///
30 | public void Undo()
31 | {
32 | _viewModel.ChangeThemeName(_previousName);
33 | }
34 |
35 | ///
36 | public void Redo()
37 | {
38 | _viewModel.ChangeThemeName(_newName);
39 | }
40 | }
--------------------------------------------------------------------------------
/src/PleasantUI.ToolKit/Controls/PleasantColorView/PleasantColorView.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using Avalonia.Controls.Metadata;
3 | using Avalonia.Controls.Primitives;
4 | using Avalonia.Interactivity;
5 | using PleasantUI.Core;
6 |
7 | namespace PleasantUI.ToolKit.Controls.PleasantColorView;
8 |
9 | ///
10 | /// Represents a view for displaying a pleasant color and providing color manipulation actions.
11 | ///
12 | [TemplatePart("DeleteColor", typeof(MenuItem))]
13 | [TemplatePart("AddColorButton", typeof(Button))]
14 | public class PleasantColorView : ColorView
15 | {
16 | ///
17 | protected override Type StyleKeyOverride => typeof(ColorView);
18 |
19 | ///
20 | protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
21 | {
22 | base.OnApplyTemplate(e);
23 |
24 | MenuItem? menuItem = e.NameScope.Find