Compare commits

...

80 Commits

Author SHA1 Message Date
Zhang Dian 7f557bb2c5 feat: update window decoration styles to use transparent backgrounds. 2026-05-21 15:14:24 +08:00
Zhang Dian ec94bdd36d Integrate font management for Linux demo (#822)
* feat: integrate font management by adding Semi.Avalonia.Demo.Fonts project.

* chore: test on ubuntu.

* feat: add linux options.

* feat: update theme settings and adjust window decorations.

* feat: add font to DRM project.

* misc: net8.0->net10.0
2026-05-18 21:16:03 +08:00
Zhang Dian 331141197d Enhance DrawerPage (#813)
* feat: enhance navigation and UI structure in MainView and Application.

* fix: using ContentPreseter and add HeaderTemplate.

* feat: add locale resource for navigation drawer toggle button text.

* feat: add customizations for DrawerPageDemo.

* fix: fix DrawerPage title vertical alignment to Center.

* Update DrawerPageDemo.axaml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update DrawerPageDemo.axaml.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: fix bottom bar styles.

* fix: update border background color in DrawerPageDemo.axaml.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-30 14:53:38 +08:00
Zhang Dian b0373e9697 chore: enable CPM with single file. (#816)
* chore: enable CPM with single file.

* fix: fix copilot comments.
2026-04-30 14:37:51 +08:00
Copilot d2f789bdbd Add scheduled workflow to auto-remove old CI artifacts (#815)
* Initial plan

* Add workflow to remove old artifacts

Agent-Logs-Url: https://github.com/irihitech/Semi.Avalonia/sessions/ac7e9f88-0a15-4dfe-aae7-64cda4c5ad1e

Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com>

* ci: add workflow_dispatch trigger to remove-old-artifacts.yml.

* ci: add remove-old-artifacts.yml to solution file.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com>
Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>
2026-04-28 11:10:34 +08:00
Zhang Dian d164acea21 feat: enhance navigation and UI structure in MainView and Application. (#811)
* feat: enhance navigation and UI structure in MainView and Application.

* feat: implement singleton pattern for PaletteDemoViewModel and add initialization check

* feat: set FontWeight to Normal for navigation button in MainView

---------

Co-authored-by: Dong Bin <popmessiah@hotmail.com>
2026-04-24 19:58:27 +08:00
Copilot 1f10fd680f Add git commit message convention under .github (#789) 2026-04-24 14:48:16 +08:00
Dong Bin 480316e2f9 Change indent size for Xaml files from 2 to 4 2026-04-21 16:02:25 +08:00
rabbitism a024d2ca0e chore: fix datagrid version and bump package version 2026-04-18 16:49:25 +08:00
Copilot 18dec50bb5 Bump Avalonia version to 12.0.1 (#805)
Agent-Logs-Url: https://github.com/irihitech/Semi.Avalonia/sessions/ccdc8843-c9ae-4277-89e1-f25308ba3eaf

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com>
2026-04-18 16:44:43 +08:00
Zhang Dian 6eb871581c misc: replace QR code of community-support. 2026-04-17 12:57:11 +08:00
Zhang Dian 3807090a4b misc: follow .editorconfig from Avalonia. (#798)
* misc: follow .editorconfig from Avalonia.

* fix: remove Avalonia DevAnalyzer preferences.
2026-04-16 17:37:22 +08:00
Zhang Dian 89cdae2d39 Update AutoCompleteBox bindings and clean up project files (#802)
* fix: update ValueMemberBinding syntax for AutoCompleteBox components.

* chore: remove AvaloniaUseCompiledBindingsByDefault property from project files.

* ci: upgrade draft release version.
2026-04-15 17:01:28 +08:00
Zhang Dian 555ecf16d9 Add icons to TabbedPage content and improve layout. (#801)
* fix: add icons to TabbedPage content and improve layout.

* fix: only update Placement=Top/Bottom in TabbedPage.
2026-04-13 22:46:53 +08:00
Zhang Dian 49ee1c12cc fix: fix workflow_call secrets issue. 2026-04-10 14:56:12 +08:00
Zhang Dian 4447475f18 chore: bump ColorPicker & DataGrid version to 12.0.0. 2026-04-08 01:00:05 +08:00
Zhang Dian e53e744d1f Refactor ColorPicker components and improve UI consistency (#795)
* feat: add converters and update bindings in ColorPicker components.

* feat: simplify ColorPicker layout by replacing complex structure with ColorView component.

* feat: remove CornerRadiusToDoubleConverter.

* feat: replace EnumToBoolConverter & ToColorModel with ObjectConverters.Equal.

* feat: set HexInputAlphaPosition to Trailing.

* feat: update ColorView layout and styling for improved UI consistency.

* feat: bind Increment property of ColorSliders to respective TickFrequency and Slider values.

* feat: update ColorView bindings to use new syntax and adjust CornerRadius for improved styling.

* feat: update ColorPicker SelectedIndex Mode to TwoWay.

* feat: sync upstream changes.

* feat: update ColorPicker and ColorView to use SemiColorPalette for improved color selection.

* feat: update ControlTemplate TargetType.

* feat: add AIPurple colors to Palette.

* refactor: display real Hex in HexColorPicker.

* fix: update ColorView bindings to handle null values with a converter.

* refactor: refactor ColorPicker demo.

* refactor: replace RelativeSource bindings with TemplateBinding in ColorView.

* chore: copy ColorView Template to ColorPicker.

* fix: update AlphaEnabled ToggleSwitch content to reflect correct label.

* fix: fix index order in ColorPicker.
2026-04-08 00:55:03 +08:00
Zhang Dian 6eaa47e7ce chore: bump version to 12.0.0. 2026-04-08 00:09:46 +08:00
Zhang Dian 1edc65c091 Remove obsolete resources. (#792) 2026-04-08 00:03:22 +08:00
Dong Bin 1348149957 Update Drawer to match upstream design (#790)
* feat: update DrawerPage and related resources for improved layout and functionality

* feat: enable mouse swipe gesture for Drawer control.

* chore: remove useless resources.

* chore: remove useless Style.

* chore: using TemplateBinding.

* fix: using InnerPathIcon theme for Icon.

* fix: use normal Binding.

---------

Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>
2026-04-07 23:56:17 +08:00
Zhang Dian 3b4443cd54 Fix CarouselPage ControlTemplate and sync NavigationPage template (#791)
* fix: specify TargetType in ControlTemplate for CarouselPage and remove redundant ItemsSource bindings in TabbedPage.

* feat: sync ContentPage with Avalonia Fluent version.

* fix: sync upstream NavigationPage template.

* feat: adjust NavigationPage bar height and add large style support

* feat: add ToggleSwitch for large style support in NavigationPageDemo

---------

Co-authored-by: Dong Bin <popmessiah@hotmail.com>
2026-04-07 23:53:11 +08:00
Zhang Dian 35bea6ff1f feat: add maximize2 and restore icons. 2026-04-07 21:30:36 +08:00
Zhang Dian c393d41112 chore: upgrade version to Avalonia 12.0.0. 2026-04-07 21:29:32 +08:00
Zhang Dian d4c4ef1dba Merge branch '12.0.0-rc2' 2026-04-07 21:14:20 +08:00
Zhang Dian 35b62fe3af chore: bump version to 12.0.0-rc2. 2026-04-07 11:56:21 +08:00
Zhang Dian c48d96e40f Sync Avalonia 12.0.0-rc2 changes (#786)
* chore: AppBar -> CommanrBar.

* feat: Add keyboard navigation for overflow CommandBar popup.

* chore: Style -> Theme in PipsPager.

* chore: add Header/Footer templates to DrawerPage.

* feaa: hide caption buttons when the platform does not support the action.

* feat: Touch Improvements to TextBox.

* chore: remove Opacity from PART_Placeholder.

* feat: enable access key recognition for GroupBox.

* feat: limit label text to a single line in CommandBar.
2026-04-01 23:01:45 +08:00
Zhang Dian c128feb4ff Refactor ProgressBar styles for improved layout and animation (#750)
* refactor: refactor ProgressBar styles for improved layout and animation.

* fix: set MinHeight for ProgressBar text part.

* chore: remove useless Progress resources.
2026-04-01 18:05:01 +08:00
Zhang Dian 48c3837d81 chore: upgrade to Avalonia 12.0.0-rc2. 2026-04-01 11:28:01 +08:00
Zhang Dian f22709fcb1 Update CaptionButtonForeground resource and WindowDrawnDecorations layout (#779)
* fix: update CaptionButtonForeground resource key and remove cursor setter.

* fix: update WindowDrawnDecorations layout.

* feat: add CaptionButtonDisabledForeground for disabled state and WindowCustomizationsPage.
2026-03-26 14:15:47 +08:00
Zhang Dian 0fbcf43309 feat: update TabItem with icon. (#778) 2026-03-25 19:51:23 +08:00
Zhang Dian a1bda0d2d9 fix: remove ExtendClientAreaTitleBarHeightHint from MainWindow.axaml. 2026-03-25 14:57:45 +08:00
Zhang Dian 52cc3887b1 feat: add MaximizeGlyph & RestoreGlyph. (#777) 2026-03-24 14:12:33 +08:00
Copilot 9cf27b3906 Add SplitButtonSpinner theme for ButtonSpinner and NumericUpDown (#776)
* Initial plan

* Add SplitButtonSpinner theme for ButtonSpinner

Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com>
Agent-Logs-Url: https://github.com/irihitech/Semi.Avalonia/sessions/7095fb6c-cdd9-48c0-9076-85a35fa93453

* feat: enhance ButtonSpinner and NumericUpDown with new styles and properties.

* fix: fix Glyph and enlarge icons.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rabbitism <14807942+rabbitism@users.noreply.github.com>
Co-authored-by: Dong Bin <popmessiah@hotmail.com>
Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>
2026-03-23 17:20:41 +08:00
Zhang Dian bfb3dd671b Add fullscreen toggle functionality and update popover alignment (#773)
* fix: update Height binding and add VerticalAlignment to fullscreen popover.

* feat: add fullscreen toggle functionality with F11 key.
2026-03-21 22:21:23 +08:00
Zhang Dian 665dca3bd3 fix: fix the draft release version tag. 2026-03-21 18:18:49 +08:00
Zhang Dian f5e56511ac chore: bump to 12.0.0-rc1. 2026-03-21 18:08:48 +08:00
Dong Bin b3b7459088 Pr3/carousel page (#772)
* feat: add CarouselPage and PipsPager.

* feat: add PipsPager control and integrate into index

* feat: add PipsPagerDemo and integrate into MainView

---------

Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>
2026-03-21 17:58:35 +08:00
Zhang Dian 96f7f3d1e1 Adjust Resource Structure (#771)
* chore: update GitHub Actions to use latest versions of actions.

* feat: update theme resource structure and remove Schemes.

* refactor: simplify locale resource handling and remove redundant code.

* feat: add Light theme resource to ColorPicker and DataGrid semi themes.

* feat: replace SetResources with BulkSetResources.
2026-03-21 17:57:56 +08:00
Zhang Dian 64e2b50a1d fix: add ContentTemplate binding for DrawerIcon in DrawerPage.axaml. 2026-03-20 15:47:53 +08:00
Zhang Dian fbfe5b0b6a fix: add Name to VisualLayerManager for 12.0.0-rc1. 2026-03-20 15:11:30 +08:00
Zhang Dian bd4d4e2096 chore: update package versions to 12.0.0-rc1. 2026-03-20 15:05:00 +08:00
Dong Bin 01e213d741 Implement DataGrid V12 (#770)
* feat: bring datagrid demo back.

* feat: add FunctionalColorGroupControl and ShadowGroupControl with data binding

* Add 10 TFM

Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>

* feat: Use new property

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: fix changelog.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: fix sort member path.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: remove useless property.

---------

Co-authored-by: Zhang Dian <54255897+zdpcdt@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-19 13:28:13 +08:00
Zhang Dian 87fed4febd chore: bump to 12.0.0-preview2. 2026-03-15 22:09:39 +08:00
Zhang Dian 646272dc21 Fix Android Demo Issues (#767)
* fix: fix android demo issues.

* feat: enable CoreCLR usage on Android.
2026-03-15 22:09:39 +08:00
Zhang Dian 672560643b fix: Watermark -> Placeholder. (#769) 2026-03-15 03:40:20 +08:00
Zhang Dian d6d03133b4 feat: refactor WindowDrawnDecorations with new styling and structure. (#768) 2026-03-15 03:39:24 +08:00
Copilot 1d59cff87d Implement Semi Design theme for page-based navigation controls (ContentPage / DrawerPage / NavigationPage / TabbedPage) (#766)
* Initial plan

* Implement Semi Design theme for ContentPage, DrawerPage, NavigationPage, TabbedPage

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* fix: bind ItemsSource to Pages in TabControl of TabbedPage.

* chore: split demo navigation pages.

* demo: improve NavigationPage demo pages with interactive controls

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* fix: use comma-separated Padding syntax and remove trailing newline

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* feat: implement semi design theme for navigation controls in demo pages.

* feat: enhance demo pages with foreground color for better visibility

* feat: add back button visibility control and improve navigation page layout.

* chore: remove DrawerPage unused static resources.

* feat: add HighContrast resources for ContentPage, DrawerPage, NavigationPage, TabbedPage

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* feat: implement CardTabbedPage & ButtonTabbedPage themes.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>
Co-authored-by: Dong Bin <popmessiah@hotmail.com>
2026-03-15 03:37:50 +08:00
Zhang Dian 141eeefd2e Sync upstream update. (#764) 2026-03-13 18:38:00 +08:00
Zhang Dian c84c8a3c90 fix: fix :checked:disabled color in AppBarToggleButton. 2026-03-12 16:34:24 +08:00
Zhang Dian dd5f5182fa fix CommandBar issues (#763)
* feat: extract shared theme from AppBarButton & AppBarToggleButton.

* feat: enhance CommandBar with dynamic overflow and adjustable width.

* fix: fix Width in IsCompact mode.
2026-03-12 15:56:39 +08:00
Zhang Dian d865f2aeb4 chore: enable developer tools in debug mode and update diagnostics package references. 2026-03-10 19:07:27 +08:00
Copilot 44152ef731 Sync 45 new icons from Semi Design commit ba384587 (#761)
* Initial plan

* Sync 45 new icons from Semi Design commit ba384587

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* fix: correct geometry paths for Semi icons.

* fix: update EyeClosedSolidStroked & IconHornStroked paths for Semi icons in StrokedIcons.axaml.

* fix: resolve copilot review.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>
(cherry picked from commit 77dffc55b1)
2026-03-10 16:49:34 +08:00
Zhang Dian 25f75d605c feat: add Semi theme styling for CommandBar, AppBarButton, AppBarTogg… (#759)
* feat: add Semi theme styling for CommandBar, AppBarButton, AppBarToggleButton, AppBarSeparator

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* feat: add Semi theme icons for CommandBar buttons and update styles.

* feat: add dynamic label position selection to CommandBar demo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-03-10 16:49:03 +08:00
Copilot 77dffc55b1 Sync 45 new icons from Semi Design commit ba384587 (#761)
* Initial plan

* Sync 45 new icons from Semi Design commit ba384587

Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>

* fix: correct geometry paths for Semi icons.

* fix: update EyeClosedSolidStroked & IconHornStroked paths for Semi icons in StrokedIcons.axaml.

* fix: resolve copilot review.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zdpcdt <54255897+zdpcdt@users.noreply.github.com>
2026-03-10 14:42:21 +08:00
Dong Bin c144056ab0 feat: add basic implementation of window decorations. 2026-03-08 23:33:23 +08:00
Zhang Dian 65e4d0d4a4 feat: upgrade Avalonia to 12.0.0-preview2. 2026-03-06 15:09:57 +08:00
Gehongyan 3ba357b691 Fix TextBox MaxLines property not constraining height in Semi theme (#753)
* Initial plan

* Fix TextBox MaxLines property by adding Name=PART_ScrollViewer to ScrollViewer elements

Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-03-05 23:16:29 +08:00
rabbitism de3ffc97b6 chore: bump to 12.0 preview 2026-02-18 11:04:28 +08:00
Zhang Dian 7da8a03f84 chore: add Avalonia Nightly repo
(cherry picked from commit 3e03cf32b5a071879315c9742aea5831339e41b9)
2026-02-18 11:04:28 +08:00
Zhang Dian ab03be1aea misc: bump nightly version. 2026-02-18 11:04:28 +08:00
Zhang Dian 4ec2d0cf86 Update AutoCompleteBox style to use ClassHelper for Bordered TextBox (#747)
* feat: update AutoCompleteBox style to use ClassHelper for Bordered TextBox.

* Update src/Semi.Avalonia/Controls/AutoCompleteBox.axaml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: unitize Bordered style selectors.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-18 11:04:23 +08:00
Dong Bin 757f91a140 Implement PlaceholderText (#727)
* feat: replace Watermark with PlaceholderText in AutoCompleteBox and related controls

* fix: remove duplicate PlaceholderForeground setter.
2026-02-18 11:04:01 +08:00
Zhang Dian f6d068b722 adjust CornerRadius & MinWidth for SplitButton (#725)
* feat: support CornerRadius for SplitButton.

* Update src/Semi.Avalonia/Controls/SplitButton.axaml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: refactor SplitButton layout to use Grid for better structure.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-18 11:04:01 +08:00
Zhang Dian 3a6452cccd misc: update XML namespace references and converters in XAML files. (#726) 2026-02-18 11:04:01 +08:00
Zhang Dian 5ea834d57e chore: fix conflict typos. 2026-02-18 11:04:01 +08:00
Zhang Dian 1d9fe693a3 misc: add SemiBorderRadiusSpacingExtraSmall for tokens. 2026-02-18 11:04:01 +08:00
Zhang Dian 2b867f9c6f misc: remove useless theme. 2026-02-18 11:04:00 +08:00
Zhang Dian 5ea42844ea misc: using AvaloniaUseCompiledBindingsByDefault. 2026-02-18 11:04:00 +08:00
Zhang Dian f819531465 feat: colorpicker reference Shared package. 2026-02-18 11:04:00 +08:00
Zhang Dian 8f24b2f332 feat: add GroupBox. 2026-02-18 11:04:00 +08:00
Zhang Dian a309729c11 chore: ready for 12.0.x. 2026-02-18 11:03:55 +08:00
Zhang Dian d57c843032 misc: bump version. 2026-02-09 23:54:05 +08:00
Zhang Dian a56b1e374a fix: update TextBox padding for improved layout consistency. (#748) 2026-02-09 23:29:28 +08:00
Zhang Dian 664d05db45 feat: add ClearSelectionOnLostFocus property to AutoCompleteBox. (#746) 2026-02-09 23:28:15 +08:00
Zhang Dian fdbfd91b8f feat: Properly handle nc hit test for caption buttons. (#745) 2026-02-09 21:33:12 +08:00
Zhang Dian 3b0b007a40 fix: reverse TickBar when Slider direction is reversed. (#744) 2026-02-09 18:29:13 +08:00
Zhang Dian c1eff9ddf8 fix: add AutomationProperties names to ScrollViewer controls. (#738) 2026-02-09 15:17:21 +08:00
xoma-zver 4285e6e227 feat: add Inter font resource reference to SemiFontFamilyRegular (#722) 2026-02-09 14:51:29 +08:00
Zhang Dian edacd88fa7 fix: update MenuFlyout to use ShowMode for context menus in SelectableTextBlock and TextBox (#739) 2026-02-09 14:46:29 +08:00
Zhang Dian 136d577667 fix: fix DatePicker & TimePicker to respect custom Width property. (#737) 2026-02-09 14:45:17 +08:00
229 changed files with 5209 additions and 2970 deletions
+240
View File
@@ -0,0 +1,240 @@
# 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
# trim_trailing_whitespace = 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
# private static fields should have s_ prefix
dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
dotnet_naming_style.private_static_prefix_style.required_prefix = s_
dotnet_naming_style.private_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 = false
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
space_within_single_line_array_initializer_braces = true
#Net Analyzer
dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
# CA1018: Mark attributes with AttributeUsageAttribute
dotnet_diagnostic.CA1018.severity = warning
# CA1304: Specify CultureInfo
dotnet_diagnostic.CA1304.severity = warning
# CA1802: Use literals where appropriate
dotnet_diagnostic.CA1802.severity = warning
# CA1813: Avoid unsealed attributes
dotnet_diagnostic.CA1813.severity = warning
# CA1815: Override equals and operator equals on value types
dotnet_diagnostic.CA1815.severity = warning
# CA1820: Test for empty strings using string length
dotnet_diagnostic.CA1820.severity = warning
# CA1821: Remove empty finalizers
dotnet_diagnostic.CA1821.severity = warning
# CA1822: Mark members as static
dotnet_diagnostic.CA1822.severity = suggestion
dotnet_code_quality.CA1822.api_surface = private, internal
# CA1823: Avoid unused private fields
dotnet_diagnostic.CA1823.severity = warning
# CA1825: Avoid zero-length array allocations
dotnet_diagnostic.CA1825.severity = warning
# CA1826: Use property instead of Linq Enumerable method
dotnet_diagnostic.CA1826.severity = suggestion
# CA1827: Do not use Count/LongCount when Any can be used
dotnet_diagnostic.CA1827.severity = warning
# CA1828: Do not use CountAsync/LongCountAsync when AnyAsync can be used
dotnet_diagnostic.CA1828.severity = warning
# CA1829: Use Length/Count property instead of Enumerable.Count method
dotnet_diagnostic.CA1829.severity = warning
#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
dotnet_diagnostic.CA1847.severity = warning
# CA1851: Possible multiple enumerations of IEnumerable collection
dotnet_diagnostic.CA1851.severity = warning
#CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
dotnet_diagnostic.CA1854.severity = warning
#CA2211:Non-constant fields should not be visible
dotnet_diagnostic.CA2211.severity = warning
# Wrapping preferences
csharp_wrap_before_ternary_opsigns = false
# Avalonia PublicAnalyzer preferences
dotnet_diagnostic.AVP1000.severity = warning
dotnet_diagnostic.AVP1001.severity = warning
dotnet_diagnostic.AVP1002.severity = warning
dotnet_diagnostic.AVP1010.severity = warning
dotnet_diagnostic.AVP1011.severity = warning
dotnet_diagnostic.AVP1012.severity = warning
dotnet_diagnostic.AVP1013.severity = warning
dotnet_diagnostic.AVP1020.severity = warning
dotnet_diagnostic.AVP1021.severity = warning
dotnet_diagnostic.AVP1022.severity = warning
dotnet_diagnostic.AVP1030.severity = warning
dotnet_diagnostic.AVP1031.severity = warning
dotnet_diagnostic.AVP1032.severity = warning
dotnet_diagnostic.AVP1040.severity = warning
dotnet_diagnostic.AVA2001.severity = warning
# Xaml files
[*.{xaml,axaml}]
indent_size = 4
# DuplicateSetterError
avalonia_xaml_diagnostic.AVLN2203.severity = warning
# StyleInMergedDictionaries
avalonia_xaml_diagnostic.AVLN2204.severity = warning
# RequiredTemplatePartMissing
avalonia_xaml_diagnostic.AVLN2205.severity = warning
# OptionalTemplatePartMissing
avalonia_xaml_diagnostic.AVLN2206.severity = info
# TemplatePartWrongType
avalonia_xaml_diagnostic.AVLN2207.severity = warning
# ItemContainerInsideTemplate
avalonia_xaml_diagnostic.AVLN2208.severity = warning
# Obsolete
avalonia_xaml_diagnostic.AVLN5001.severity = warning
# 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
[*.json]
indent_size = 2
# Shell scripts
[*.sh]
end_of_line = lf
[*.{cmd,bat}]
end_of_line = crlf
+92
View File
@@ -0,0 +1,92 @@
# Git Commit Message Convention
This project follows the [Conventional Commits](https://www.conventionalcommits.org/) specification for commit messages.
## Format
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
## Types
| Type | Description |
|------|-------------|
| `feat` | A new feature |
| `fix` | A bug fix |
| `docs` | Documentation only changes |
| `style` | Changes that do not affect the meaning of the code (formatting, missing semicolons, etc.) |
| `refactor` | A code change that neither fixes a bug nor adds a feature |
| `perf` | A code change that improves performance |
| `test` | Adding missing tests or correcting existing tests |
| `build` | Changes that affect the build system or external dependencies |
| `ci` | Changes to CI configuration files and scripts |
| `chore` | Other changes that don't modify source or test files |
| `revert` | Reverts a previous commit |
## Rules
1. **Limit the subject line to 50 characters** (72 character hard limit)
2. **Use the imperative mood** in the subject line (e.g., "add feature" not "added feature")
3. **Do not end the subject line with a period**
4. **Use lowercase** for the description (e.g., "add feature" not "Add feature")
5. **Separate subject from body with a blank line**
6. **Wrap the body at 72 characters**
7. **Use the body to explain what and why**, not how
8. **Reference issues and pull requests** in the footer
## Scope
The scope should be the name of the package or area affected (e.g., `button`, `datepicker`, `theme`, `demo`).
## Examples
### Simple commit
```
feat(button): add loading state support
```
### Commit with body
```
fix(datepicker): correct month navigation overflow
When navigating past December, the month index wrapped to a
negative value instead of rolling over to January of the next year.
```
### Commit with breaking change
```
feat(theme)!: rename SemiColorPrimary to SemiColorBrand
BREAKING CHANGE: The token SemiColorPrimary has been renamed to
SemiColorBrand. Update all references in your custom theme files.
```
### Commit referencing an issue
```
fix(textbox): placeholder not visible in dark mode
Closes #123
```
## Breaking Changes
Breaking changes must be indicated by appending a `!` after the type/scope, or by including a `BREAKING CHANGE:` footer. Both methods may be used together.
## Revert Commits
When reverting a previous commit, use the `revert` type and reference the reverted commit SHA in the footer:
```
revert: feat(button): add loading state support
Revert commit a1b2c3d.
```
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v5 uses: actions/setup-dotnet@v5
@@ -32,7 +32,7 @@ jobs:
run: touch $OUTPUT_PATH/.nojekyll run: touch $OUTPUT_PATH/.nojekyll
- name: Commit wwwroot to GitHub Pages - name: Commit wwwroot to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4.5.0 uses: JamesIves/github-pages-deploy-action@v4
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages branch: gh-pages
+3 -3
View File
@@ -6,7 +6,7 @@ on:
Version_Prefix: Version_Prefix:
description: 'Version Prefix' description: 'Version Prefix'
required: true required: true
default: '11.2.999' default: '12.0.999'
type: string type: string
Semi_Avalonia: Semi_Avalonia:
description: 'Pack Semi.Avalonia' description: 'Pack Semi.Avalonia'
@@ -31,7 +31,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Get Version - name: Get Version
run: | run: |
@@ -62,7 +62,7 @@ jobs:
run: dotnet nuget push "nugets/*.nupkg" --api-key ${{ secrets.IRIHI_NUGET_API_KEY }} --source irihi.tech --skip-duplicate run: dotnet nuget push "nugets/*.nupkg" --api-key ${{ secrets.IRIHI_NUGET_API_KEY }} --source irihi.tech --skip-duplicate
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: nugets name: nugets
path: nugets path: nugets
+3 -2
View File
@@ -40,6 +40,7 @@ on:
Semi_Avalonia_TreeDataGrid: Semi_Avalonia_TreeDataGrid:
type: boolean type: boolean
default: true default: true
secrets: {}
jobs: jobs:
Pack_to_NuGet: Pack_to_NuGet:
@@ -47,7 +48,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Pack Semi.Avalonia - name: Pack Semi.Avalonia
if: ${{ inputs.Semi_Avalonia }} if: ${{ inputs.Semi_Avalonia }}
@@ -70,7 +71,7 @@ jobs:
run: dotnet nuget push "nugets/*.nupkg" --api-key ${{ secrets.NUGET_ORG_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate run: dotnet nuget push "nugets/*.nupkg" --api-key ${{ secrets.NUGET_ORG_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: nugets name: nugets
path: nugets path: nugets
+18 -18
View File
@@ -75,11 +75,11 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Publish win-x64 - name: Publish win-x64
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r win-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r win-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.win-x64 name: Semi.Avalonia.Demo.Desktop.win-x64
path: | path: |
@@ -91,13 +91,13 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Enable Native AOT in .csproj - name: Enable Native AOT in .csproj
run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj
- name: Publish win-x64 AOT - name: Publish win-x64 AOT
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r win-x64 -c Release -o publish run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r win-x64 -c Release -o publish
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.win-x64.NativeAOT name: Semi.Avalonia.Demo.Desktop.win-x64.NativeAOT
path: | path: |
@@ -109,11 +109,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Publish linux-x64 - name: Publish linux-x64
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r linux-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r linux-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.linux-x64 name: Semi.Avalonia.Demo.Desktop.linux-x64
path: | path: |
@@ -125,13 +125,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Enable Native AOT in .csproj - name: Enable Native AOT in .csproj
run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj
- name: Publish linux-x64 AOT - name: Publish linux-x64 AOT
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r linux-x64 -c Release -o publish run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r linux-x64 -c Release -o publish
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.linux-x64.NativeAOT name: Semi.Avalonia.Demo.Desktop.linux-x64.NativeAOT
path: | path: |
@@ -143,11 +143,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Publish linux-x64 DRM - name: Publish linux-x64 DRM
run: dotnet publish demo/Semi.Avalonia.Demo.Drm -r linux-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true run: dotnet publish demo/Semi.Avalonia.Demo.Drm -r linux-x64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Drm.linux-x64 name: Semi.Avalonia.Demo.Drm.linux-x64
path: | path: |
@@ -159,13 +159,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Enable Native AOT in .csproj - name: Enable Native AOT in .csproj
run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Drm/Semi.Avalonia.Demo.Drm.csproj run: sed -i 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Drm/Semi.Avalonia.Demo.Drm.csproj
- name: Publish linux-x64 AOT - name: Publish linux-x64 AOT
run: dotnet publish demo/Semi.Avalonia.Demo.Drm -r linux-x64 -c Release -o publish run: dotnet publish demo/Semi.Avalonia.Demo.Drm -r linux-x64 -c Release -o publish
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Drm.linux-x64.NativeAOT name: Semi.Avalonia.Demo.Drm.linux-x64.NativeAOT
path: | path: |
@@ -177,11 +177,11 @@ jobs:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Publish osx-arm64 - name: Publish osx-arm64
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r osx-arm64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r osx-arm64 -c Release -o publish --sc /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.osx-arm64 name: Semi.Avalonia.Demo.Desktop.osx-arm64
path: | path: |
@@ -193,13 +193,13 @@ jobs:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Enable Native AOT in .csproj - name: Enable Native AOT in .csproj
run: sed -i '' 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj run: sed -i '' 's#<!--<PublishAot>true</PublishAot>-->#<PublishAot>true</PublishAot>#' demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj
- name: Publish osx-arm64 AOT - name: Publish osx-arm64 AOT
run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r osx-arm64 -c Release -o publish run: dotnet publish demo/Semi.Avalonia.Demo.Desktop -r osx-arm64 -c Release -o publish
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: Semi.Avalonia.Demo.Desktop.osx-arm64.NativeAOT name: Semi.Avalonia.Demo.Desktop.osx-arm64.NativeAOT
path: | path: |
@@ -211,7 +211,7 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Install Android workload - name: Install Android workload
run: dotnet workload install android run: dotnet workload install android
- name: Restore Dependencies - name: Restore Dependencies
@@ -219,7 +219,7 @@ jobs:
- name: Publish Android - name: Publish Android
run: dotnet publish demo/Semi.Avalonia.Demo.Android -c Release -f net10.0-android --no-restore -o publish /p:RuntimeIdentifier=android-arm64 run: dotnet publish demo/Semi.Avalonia.Demo.Android -c Release -f net10.0-android --no-restore -o publish /p:RuntimeIdentifier=android-arm64
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.2 uses: actions/upload-artifact@v7
with: with:
name: android-arm64 name: android-arm64
path: publish/*Signed.apk path: publish/*Signed.apk
+3 -2
View File
@@ -33,6 +33,7 @@ jobs:
Semi_Avalonia_ColorPicker: ${{ inputs.Semi_Avalonia_ColorPicker }} Semi_Avalonia_ColorPicker: ${{ inputs.Semi_Avalonia_ColorPicker }}
Semi_Avalonia_DataGrid: ${{ inputs.Semi_Avalonia_DataGrid }} Semi_Avalonia_DataGrid: ${{ inputs.Semi_Avalonia_DataGrid }}
Semi_Avalonia_TreeDataGrid: ${{ inputs.Semi_Avalonia_TreeDataGrid }} Semi_Avalonia_TreeDataGrid: ${{ inputs.Semi_Avalonia_TreeDataGrid }}
secrets: inherit
publish: publish:
uses: ./.github/workflows/publish.yml uses: ./.github/workflows/publish.yml
@@ -41,7 +42,7 @@ jobs:
needs: [ nuget,publish ] needs: [ nuget,publish ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v4.3.0 - uses: actions/download-artifact@v8
- name: Display structure of downloaded files - name: Display structure of downloaded files
run: ls -R run: ls -R
@@ -62,7 +63,7 @@ jobs:
run: ls -R run: ls -R
- name: Release - name: Release
uses: softprops/action-gh-release@v2.3.2 uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
with: with:
generate_release_notes: true generate_release_notes: true
@@ -0,0 +1,25 @@
name: Remove old artifacts
on:
schedule:
# Every day at 1am
- cron: '0 1 * * *'
workflow_dispatch:
jobs:
remove-old-artifacts:
runs-on: ubuntu-latest
timeout-minutes: 10
# For private repos
permissions:
actions: write
steps:
- name: Remove old artifacts
uses: c-hive/gha-remove-artifacts@v1
with:
age: '15 days' # '<number> <unit>', e.g. 5 days, 2 years, 90 seconds, parsed by Moment.js
# Optional inputs
skip-tags: true
skip-recent: 5
+26
View File
@@ -0,0 +1,26 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageVersionOverrideEnabled>true</CentralPackageVersionOverrideEnabled>
<AvaloniaVersion>12.0.1</AvaloniaVersion>
<DataGridVersion>12.0.0</DataGridVersion>
</PropertyGroup>
<ItemGroup>
<!--src-->
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(DataGridVersion)"/>
<PackageVersion Include="Avalonia.Controls.TreeDataGrid" Version="11.1.1"/>
<PackageVersion Include="Irihi.Avalonia.Shared" Version="0.4.0"/>
<!--demo-->
<PackageVersion Include="Avalonia.Android" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Browser" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.iOS" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.LinuxFramebuffer" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1"/>
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2"/>
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0.2"/>
</ItemGroup>
</Project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="avalonia-nightly" value="https://nuget-feed-nightly.avaloniaui.net/v3/index.json" />
</packageSources>
</configuration>
+9 -3
View File
@@ -3,6 +3,7 @@
<Project Path="demo/Semi.Avalonia.Demo.Android/Semi.Avalonia.Demo.Android.csproj"/> <Project Path="demo/Semi.Avalonia.Demo.Android/Semi.Avalonia.Demo.Android.csproj"/>
<Project Path="demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj"/> <Project Path="demo/Semi.Avalonia.Demo.Desktop/Semi.Avalonia.Demo.Desktop.csproj"/>
<Project Path="demo/Semi.Avalonia.Demo.Drm/Semi.Avalonia.Demo.Drm.csproj"/> <Project Path="demo/Semi.Avalonia.Demo.Drm/Semi.Avalonia.Demo.Drm.csproj"/>
<Project Path="demo/Semi.Avalonia.Demo.Fonts/Semi.Avalonia.Demo.Fonts.csproj"/>
<Project Path="demo/Semi.Avalonia.Demo.Web/Semi.Avalonia.Demo.Web.csproj"/> <Project Path="demo/Semi.Avalonia.Demo.Web/Semi.Avalonia.Demo.Web.csproj"/>
<Project Path="demo/Semi.Avalonia.Demo/Semi.Avalonia.Demo.csproj"/> <Project Path="demo/Semi.Avalonia.Demo/Semi.Avalonia.Demo.csproj"/>
</Folder> </Folder>
@@ -12,13 +13,18 @@
<File Path=".github/workflows/pack.yml"/> <File Path=".github/workflows/pack.yml"/>
<File Path=".github/workflows/publish.yml"/> <File Path=".github/workflows/publish.yml"/>
<File Path=".github/workflows/release-tag.yml"/> <File Path=".github/workflows/release-tag.yml"/>
<File Path=".github/workflows/remove-old-artifacts.yml"/>
</Folder>
<Folder Name="/Solution Items/">
<File Path="Directory.Packages.props"/>
<File Path="global.json"/>
<File Path="Nuget.Config"/>
</Folder> </Folder>
<Folder Name="/Solution Items/Demo/"> <Folder Name="/Solution Items/Demo/">
<File Path="demo/Directory.Packages.props"/> <File Path="demo/Directory.Build.targets"/>
<File Path="demo/global.json"/> <File Path="demo/global.json"/>
</Folder> </Folder>
<Folder Name="/Solution Items/Package/"> <Folder Name="/Solution Items/Src/">
<File Path="src/Directory.Packages.props"/>
<File Path="src/Directory.Build.props"/> <File Path="src/Directory.Build.props"/>
</Folder> </Folder>
<Project Path="src/Semi.Avalonia.ColorPicker/Semi.Avalonia.ColorPicker.csproj"/> <Project Path="src/Semi.Avalonia.ColorPicker/Semi.Avalonia.ColorPicker.csproj"/>
+17
View File
@@ -0,0 +1,17 @@
<Project>
<PropertyGroup>
<AvaloniaVersion>12.0.2</AvaloniaVersion>
<DataGridVersion>12.0.0</DataGridVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Update="Avalonia" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.Android" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.Browser" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.Desktop" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.iOS" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.LinuxFramebuffer" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.Controls.ColorPicker" VersionOverride="$(AvaloniaVersion)"/>
<PackageReference Update="Avalonia.Controls.DataGrid" VersionOverride="$(DataGridVersion)"/>
</ItemGroup>
</Project>
-27
View File
@@ -1,27 +0,0 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<AvaloniaVersion>11.3.10</AvaloniaVersion>
<DataGridVersion>11.3.10</DataGridVersion>
<SkiaSharpVersion>3.119.1</SkiaSharpVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.LinuxFramebuffer" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.iOS" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Browser" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Android" Version="$(AvaloniaVersion)" />
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(DataGridVersion)"/>
<PackageVersion Include="SkiaSharp" Version="$(SkiaSharpVersion)"/>
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="$(SkiaSharpVersion)"/>
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0"/>
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
<PackageVersion Include="Irihi.Avalonia.Shared" Version="0.3.1"/>
</ItemGroup>
</Project>
@@ -0,0 +1,21 @@
using Android.App;
using Android.Runtime;
using Avalonia;
using Avalonia.Android;
using Semi.Avalonia.Demo.Fonts;
namespace Semi.Avalonia.Demo.Android;
[Application]
public class Application : AvaloniaAndroidApplication<App>
{
protected Application(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.WithSourceHanSansCNFont();
}
}
@@ -1,16 +0,0 @@
using Avalonia;
using Avalonia.Media;
namespace Semi.Avalonia.Demo.Android;
public static class AvaloniaAppBuilderExtensions
{
private static string DefaultFontFamily => "avares://Semi.Avalonia.Demo.Android/Assets#Source Han Sans CN";
public static AppBuilder WithSourceHanSansCNFont(this AppBuilder builder) =>
builder.With(new FontManagerOptions
{
DefaultFamilyName = DefaultFontFamily,
FontFallbacks = [new FontFallback { FontFamily = new FontFamily(DefaultFontFamily) }]
});
}
@@ -1,6 +1,5 @@
using Android.App; using Android.App;
using Android.Content.PM; using Android.Content.PM;
using Avalonia;
using Avalonia.Android; using Avalonia.Android;
namespace Semi.Avalonia.Demo.Android; namespace Semi.Avalonia.Demo.Android;
@@ -12,11 +11,4 @@ namespace Semi.Avalonia.Demo.Android;
MainLauncher = true, MainLauncher = true,
LaunchMode = LaunchMode.SingleTop, LaunchMode = LaunchMode.SingleTop,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App> public class MainActivity : AvaloniaMainActivity;
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.WithSourceHanSansCNFont();
}
}
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net10.0-android</TargetFramework> <TargetFramework>net10.0-android</TargetFramework>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion> <SupportedOSPlatformVersion>23</SupportedOSPlatformVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ApplicationId>com.irihitech.Semi.Avalonia</ApplicationId> <ApplicationId>com.irihitech.Semi.Avalonia</ApplicationId>
<ApplicationVersion>1</ApplicationVersion> <ApplicationVersion>1</ApplicationVersion>
@@ -13,9 +13,14 @@
<RootNamespace>Semi.Avalonia.Demo.Android</RootNamespace> <RootNamespace>Semi.Avalonia.Demo.Android</RootNamespace>
</PropertyGroup> </PropertyGroup>
<!-- Use CoreCLR on Android -->
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<UseMonoRuntime>false</UseMonoRuntime>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Icon.png" Link="Resources\drawable\Icon.png"/> <AndroidResource Include="Icon.png" Link="Resources\drawable\Icon.png"/>
<AvaloniaResource Include="..\Fonts\*" Link="Assets\Fonts\%(Filename)%(Extension)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -25,5 +30,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/> <ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/>
<ProjectReference Include="..\Semi.Avalonia.Demo.Fonts\Semi.Avalonia.Demo.Fonts.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
+20 -14
View File
@@ -2,8 +2,10 @@
using Avalonia; using Avalonia;
using Avalonia.Dialogs; using Avalonia.Dialogs;
using Avalonia.Media; using Avalonia.Media;
using Semi.Avalonia.Demo.Fonts;
namespace Semi.Avalonia.Demo.Desktop; namespace Semi.Avalonia.Demo.Desktop;
#pragma warning disable CA1416, AVALONIA_X11_CSD, AVALONIA_X11_FORCE_CSD
sealed class Program sealed class Program
{ {
@@ -11,24 +13,28 @@ sealed class Program
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break. // yet and stuff might break.
[STAThread] [STAThread]
public static void Main(string[] args) => BuildAvaloniaApp() public static void Main(string[] args)
.With(new FontManagerOptions {
{ var appBuilder = BuildAvaloniaApp();
FontFallbacks = if (!OperatingSystem.IsLinux())
[ appBuilder.With(new FontManagerOptions
new FontFallback {
{ FontFallbacks = [new FontFallback { FontFamily = new FontFamily("Microsoft YaHei") }]
FontFamily = new FontFamily("Microsoft YaHei") });
}
] appBuilder.StartWithClassicDesktopLifetime(args);
}) }
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer. // Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>() {
var appBuilder = AppBuilder.Configure<App>()
.UseManagedSystemDialogs() .UseManagedSystemDialogs()
.UsePlatformDetect() .UsePlatformDetect()
.With(new Win32PlatformOptions()) .With(new Win32PlatformOptions())
.With(new X11PlatformOptions { EnableDrawnDecorations = true })
.LogToTrace(); .LogToTrace();
} if (OperatingSystem.IsLinux()) appBuilder.WithSourceHanSansCNFont();
return appBuilder;
}
}
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationIcon>..\Semi.Avalonia.Demo\Assets\irihi.ico</ApplicationIcon> <ApplicationIcon>..\Semi.Avalonia.Demo\Assets\irihi.ico</ApplicationIcon>
@@ -28,5 +28,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/> <ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/>
<ProjectReference Include="..\Semi.Avalonia.Demo.Fonts\Semi.Avalonia.Demo.Fonts.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
+10 -8
View File
@@ -4,8 +4,10 @@ using System.Linq;
using System.Threading; using System.Threading;
using Avalonia; using Avalonia;
using Avalonia.Dialogs; using Avalonia.Dialogs;
using Semi.Avalonia.Demo.Fonts;
namespace Semi.Avalonia.Demo.Drm; namespace Semi.Avalonia.Demo.Drm;
#pragma warning disable CA1416, AVALONIA_X11_CSD, AVALONIA_X11_FORCE_CSD
sealed class Program sealed class Program
{ {
@@ -40,17 +42,17 @@ sealed class Program
=> AppBuilder.Configure<App>() => AppBuilder.Configure<App>()
.UseManagedSystemDialogs() .UseManagedSystemDialogs()
.UsePlatformDetect() .UsePlatformDetect()
.With(new Win32PlatformOptions()) .With(new X11PlatformOptions { EnableDrawnDecorations = true })
.WithSourceHanSansCNFont()
.LogToTrace(); .LogToTrace();
private static void SilenceConsole() private static void SilenceConsole()
{ {
new Thread(() => new Thread(() =>
{ {
Console.CursorVisible = false; Console.CursorVisible = false;
while (true) while (true)
Console.ReadKey(true); Console.ReadKey(true);
}) }) { IsBackground = true }.Start();
{ IsBackground = true }.Start();
} }
} }
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationIcon>..\Semi.Avalonia.Demo\Assets\irihi.ico</ApplicationIcon> <ApplicationIcon>..\Semi.Avalonia.Demo\Assets\irihi.ico</ApplicationIcon>
@@ -29,5 +29,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/> <ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/>
<ProjectReference Include="..\Semi.Avalonia.Demo.Fonts\Semi.Avalonia.Demo.Fonts.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -0,0 +1,16 @@
using Avalonia;
using Avalonia.Media;
namespace Semi.Avalonia.Demo.Fonts;
public static class AvaloniaAppBuilderExtensions
{
public static AppBuilder WithSourceHanSansCNFont(this AppBuilder builder)
{
const string uri = "avares://Semi.Avalonia.Demo.Fonts/Assets#Source Han Sans CN";
return builder.With(new FontManagerOptions
{
DefaultFamilyName = uri, FontFallbacks = [new FontFallback { FontFamily = new FontFamily(uri) }]
});
}
}
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia"/>
</ItemGroup>
</Project>
@@ -1,16 +0,0 @@
using Avalonia;
using Avalonia.Media;
namespace Semi.Avalonia.Demo.Web;
public static class AvaloniaAppBuilderExtensions
{
private static string DefaultFontFamily => "avares://Semi.Avalonia.Demo.Web/Assets#Source Han Sans CN";
public static AppBuilder WithSourceHanSansCNFont(this AppBuilder builder) =>
builder.With(new FontManagerOptions
{
DefaultFamilyName = DefaultFontFamily,
FontFallbacks = [new FontFallback { FontFamily = new FontFamily(DefaultFontFamily) }]
});
}
+2 -1
View File
@@ -2,6 +2,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Browser; using Avalonia.Browser;
using Semi.Avalonia.Demo.Fonts;
[assembly: SupportedOSPlatform("browser")] [assembly: SupportedOSPlatform("browser")]
@@ -15,4 +16,4 @@ internal sealed partial class Program
public static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>(); => AppBuilder.Configure<App>();
} }
@@ -6,17 +6,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="..\Fonts\*" Link="Assets\Fonts\%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Browser"/> <PackageReference Include="Avalonia.Browser"/>
<PackageReference Include="SkiaSharp"/>
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/> <ProjectReference Include="..\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj"/>
<ProjectReference Include="..\Semi.Avalonia.Demo.Fonts\Semi.Avalonia.Demo.Fonts.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
+12 -2
View File
@@ -5,13 +5,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:semi="https://irihi.tech/semi" xmlns:semi="https://irihi.tech/semi"
xmlns:vm="clr-namespace:Semi.Avalonia.Demo.ViewModels" xmlns:vm="clr-namespace:Semi.Avalonia.Demo.ViewModels"
RequestedThemeVariant="Default"
x:DataType="vm:ApplicationViewModel"> x:DataType="vm:ApplicationViewModel">
<Application.Styles> <Application.Styles>
<semi:SemiTheme Locale="zh-CN" /> <semi:SemiTheme Locale="zh-CN" />
<semi:SemiPopupAnimations /> <semi:SemiPopupAnimations />
<semi:ColorPickerSemiTheme /> <semi:ColorPickerSemiTheme />
<semi:DataGridSemiTheme /> <semi:DataGridSemiTheme />
<semi:TreeDataGridSemiTheme /> <!-- <semi:TreeDataGridSemiTheme /> -->
</Application.Styles> </Application.Styles>
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
@@ -28,6 +29,15 @@
CommandParameter="{Binding $self.Header}" /> CommandParameter="{Binding $self.Header}" />
</NativeMenu> </NativeMenu>
</NativeMenu.Menu> </NativeMenu.Menu>
<NativeDock.Menu>
<NativeMenu>
<NativeMenuItem Header="New Window" />
<NativeMenuItemSeparator />
<NativeMenuItem Header="Show Main Window" />
<NativeMenuItemSeparator />
<NativeMenuItem Header="Add Dock Menu Item" />
</NativeMenu>
</NativeDock.Menu>
<TrayIcon.Icons> <TrayIcon.Icons>
<TrayIcons> <TrayIcons>
<TrayIcon <TrayIcon
@@ -49,4 +59,4 @@
</TrayIcon> </TrayIcon>
</TrayIcons> </TrayIcons>
</TrayIcon.Icons> </TrayIcon.Icons>
</Application> </Application>
+20 -13
View File
@@ -1,6 +1,6 @@
using System;
using Avalonia; using Avalonia;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Semi.Avalonia.Demo.ViewModels; using Semi.Avalonia.Demo.ViewModels;
using Semi.Avalonia.Demo.Views; using Semi.Avalonia.Demo.Views;
@@ -12,25 +12,32 @@ public partial class App : Application
public override void Initialize() public override void Initialize()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
this.DataContext = new ApplicationViewModel(); #if DEBUG
this.AttachDeveloperTools();
#endif
DataContext = new ApplicationViewModel();
if (OperatingSystem.IsLinux())
{
Resources.Add("DefaultFontFamily", null);
}
} }
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
switch (ApplicationLifetime) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
case IClassicDesktopStyleApplicationLifetime desktop: desktop.MainWindow = new MainWindow { DataContext = new MainViewModel() };
// Line below is needed to remove Avalonia data validation. }
// Without this line you will get duplicate validations from both Avalonia and CT else if (ApplicationLifetime is IActivityApplicationLifetime applicationLifetime)
BindingPlugins.DataValidators.RemoveAt(0); {
desktop.MainWindow = new MainWindow(); applicationLifetime.MainViewFactory = () => new MainView { DataContext = new MainViewModel() };
break; }
case ISingleViewApplicationLifetime singleView: else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
singleView.MainView = new MainView(); {
break; singleViewPlatform.MainView = new MainView { DataContext = new MainViewModel() };
} }
this.RegisterFollowSystemTheme(); this.RegisterFollowSystemTheme();
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
} }
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Input.Platform;
using Avalonia.Media; using Avalonia.Media;
using Semi.Avalonia.Demo.Converters; using Semi.Avalonia.Demo.Converters;
@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Avalonia;
using Avalonia.Data.Converters;
using Avalonia.Metadata;
namespace Semi.Avalonia.Demo.Converters;
public class FileIconConverter : IMultiValueConverter
{
[Content] public IDictionary<string, object?> Items { get; } = new Dictionary<string, object?>();
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
{
if (values[0] is bool isDirectory && values[1] is bool isOpen)
{
if (!isDirectory)
{
return Items["file"];
}
return isOpen ? Items["folderOpen"] : Items["folderClosed"];
}
return AvaloniaProperty.UnsetValue;
}
}
@@ -28,59 +28,59 @@
</StackPanel.Styles> </StackPanel.Styles>
<AutoCompleteBox <AutoCompleteBox
Watermark="Please select a State" PlaceholderText="Please select a State"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Classes="Large" Classes="Large"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Classes="Small" Classes="Small"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Classes="Bordered" Classes="Bordered"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
IsEnabled="False" IsEnabled="False"
Watermark="Disabled" PlaceholderText="Disabled"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
InnerLeftContent="https://" InnerLeftContent="https://"
InnerRightContent=".com" InnerRightContent=".com"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
Classes="Large" Classes="Large"
Watermark="Large" PlaceholderText="Large"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
Watermark="Default" PlaceholderText="Default"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
Classes="Small" Classes="Small"
Watermark="Small" PlaceholderText="Small"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
IsEnabled="False" IsEnabled="False"
Watermark="Disabled" PlaceholderText="Disabled"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
Classes="Bordered" Classes="Bordered"
Watermark="Bordered" PlaceholderText="Bordered"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
<AutoCompleteBox <AutoCompleteBox
Width="100" Width="100"
Classes="Bordered" Classes="Bordered"
IsEnabled="False" IsEnabled="False"
ValueMemberBinding="{Binding Name,DataType=vm:StateData}" /> ValueMemberBinding="{Binding Name,x:DataType=vm:StateData}" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
@@ -35,5 +35,30 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Text="A.S.I.A" /> Text="A.S.I.A" />
</ButtonSpinner> </ButtonSpinner>
<ButtonSpinner
Height="30"
AllowSpin="{Binding #allowSpinCheck.IsChecked}"
BorderThickness="1"
ShowButtonSpinner="{Binding #showSpinCheck.IsChecked}"
Spin="OnSpin"
Theme="{StaticResource SplitButtonSpinner}">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="A.S.I.A" />
</ButtonSpinner>
<ButtonSpinner
Height="30"
AllowSpin="{Binding #allowSpinCheck.IsChecked}"
ButtonSpinnerLocation="Left"
BorderThickness="1"
ShowButtonSpinner="{Binding #showSpinCheck.IsChecked}"
Spin="OnSpin"
Theme="{StaticResource SplitButtonSpinner}">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="A.S.I.A" />
</ButtonSpinner>
</StackPanel> </StackPanel>
</UserControl> </UserControl>
@@ -33,6 +33,6 @@
Margin="0,0,0,8" Margin="0,0,0,8"
CustomDateFormatString="ddd, MMM d" CustomDateFormatString="ddd, MMM d"
SelectedDateFormat="Custom" /> SelectedDateFormat="Custom" />
<CalendarDatePicker Margin="0,0,0,8" Watermark="Watermark" /> <CalendarDatePicker Margin="0,0,0,8" PlaceholderText="Placeholder" />
</StackPanel> </StackPanel>
</UserControl> </UserControl>
@@ -0,0 +1,69 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Semi.Avalonia.Demo.Pages.CarouselPageDemo">
<DockPanel>
<ScrollViewer DockPanel.Dock="Right" Width="220">
<StackPanel Margin="12" Spacing="8">
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16"
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" />
<TextBlock Text="Navigation" FontWeight="SemiBold" FontSize="13" />
<StackPanel Spacing="6">
<Button Content="Previous" Click="OnPrevious" HorizontalAlignment="Stretch" />
<Button Content="Next" Click="OnNext" HorizontalAlignment="Stretch" />
</StackPanel>
<Separator />
<TextBlock Text="Status" FontWeight="SemiBold" FontSize="13" />
<TextBlock Name="StatusText" Text="Page 1 of 3" Opacity="0.7" TextWrapping="Wrap" />
</StackPanel>
</ScrollViewer>
<Border DockPanel.Dock="Right" Width="1"
Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" />
<Border Margin="12"
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1" CornerRadius="6" ClipToBounds="True">
<Panel>
<CarouselPage Name="DemoCarousel"
SelectionChanged="OnSelectionChanged">
<ContentPage Header="Welcome">
<StackPanel Margin="24" Spacing="12"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Welcome" FontSize="28" FontWeight="Bold"
HorizontalAlignment="Center" />
<TextBlock Text="Swipe left or use the buttons to navigate."
TextWrapping="Wrap" Opacity="0.7" TextAlignment="Center" MaxWidth="280" />
</StackPanel>
</ContentPage>
<ContentPage Header="Explore">
<StackPanel Margin="24" Spacing="12"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Explore" FontSize="28" FontWeight="Bold"
HorizontalAlignment="Center" />
<TextBlock Text="CarouselPage supports scroll-based and transition-based navigation modes."
TextWrapping="Wrap" Opacity="0.7" TextAlignment="Center" MaxWidth="280" />
</StackPanel>
</ContentPage>
<ContentPage Header="Get Started">
<StackPanel Margin="24" Spacing="12"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Get Started" FontSize="28" FontWeight="Bold"
HorizontalAlignment="Center" />
<TextBlock Text="Use SelectedIndex to jump to any page, or assign a PageTransition for animated switching."
TextWrapping="Wrap" Opacity="0.7" TextAlignment="Center" MaxWidth="280" />
</StackPanel>
</ContentPage>
</CarouselPage>
<PipsPager HorizontalAlignment="Center"
VerticalAlignment="Bottom" Margin="0,0,0,20"
NumberOfPages="3"
SelectedPageIndex="{Binding #DemoCarousel.SelectedIndex}" />
</Panel>
</Border>
</DockPanel>
</UserControl>
@@ -0,0 +1,34 @@
using System.Collections;
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace Semi.Avalonia.Demo.Pages;
public partial class CarouselPageDemo : UserControl
{
public CarouselPageDemo()
{
InitializeComponent();
}
private void OnPrevious(object? sender, RoutedEventArgs e)
{
if (DemoCarousel.SelectedIndex > 0)
DemoCarousel.SelectedIndex--;
}
private void OnNext(object? sender, RoutedEventArgs e)
{
var pageCount = (DemoCarousel.Pages as IList)?.Count ?? 0;
if (DemoCarousel.SelectedIndex < pageCount - 1)
DemoCarousel.SelectedIndex++;
}
private void OnSelectionChanged(object? sender, PageSelectionChangedEventArgs e)
{
if (StatusText == null)
return;
var pageCount = (DemoCarousel.Pages as IList)?.Count ?? 0;
StatusText.Text = $"Page {DemoCarousel.SelectedIndex + 1} of {pageCount}";
}
}
@@ -2,80 +2,90 @@
x:Class="Semi.Avalonia.Demo.Pages.ColorPickerDemo" x:Class="Semi.Avalonia.Demo.Pages.ColorPickerDemo"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:semi="https://irihi.tech/semi"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="1450" d:DesignHeight="1450"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d"> mc:Ignorable="d">
<ScrollViewer> <DockPanel>
<StackPanel Spacing="20"> <ScrollViewer DockPanel.Dock="Right" Width="260">
<StackPanel Orientation="Horizontal" Spacing="20"> <StackPanel Margin="12" Spacing="8">
<ColorView Name="Test" ColorSpectrumShape="Ring" /> <StackPanel.Styles>
<ColorView ColorSpectrumShape="Box" /> <Style Selector="ToggleSwitch">
<ColorView Palette="{DynamicResource SemiColorPalette}" /> <Setter Property="OffContent" Value="{Binding $self.OnContent}" />
</StackPanel> </Style>
<StackPanel Orientation="Horizontal"> </StackPanel.Styles>
<ColorView <StackPanel Spacing="8">
Name="SimpleColorViewTest" <ToggleSwitch Name="AccentColors" OnContent="IsAccentColorsVisible" IsChecked="True" />
HsvColor="hsv(180,80%,70%)" <ToggleSwitch Name="AlphaEnabled" OnContent="IsAlphaEnabled" IsChecked="True" />
IsAlphaVisible="True" <ToggleSwitch Name="Alpha" OnContent="IsAlphaVisible" IsChecked="True" />
Theme="{StaticResource SimpleColorView}" /> <ToggleSwitch Name="ColorComponents" OnContent="IsColorComponentsVisible" IsChecked="True" />
<StackPanel> <ToggleSwitch Name="ColorModel" OnContent="IsColorModelVisible" IsChecked="True" />
<TextBlock Text="{Binding #SimpleColorViewTest.HsvColor}" /> <ToggleSwitch Name="ColorPalette" OnContent="IsColorPaletteVisible" IsChecked="True" />
<TextBlock Text="{Binding #SimpleColorViewTest.Color}" /> <ToggleSwitch Name="ColorPreview" OnContent="IsColorPreviewVisible" IsChecked="True" />
<ToggleSwitch Name="ColorSpectrum" OnContent="IsColorSpectrumVisible" IsChecked="True" />
<ToggleSwitch Name="ColorSpectrumSlider" OnContent="IsColorSpectrumSliderVisible" IsChecked="True" />
<ToggleSwitch Name="ComponentSlider" OnContent="IsComponentSliderVisible" IsChecked="True" />
<ToggleSwitch Name="ComponentTextInput" OnContent="IsComponentTextInputVisible" IsChecked="True" />
<ToggleSwitch Name="HexInput" OnContent="IsHexInputVisible" IsChecked="True" />
</StackPanel>
<Separator />
<StackPanel Spacing="8">
<TextBlock>
<Run Text="Color: " />
<Run Text="{Binding #cv.Color,Mode=OneWay}" />
</TextBlock>
<TextBlock>
<Run Text="HsvColor:" />
<Run Text="{Binding #cv.HsvColor,Mode=OneWay}" />
</TextBlock>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8"> </ScrollViewer>
<ColorPicker ColorSpectrumShape="Ring">
<ColorPicker.Palette>
<FlatHalfColorPalette />
</ColorPicker.Palette>
</ColorPicker>
<ColorPicker ColorSpectrumShape="Box">
<ColorPicker.Palette>
<semi:SemiColorLightPalette />
</ColorPicker.Palette>
</ColorPicker>
<ColorPicker
Theme="{DynamicResource HexColorPicker}"
ColorSpectrumShape="Box">
<ColorPicker.Palette>
<semi:SemiColorLightPalette />
</ColorPicker.Palette>
</ColorPicker>
</StackPanel>
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="Use Style to customize button" />
<ColorPicker
Margin="8"
MinWidth="32"
HsvColor="hsv(180,80%,70%)">
<ColorPicker.Content>
<Border
Margin="1"
Background="{Binding $parent[ColorPicker].HsvColor, Converter={StaticResource ToBrushConverter}}"
CornerRadius="1" />
</ColorPicker.Content>
<ColorPicker.Styles>
<Style Selector="DropDownButton">
<Setter Property="Padding" Value="0" />
<Style Selector="^ /template/ PathIcon">
<Setter Property="IsVisible" Value="False" />
</Style>
</Style>
</ColorPicker.Styles>
</ColorPicker>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8"> <Border Margin="12"
<ColorPicker BorderBrush="{DynamicResource SemiColorBorder}"
Theme="{StaticResource SimpleColorPicker}" BorderThickness="1"
HsvColor="hsv(180,80%,70%)" /> CornerRadius="6"
<ColorPicker ClipToBounds="True">
Theme="{StaticResource HexSimpleColorPicker}" <Border.Styles>
HsvColor="hsv(180,80%,70%)" /> <Style Selector=":is(ColorView)">
<Setter Property="IsAccentColorsVisible" Value="{Binding #AccentColors.IsChecked}" />
<Setter Property="IsAlphaEnabled" Value="{Binding #AlphaEnabled.IsChecked}" />
<Setter Property="IsAlphaVisible" Value="{Binding #Alpha.IsChecked}" />
<Setter Property="IsColorComponentsVisible" Value="{Binding #ColorComponents.IsChecked}" />
<Setter Property="IsColorModelVisible" Value="{Binding #ColorModel.IsChecked}" />
<Setter Property="IsColorPaletteVisible" Value="{Binding #ColorPalette.IsChecked}" />
<Setter Property="IsColorPreviewVisible" Value="{Binding #ColorPreview.IsChecked}" />
<Setter Property="IsColorSpectrumVisible" Value="{Binding #ColorSpectrum.IsChecked}" />
<Setter Property="IsColorSpectrumSliderVisible" Value="{Binding #ColorSpectrumSlider.IsChecked}" />
<Setter Property="IsComponentSliderVisible" Value="{Binding #ComponentSlider.IsChecked}" />
<Setter Property="IsComponentTextInputVisible" Value="{Binding #ComponentTextInput.IsChecked}" />
<Setter Property="IsHexInputVisible" Value="{Binding #HexInput.IsChecked}" />
<Setter Property="Color" Value="#39C5BB" />
</Style>
</Border.Styles>
<StackPanel Margin="12" Spacing="12" Orientation="Horizontal">
<StackPanel Spacing="12">
<TextBlock Text="Default Theme" FontWeight="Bold" FontSize="16" />
<ColorView Name="cv" />
<StackPanel Spacing="12" Orientation="Horizontal">
<ColorPicker />
<ColorPicker Theme="{DynamicResource HexColorPicker}" />
</StackPanel>
</StackPanel>
<StackPanel Spacing="12">
<TextBlock Text="SimpleColorPicker" FontWeight="Bold" FontSize="16" />
<ColorView Theme="{DynamicResource SimpleColorView}" />
<StackPanel Spacing="12" Orientation="Horizontal">
<ColorPicker Theme="{DynamicResource SimpleColorPicker}" />
<ColorPicker Theme="{DynamicResource HexSimpleColorPicker}" />
</StackPanel>
</StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </Border>
</ScrollViewer> </DockPanel>
</UserControl> </UserControl>
@@ -0,0 +1,94 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.CommandBarDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:collections="clr-namespace:Avalonia.Collections;assembly=Avalonia.Base"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources>
<collections:AvaloniaList x:TypeArguments="CommandBarDefaultLabelPosition" x:Key="LabelPositionList">
<CommandBarDefaultLabelPosition>Bottom</CommandBarDefaultLabelPosition>
<CommandBarDefaultLabelPosition>Collapsed</CommandBarDefaultLabelPosition>
<CommandBarDefaultLabelPosition>Right</CommandBarDefaultLabelPosition>
</collections:AvaloniaList>
<collections:AvaloniaList x:TypeArguments="CommandBarOverflowButtonVisibility" x:Key="VisibilityList">
<CommandBarOverflowButtonVisibility>Auto</CommandBarOverflowButtonVisibility>
<CommandBarOverflowButtonVisibility>Collapsed</CommandBarOverflowButtonVisibility>
<CommandBarOverflowButtonVisibility>Visible</CommandBarOverflowButtonVisibility>
</collections:AvaloniaList>
</UserControl.Resources>
<ScrollViewer>
<StackPanel Spacing="16">
<GroupBox>
<GroupBox.Header>
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0" Text="DefaultLabelPosition" VerticalAlignment="Center" />
<ComboBox Grid.Row="0" Grid.Column="1"
Name="lc"
ItemsSource="{DynamicResource LabelPositionList}"
SelectedValue="{x:Static CommandBarDefaultLabelPosition.Bottom}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="OverflowButtonVisibility" VerticalAlignment="Center" />
<ComboBox Grid.Row="1" Grid.Column="1"
Name="btvb"
ItemsSource="{DynamicResource VisibilityList}"
SelectedValue="{x:Static CommandBarOverflowButtonVisibility.Auto}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="IsDynamicOverflowEnabled" VerticalAlignment="Center" />
<ToggleSwitch Grid.Row="2" Grid.Column="1" Name="idfe" IsChecked="True" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="IsOpen" VerticalAlignment="Center" />
<ToggleSwitch Grid.Row="3" Grid.Column="1" Name="isop" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="IsSticky" VerticalAlignment="Center" />
<ToggleSwitch Grid.Row="4" Grid.Column="1" Name="isst" />
<TextBlock Grid.Row="5" Grid.Column="0" Text="Width" VerticalAlignment="Center" />
<Slider Grid.Row="5" Grid.Column="1" Name="ws" HorizontalAlignment="Left" Width="500" Minimum="0" Maximum="1000" Value="200" />
</Grid>
</GroupBox.Header>
<CommandBar
DefaultLabelPosition="{Binding #lc.SelectedValue}"
OverflowButtonVisibility="{Binding #btvb.SelectedValue}"
IsDynamicOverflowEnabled="{Binding #idfe.IsChecked}"
IsOpen="{Binding #isop.IsChecked}"
IsSticky="{Binding #isst.IsChecked}"
Width="{Binding #ws.Value}">
<CommandBarButton Label="New" Icon="{DynamicResource SemiIconPlus}" />
<CommandBarButton Label="Save" Icon="{DynamicResource SemiIconSave}" />
<CommandBarSeparator />
<CommandBarToggleButton Label="Bold" Icon="{DynamicResource SemiIconBold}" />
<CommandBarToggleButton Label="Italic" Icon="{DynamicResource SemiIconItalic}" />
<CommandBarToggleButton IsChecked="True" IsEnabled="False" Label="Underline" Icon="{DynamicResource SemiIconUnderline}" />
<CommandBarSeparator />
<CommandBarButton Label="Share" Icon="{DynamicResource SemiIconShare}" />
<CommandBarButton Label="Export" Icon="{DynamicResource SemiIconExport}" />
<CommandBarButton Label="Print" Icon="{DynamicResource SemiIconPrint}" />
<CommandBarSeparator />
<CommandBarButton Label="Delete" Icon="{DynamicResource SemiIconDelete}" />
</CommandBar>
</GroupBox>
<!-- With secondary commands (overflow) -->
<GroupBox>
<GroupBox.Header>
<TextBlock Text="CommandBar — With Secondary Commands (overflow)" />
</GroupBox.Header>
<CommandBar>
<CommandBarButton Label="New" Icon="{DynamicResource SemiIconPlus}" />
<CommandBarButton Label="Save" Icon="{DynamicResource SemiIconSave}" />
<CommandBarButton Label="Share" Icon="{DynamicResource SemiIconShare}" />
<CommandBar.SecondaryCommands>
<CommandBarButton Label="Export" Icon="{DynamicResource SemiIconExport}" />
<CommandBarButton Label="Delete" Icon="{DynamicResource SemiIconDelete}" />
</CommandBar.SecondaryCommands>
</CommandBar>
</GroupBox>
</StackPanel>
</ScrollViewer>
</UserControl>
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace Semi.Avalonia.Demo.Pages;
public partial class CommandBarDemo : UserControl
{
public CommandBarDemo()
{
InitializeComponent();
}
}
@@ -0,0 +1,54 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.ContentPageDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<DockPanel>
<ScrollViewer DockPanel.Dock="Right" Width="260">
<StackPanel Margin="12" Spacing="8">
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16"
Foreground="{DynamicResource SemiColorText0}" />
<TextBlock Text="ContentPage is the fundamental page type. It hosts a single piece of content and integrates with NavigationPage, TabbedPage, and CarouselPage. The Header property sets the navigation bar title."
FontSize="12" Opacity="0.7" TextWrapping="Wrap" />
<Separator />
<TextBlock Text="Navigation" FontWeight="SemiBold" />
<Button Content="Push Page" HorizontalAlignment="Stretch" Click="OnPush" />
<Button Content="Pop Page" HorizontalAlignment="Stretch" Click="OnPop" />
<Button Content="Pop to Root" HorizontalAlignment="Stretch" Click="OnPopToRoot" />
<Separator />
<TextBlock Text="Key Properties" FontWeight="SemiBold" />
<TextBlock Text="• Header: nav bar title (string or Control)" FontSize="12" Opacity="0.8" TextWrapping="Wrap" />
<TextBlock Text="• Content: any Avalonia control" FontSize="12" Opacity="0.8" TextWrapping="Wrap" />
<TextBlock Text="• Background: page background brush" FontSize="12" Opacity="0.8" TextWrapping="Wrap" />
<TextBlock Text="• HorizontalContentAlignment" FontSize="12" Opacity="0.8" />
<TextBlock Text="• VerticalContentAlignment" FontSize="12" Opacity="0.8" />
<TextBlock Text="• AutomaticallyApplySafeAreaPadding" FontSize="12" Opacity="0.8" />
<Separator />
<TextBlock Name="StatusText"
Text="Depth: 1 | Current: Root Page"
FontSize="11"
Opacity="0.7" />
</StackPanel>
</ScrollViewer>
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SemiColorBackground0}" />
<Border Margin="12"
BorderBrush="{DynamicResource SemiColorBorder}"
BorderThickness="1"
CornerRadius="6"
ClipToBounds="True">
<NavigationPage Name="DemoNav" />
</Border>
</DockPanel>
</UserControl>
@@ -0,0 +1,93 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Layout;
namespace Semi.Avalonia.Demo.Pages;
public partial class ContentPageDemo : UserControl
{
private static readonly Color[] PageColors =
[
Color.FromRgb(0xE3, 0xF2, 0xFD), // blue
Color.FromRgb(0xF3, 0xE5, 0xF5), // purple
Color.FromRgb(0xE8, 0xF5, 0xE9), // green
Color.FromRgb(0xFF, 0xF8, 0xE1), // amber
Color.FromRgb(0xFB, 0xE9, 0xE7), // deep orange
];
private int _pageCount;
public ContentPageDemo()
{
InitializeComponent();
Loaded += OnLoaded;
}
private async void OnLoaded(object? sender, RoutedEventArgs e)
{
await DemoNav.PushAsync(MakePage("Root Page", "ContentPage inside a NavigationPage.\nUse the options to navigate."));
UpdateStatus();
}
private async void OnPush(object? sender, RoutedEventArgs e)
{
_pageCount++;
await DemoNav.PushAsync(MakePage($"Page {_pageCount}", $"ContentPage #{_pageCount}.\nNavigate back using the back button."));
UpdateStatus();
}
private async void OnPop(object? sender, RoutedEventArgs e)
{
await DemoNav.PopAsync();
UpdateStatus();
}
private async void OnPopToRoot(object? sender, RoutedEventArgs e)
{
await DemoNav.PopToRootAsync();
_pageCount = 0;
UpdateStatus();
}
private void UpdateStatus()
{
StatusText.Text = $"Depth: {DemoNav.StackDepth} | Current: {DemoNav.CurrentPage?.Header}";
}
private ContentPage MakePage(string header, string body) =>
new ContentPage
{
Header = header,
Background = new SolidColorBrush(PageColors[_pageCount % PageColors.Length]),
Content = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Spacing = 10,
Children =
{
new TextBlock
{
Text = header,
FontSize = 20,
FontWeight = FontWeight.SemiBold,
HorizontalAlignment = HorizontalAlignment.Center,
Foreground = Brushes.Black,
},
new TextBlock
{
Text = body,
FontSize = 13,
Opacity = 0.7,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Center,
MaxWidth = 260,
Foreground = Brushes.Black,
}
}
},
HorizontalContentAlignment = HorizontalAlignment.Stretch,
VerticalContentAlignment = VerticalAlignment.Stretch
};
}
@@ -1,4 +1,6 @@
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Semi.Avalonia.Demo.ViewModels; using Semi.Avalonia.Demo.ViewModels;
namespace Semi.Avalonia.Demo.Pages; namespace Semi.Avalonia.Demo.Pages;
@@ -0,0 +1,116 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.DrawerPageDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="700"
d:DesignWidth="800"
mc:Ignorable="d">
<DockPanel>
<ScrollViewer DockPanel.Dock="Right" Width="260">
<StackPanel Margin="12" Spacing="8">
<TextBlock
Theme="{DynamicResource TitleTextBlock}"
Classes="H4"
Text="Configuration" />
<CheckBox Name="ToggleDrawerCheck"
Content="Toggle Drawer" />
<CheckBox Name="GestureCheck"
Content="Gesture Enabled"
IsChecked="True" />
<TextBlock Text="Behavior" FontSize="12" />
<ComboBox
Name="BehaviorComboBox"
HorizontalAlignment="Stretch"
SelectedIndex="0">
<DrawerBehavior>Auto</DrawerBehavior>
<DrawerBehavior>Flyout</DrawerBehavior>
<DrawerBehavior>Locked</DrawerBehavior>
<DrawerBehavior>Disabled</DrawerBehavior>
</ComboBox>
<TextBlock Text="Layout" FontSize="12" />
<ComboBox
Name="LayoutComboBox"
HorizontalAlignment="Stretch"
SelectedIndex="0">
<DrawerLayoutBehavior>Overlay</DrawerLayoutBehavior>
<DrawerLayoutBehavior>Split</DrawerLayoutBehavior>
<DrawerLayoutBehavior>CompactOverlay</DrawerLayoutBehavior>
<DrawerLayoutBehavior>CompactInline</DrawerLayoutBehavior>
</ComboBox>
<TextBlock Text="Placement" FontSize="12" />
<ComboBox
Name="PlacementComboBox"
HorizontalAlignment="Stretch"
SelectedIndex="0">
<DrawerPlacement>Left</DrawerPlacement>
<DrawerPlacement>Right</DrawerPlacement>
<DrawerPlacement>Top</DrawerPlacement>
<DrawerPlacement>Bottom</DrawerPlacement>
</ComboBox>
<TextBlock Text="Compact Drawer Length" FontSize="12" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Slider Name="CompactDrawerLengthSlider"
Minimum="0" Maximum="250" Value="80"
TickFrequency="1"
IsSnapToTickEnabled="True"
Width="150" />
<TextBlock Text="{Binding #CompactDrawerLengthSlider.Value}" />
</StackPanel>
<TextBlock Text="Drawer Length" FontSize="12" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Slider Name="DrawerLengthSlider"
Minimum="150" Maximum="400" Value="260"
TickFrequency="1"
IsSnapToTickEnabled="True"
Width="150" />
<TextBlock Text="{Binding #DrawerLengthSlider.Value}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SemiColorBorder}" />
<DrawerPage Name="DemoDrawer"
Margin="12"
Header="First Look"
IsOpen="{Binding #ToggleDrawerCheck.IsChecked}"
IsGestureEnabled="{Binding #GestureCheck.IsChecked}"
DrawerBehavior="{Binding #BehaviorComboBox.SelectedItem}"
DrawerLayoutBehavior="{Binding #LayoutComboBox.SelectedItem}"
DrawerPlacement="{Binding #PlacementComboBox.SelectedItem}"
CompactDrawerLength="{Binding #CompactDrawerLengthSlider.Value}"
DrawerLength="{Binding #DrawerLengthSlider.Value}">
<DrawerPage.DrawerHeader>
<TextBlock Text="Menu" Margin="16" FontSize="18" FontWeight="SemiBold" Foreground="{DynamicResource SemiColorPrimary}" />
</DrawerPage.DrawerHeader>
<DrawerPage.DrawerFooter>
<TextBlock HorizontalAlignment="Center" Text="Powered by IRIHI" Margin="8" />
</DrawerPage.DrawerFooter>
<DrawerPage.Drawer>
<ListBox Name="DrawerMenu" SelectionChanged="OnMenuSelectionChanged">
<ListBoxItem Content="Home" />
<ListBoxItem Content="Settings" />
<ListBoxItem Content="Profile" />
<ListBoxItem Content="About" />
</ListBox>
</DrawerPage.Drawer>
<DrawerPage.Content>
<ContentPage Header="Home">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="8">
<TextBlock Text="Home Page" FontSize="20" FontWeight="SemiBold" HorizontalAlignment="Center" />
<TextBlock Text="Swipe from the left edge or use the hamburger button to open the drawer."
FontSize="13" Opacity="0.7" TextWrapping="Wrap" TextAlignment="Center" MaxWidth="300" />
</StackPanel>
</ContentPage>
</DrawerPage.Content>
</DrawerPage>
</DockPanel>
</UserControl>
@@ -0,0 +1,45 @@
using System.Linq;
using Avalonia.Controls;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Layout;
namespace Semi.Avalonia.Demo.Pages;
public partial class DrawerPageDemo : UserControl
{
public DrawerPageDemo()
{
InitializeComponent();
EnableMouseSwipeGesture(DemoDrawer);
}
private void OnMenuSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (DrawerMenu.SelectedItem is ListBoxItem item)
{
DemoDrawer.Content = new ContentPage
{
Header = item.Content?.ToString(),
Content = new TextBlock
{
Text = $"{item.Content} page content",
FontSize = 16,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
},
HorizontalContentAlignment = HorizontalAlignment.Stretch,
VerticalContentAlignment = VerticalAlignment.Stretch
};
DemoDrawer.IsOpen = false;
}
}
private static void EnableMouseSwipeGesture(Control control)
{
var recognizer = control.GestureRecognizers
.OfType<SwipeGestureRecognizer>()
.FirstOrDefault();
recognizer?.IsMouseEnabled = true;
}
}
@@ -36,10 +36,20 @@
<HyperlinkButton HorizontalAlignment="Right" Content="更多" /> <HyperlinkButton HorizontalAlignment="Right" Content="更多" />
</Panel> </Panel>
</HeaderedContentControl.Header> </HeaderedContentControl.Header>
<HeaderedContentControl.Content> <SelectableTextBlock Text="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。" />
<SelectableTextBlock Text="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。" />
</HeaderedContentControl.Content>
</HeaderedContentControl> </HeaderedContentControl>
<TextBlock>Real GroupBox</TextBlock>
<GroupBox
HorizontalAlignment="Left"
MaxWidth="360">
<HeaderedContentControl.Header>
<Panel>
<SelectableTextBlock Text="Semi Design" />
<HyperlinkButton HorizontalAlignment="Right" Content="更多" />
</Panel>
</HeaderedContentControl.Header>
<SelectableTextBlock Text="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。" />
</GroupBox>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>
@@ -1,4 +1,4 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input.Platform;
using Semi.Avalonia.Demo.ViewModels; using Semi.Avalonia.Demo.ViewModels;
namespace Semi.Avalonia.Demo.Pages; namespace Semi.Avalonia.Demo.Pages;
+1 -1
View File
@@ -16,7 +16,7 @@
Margin="8" Margin="8"
Classes="ClearButton" Classes="ClearButton"
Text="{Binding SearchText}" Text="{Binding SearchText}"
Watermark="Input Icon Name" /> PlaceholderText="Input Icon Name" />
<TabControl <TabControl
Grid.Row="1" Grid.Row="1"
@@ -0,0 +1,66 @@
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
namespace Semi.Avalonia.Demo.Pages;
/// <summary>
/// Shared helpers for ControlCatalog demo pages.
/// </summary>
internal static class NavigationDemoHelper
{
/// <summary>
/// Pastel background brushes cycled by page index.
/// </summary>
internal static readonly IBrush[] PageBrushes =
[
new SolidColorBrush(Color.Parse("#BBDEFB")),
new SolidColorBrush(Color.Parse("#C8E6C9")),
new SolidColorBrush(Color.Parse("#FFE0B2")),
new SolidColorBrush(Color.Parse("#E1BEE7")),
new SolidColorBrush(Color.Parse("#FFCDD2")),
new SolidColorBrush(Color.Parse("#B2EBF2"))
];
internal static IBrush GetPageBrush(int index) =>
PageBrushes[(index % PageBrushes.Length + PageBrushes.Length) % PageBrushes.Length];
/// <summary>
/// Creates a simple demo ContentPage with a centered title and subtitle.
/// </summary>
internal static ContentPage MakePage(string header, string body, int colorIndex) =>
new()
{
Header = header,
Background = GetPageBrush(colorIndex),
Content = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Spacing = 8,
Children =
{
new TextBlock
{
Text = header,
FontSize = 20,
FontWeight = FontWeight.SemiBold,
HorizontalAlignment = HorizontalAlignment.Center,
Foreground = Brushes.Black,
},
new TextBlock
{
Text = body,
FontSize = 13,
Opacity = 0.7,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Center,
MaxWidth = 260,
Foreground = Brushes.Black,
}
}
},
HorizontalContentAlignment = HorizontalAlignment.Stretch,
VerticalContentAlignment = VerticalAlignment.Stretch
};
}
@@ -0,0 +1,68 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.NavigationPageDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="700"
d:DesignWidth="800"
mc:Ignorable="d">
<ScrollViewer>
<DockPanel>
<ScrollViewer DockPanel.Dock="Right" Width="260">
<StackPanel Margin="12" Spacing="8">
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" />
<TextBlock Text="Navigation" FontWeight="SemiBold" FontSize="13" />
<Button Content="Push Page"
HorizontalAlignment="Stretch"
Click="OnPush" />
<Button Content="Pop"
HorizontalAlignment="Stretch"
Click="OnPop" />
<Button Content="Pop to Root"
HorizontalAlignment="Stretch"
Click="OnPopToRoot" />
<Separator />
<TextBlock Text="Options" FontWeight="SemiBold" FontSize="14" />
<CheckBox Name="HasNavBarCheck"
Content="Has Navigation Bar"
IsChecked="True"
IsCheckedChanged="OnHasNavBarChanged" />
<CheckBox Name="HasBackButtonCheck"
Content="Has Back Button"
IsChecked="True"
IsCheckedChanged="OnHasBackButonChanged" />
<Separator />
<TextBlock Text="Status" FontWeight="SemiBold" FontSize="14" />
<TextBlock Name="StatusText"
Text="Depth: 1"
Opacity="0.7"
TextWrapping="Wrap" />
<TextBlock Name="HeaderText"
Text="Current: Home"
Opacity="0.7"
TextWrapping="Wrap" />
<ToggleSwitch Content="Large" Name="large" />
</StackPanel>
</ScrollViewer>
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SemiColorBackground0}" />
<Border Margin="12"
BorderBrush="{DynamicResource SemiColorBorder}"
BorderThickness="1"
CornerRadius="6"
ClipToBounds="True">
<NavigationPage
Name="DemoNav"
Classes.Large="{Binding #large.IsChecked}" />
</Border>
</DockPanel>
</ScrollViewer>
</UserControl>
@@ -0,0 +1,66 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace Semi.Avalonia.Demo.Pages;
public partial class NavigationPageDemo : UserControl
{
private int _pageCount;
public NavigationPageDemo()
{
InitializeComponent();
Loaded += OnLoaded;
}
private async void OnLoaded(object? sender, RoutedEventArgs e)
{
await DemoNav.PushAsync(NavigationDemoHelper.MakePage("Home", "Welcome!\nUse the buttons to push and pop pages.", 0), null);
UpdateStatus();
}
private async void OnPush(object? sender, RoutedEventArgs e)
{
_pageCount++;
var page = NavigationDemoHelper.MakePage($"Page {_pageCount}", $"This is page {_pageCount}.", _pageCount);
NavigationPage.SetHasNavigationBar(page, HasNavBarCheck.IsChecked == true);
NavigationPage.SetHasBackButton(page, HasBackButtonCheck.IsChecked == true);
await DemoNav.PushAsync(page);
UpdateStatus();
}
private async void OnPop(object? sender, RoutedEventArgs e)
{
await DemoNav.PopAsync();
UpdateStatus();
}
private async void OnPopToRoot(object? sender, RoutedEventArgs e)
{
await DemoNav.PopToRootAsync();
_pageCount = 0;
UpdateStatus();
}
private void OnHasNavBarChanged(object? sender, RoutedEventArgs e)
{
if (DemoNav == null)
return;
if (DemoNav.CurrentPage != null)
NavigationPage.SetHasNavigationBar(DemoNav.CurrentPage, HasNavBarCheck.IsChecked == true);
}
private void OnHasBackButonChanged(object? sender, RoutedEventArgs e)
{
if (DemoNav == null)
return;
if (DemoNav.CurrentPage != null)
NavigationPage.SetHasBackButton(DemoNav.CurrentPage, HasBackButtonCheck.IsChecked == true);
}
private void UpdateStatus()
{
StatusText.Text = $"Depth: {DemoNav.StackDepth}";
HeaderText.Text = $"Current: {DemoNav.CurrentPage?.Header ?? "(none)"}";
}
}
@@ -28,15 +28,15 @@
<NumericUpDown <NumericUpDown
Width="100" Width="100"
Classes="Large" Classes="Large"
Watermark="Large" PlaceholderText="Large"
ButtonSpinnerLocation="Left" /> ButtonSpinnerLocation="Left" />
<NumericUpDown <NumericUpDown
Width="100" Width="100"
Watermark="Default" PlaceholderText="Default"
ShowButtonSpinner="False" /> ShowButtonSpinner="False" />
<NumericUpDown <NumericUpDown
Width="100" Width="100"
Watermark="Small" PlaceholderText="Small"
Classes="Small" /> Classes="Small" />
</StackPanel> </StackPanel>
@@ -51,6 +51,11 @@
<NumericUpDown Width="100" IsEnabled="False" /> <NumericUpDown Width="100" IsEnabled="False" />
<NumericUpDown Width="100" ButtonSpinnerLocation="Left" /> <NumericUpDown Width="100" ButtonSpinnerLocation="Left" />
</StackPanel> </StackPanel>
<StackPanel>
<TextBlock Text="Split" />
<NumericUpDown Classes="Split" Width="300" />
</StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>
+14 -14
View File
@@ -353,12 +353,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].MainInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].MainInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].MainStyle}" Text="{Binding $parent[local:Overview].MainStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -368,12 +368,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].ColorPickerInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].ColorPickerInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].ColorPickerStyle}" Text="{Binding $parent[local:Overview].ColorPickerStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -383,12 +383,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].DataGridInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].DataGridInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].DataGridStyle}" Text="{Binding $parent[local:Overview].DataGridStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -398,12 +398,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].TreeDataGridInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].TreeDataGridInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].TreeDataGridStyle}" Text="{Binding $parent[local:Overview].TreeDataGridStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -413,12 +413,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].DockInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].DockInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].DockStyle}" Text="{Binding $parent[local:Overview].DockStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -428,12 +428,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].TabaloniaInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].TabaloniaInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].TabaloniaStyle}" Text="{Binding $parent[local:Overview].TabaloniaStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -443,12 +443,12 @@
<StackPanel> <StackPanel>
<TextBlock Text="Install via nuget: " /> <TextBlock Text="Install via nuget: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock FontFamily="Consolas" Text="{Binding $parent[local:Overview].AvaloniaEditInstall}" /> <SelectableTextBlock Text="{Binding $parent[local:Overview].AvaloniaEditInstall}" />
</Border> </Border>
<TextBlock Text="Reference styles: " /> <TextBlock Text="Reference styles: " />
<Border Margin="0,16" Classes="CodeBlock"> <Border Margin="0,16" Classes="CodeBlock">
<SelectableTextBlock <SelectableTextBlock
FontFamily="Consolas"
Text="{Binding $parent[local:Overview].AvaloniaEditStyle}" Text="{Binding $parent[local:Overview].AvaloniaEditStyle}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Border> </Border>
@@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Input.Platform;
using Avalonia.Threading; using Avalonia.Threading;
using Semi.Avalonia.Demo.ViewModels; using Semi.Avalonia.Demo.ViewModels;
@@ -11,14 +12,16 @@ public partial class PaletteDemo : UserControl
public PaletteDemo() public PaletteDemo()
{ {
InitializeComponent(); InitializeComponent();
this.DataContext = new PaletteDemoViewModel(); this.DataContext = PaletteDemoViewModel.Instance.Value;
} }
protected override async void OnApplyTemplate(TemplateAppliedEventArgs e) protected override async void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
PaletteDemoViewModel? vm = this.DataContext as PaletteDemoViewModel; if (this.DataContext is PaletteDemoViewModel vm && !vm.IsInitialized)
await Dispatcher.UIThread.InvokeAsync(() => { vm?.InitializeResources(); }); {
await Dispatcher.UIThread.InvokeAsync(() => { vm?.InitializeResources(); });
}
} }
public async Task Copy(object? o) public async Task Copy(object? o)
@@ -30,4 +33,4 @@ public partial class PaletteDemo : UserControl
await c.SetTextAsync(o.ToString()); await c.SetTextAsync(o.ToString());
} }
} }
} }
@@ -0,0 +1,99 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.PipsPagerDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<ScrollViewer>
<StackPanel HorizontalAlignment="Left" Spacing="16" Margin="0,0,0,20">
<!-- Horizontal PipsPager -->
<TextBlock Classes="H6" Text="Horizontal" />
<PipsPager
NumberOfPages="8"
Orientation="Horizontal" />
<!-- Vertical PipsPager -->
<TextBlock Classes="H6" Text="Vertical" />
<PipsPager
NumberOfPages="8"
Orientation="Vertical" />
<!-- Linked with Carousel -->
<TextBlock Classes="H6" Text="Linked with Carousel" />
<Panel>
<Carousel
Name="DemoCarousel"
Height="160">
<Border Background="#EAF5FF">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#1C1F23"
Text="Page 1" />
</Border>
<Border Background="#F9F9F9">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#1C1F23"
Text="Page 2" />
</Border>
<Border Background="#FFF8EA">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#1C1F23"
Text="Page 3" />
</Border>
<Border Background="#FEF2ED">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#1C1F23"
Text="Page 4" />
</Border>
<Border Background="#F0F5FF">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#1C1F23"
Text="Page 5" />
</Border>
</Carousel>
<ThemeVariantScope RequestedThemeVariant="Light">
<PipsPager
Name="LinkedPager"
NumberOfPages="5"
Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Margin="0,0,0,8"
SelectedPageIndex="{Binding #DemoCarousel.SelectedIndex}" />
</ThemeVariantScope>
</Panel>
<!-- Various page counts -->
<TextBlock Classes="H6" Text="Various Page Counts" />
<StackPanel Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock VerticalAlignment="Center" Width="80" Text="3 pages" />
<PipsPager NumberOfPages="3" Orientation="Horizontal" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock VerticalAlignment="Center" Width="80" Text="5 pages" />
<PipsPager NumberOfPages="5" Orientation="Horizontal" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock VerticalAlignment="Center" Width="80" Text="10 pages" />
<PipsPager NumberOfPages="10" Orientation="Horizontal" />
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</UserControl>
@@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace Semi.Avalonia.Demo.Pages;
public partial class PipsPagerDemo : UserControl
{
public PipsPagerDemo()
{
InitializeComponent();
}
}
@@ -22,6 +22,15 @@
TickFrequency="10" TickFrequency="10"
TickPlacement="Outside" TickPlacement="Outside"
Value="0" /> Value="0" />
<Slider
Value="0"
Minimum="0"
Maximum="100"
TickPlacement="BottomRight"
IsSnapToTickEnabled="True"
IsDirectionReversed="True"
Ticks="0,20,25,40,75,100"
Width="300" />
<Slider <Slider
Width="300" Width="300"
Classes="ToolTip" Classes="ToolTip"
@@ -34,14 +34,10 @@
</StackPanel> </StackPanel>
<Border MinHeight="150" Theme="{StaticResource CardBorder}"> <Border MinHeight="150" Theme="{StaticResource CardBorder}">
<TabControl Classes.ReverseSeparator="{Binding #reverse.IsChecked}" TabStripPlacement="{Binding #place.SelectedValue}"> <TabControl Classes.ReverseSeparator="{Binding #reverse.IsChecked}" TabStripPlacement="{Binding #place.SelectedValue}">
<TabItem Content="Hello 1" Header="Tab 1" /> <TabItem Content="Hello 1" Header="文档" Icon="{StaticResource SemiIconFile}" />
<TabItem Content="Hello 2" Header="Tab 2" /> <TabItem Content="Hello 2" Header="快速起步" Icon="{StaticResource SemiIconGlobe}" />
<TabItem Content="Hello 3" Header="Tab 3" /> <TabItem Content="Hello 4" Header="无效" Icon="{StaticResource SemiIconClear}" IsEnabled="False" />
<TabItem Content="中文内容" Header="中文中文" /> <TabItem Content="Hello 3" Header="帮助" Icon="{StaticResource SemiIconHelpCircle}" />
<TabItem
Content="Hello 4"
Header="Tab 4"
IsEnabled="False" />
</TabControl> </TabControl>
</Border> </Border>
<Border Height="300" Theme="{StaticResource CardBorder}"> <Border Height="300" Theme="{StaticResource CardBorder}">
@@ -57,14 +53,10 @@
<StackPanel> <StackPanel>
<Border MinHeight="150" Theme="{StaticResource CardBorder}"> <Border MinHeight="150" Theme="{StaticResource CardBorder}">
<TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource LineTabControl}"> <TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource LineTabControl}">
<TabItem Content="Hello 1" Header="Tab 1" /> <TabItem Content="Hello 1" Header="文档" Icon="{StaticResource SemiIconFile}" />
<TabItem Content="Hello 2" Header="Tab 2" /> <TabItem Content="Hello 2" Header="快速起步" Icon="{StaticResource SemiIconGlobe}" />
<TabItem Content="Hello 3" Header="Tab 3" /> <TabItem Content="Hello 4" Header="无效" Icon="{StaticResource SemiIconClear}" IsEnabled="False" />
<TabItem Content="中文内容" Header="中文中文" /> <TabItem Content="Hello 3" Header="帮助" Icon="{StaticResource SemiIconHelpCircle}" />
<TabItem
Content="Hello 4"
Header="Tab 4"
IsEnabled="False" />
</TabControl> </TabControl>
</Border> </Border>
<Border Height="300" Theme="{StaticResource CardBorder}"> <Border Height="300" Theme="{StaticResource CardBorder}">
@@ -82,14 +74,10 @@
Background="Transparent" Background="Transparent"
Theme="{StaticResource CardBorder}"> Theme="{StaticResource CardBorder}">
<TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource CardTabControl}"> <TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource CardTabControl}">
<TabItem Content="Hello 1" Header="Tab 1" /> <TabItem Content="Hello 1" Header="文档" Icon="{StaticResource SemiIconFile}" />
<TabItem Content="Hello 2" Header="Tab 2" /> <TabItem Content="Hello 2" Header="快速起步" Icon="{StaticResource SemiIconGlobe}" />
<TabItem Content="Hello 3" Header="Tab 3" /> <TabItem Content="Hello 4" Header="无效" Icon="{StaticResource SemiIconClear}" IsEnabled="False" />
<TabItem Content="中文内容" Header="中文中文" /> <TabItem Content="Hello 3" Header="帮助" Icon="{StaticResource SemiIconHelpCircle}" />
<TabItem
Content="Hello 4"
Header="Tab 4"
IsEnabled="False" />
</TabControl> </TabControl>
</Border> </Border>
<Border <Border
@@ -107,14 +95,10 @@
<StackPanel> <StackPanel>
<Border MinHeight="150" Theme="{StaticResource CardBorder}"> <Border MinHeight="150" Theme="{StaticResource CardBorder}">
<TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource ButtonTabControl}"> <TabControl TabStripPlacement="{Binding #place.SelectedValue}" Theme="{StaticResource ButtonTabControl}">
<TabItem Content="Hello 1" Header="Tab 1" /> <TabItem Content="Hello 1" Header="文档" Icon="{StaticResource SemiIconFile}" />
<TabItem Content="Hello 2" Header="Tab 2" /> <TabItem Content="Hello 2" Header="快速起步" Icon="{StaticResource SemiIconGlobe}" />
<TabItem Content="Hello 3" Header="Tab 3" /> <TabItem Content="Hello 4" Header="无效" Icon="{StaticResource SemiIconClear}" IsEnabled="False" />
<TabItem Content="中文内容" Header="中文中文" /> <TabItem Content="Hello 3" Header="帮助" Icon="{StaticResource SemiIconHelpCircle}" />
<TabItem
Content="Hello 4"
Header="Tab 4"
IsEnabled="False" />
</TabControl> </TabControl>
</Border> </Border>
<Border Height="300" Theme="{StaticResource CardBorder}"> <Border Height="300" Theme="{StaticResource CardBorder}">
@@ -0,0 +1,80 @@
<UserControl
x:Class="Semi.Avalonia.Demo.Pages.TabbedPageDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="600"
d:DesignWidth="800"
mc:Ignorable="d">
<DockPanel>
<ScrollViewer DockPanel.Dock="Right" Width="260">
<StackPanel Margin="12" Spacing="8">
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16"
Foreground="{DynamicResource SemiColorText0}" />
<TextBlock Text="Tab Management" FontWeight="SemiBold" FontSize="13" />
<StackPanel Spacing="6">
<Button Content="Add Tab" Click="OnAddTab" HorizontalAlignment="Stretch" />
<Button Content="Remove Latest Tab" Click="OnRemoveTab" HorizontalAlignment="Stretch" />
</StackPanel>
<Separator />
<TextBlock Text="Tab Placement" FontWeight="SemiBold" FontSize="13" />
<ComboBox Name="PlacementCombo" SelectedIndex="0"
SelectionChanged="OnPlacementChanged" HorizontalAlignment="Stretch">
<ComboBoxItem Content="Top" />
<ComboBoxItem Content="Bottom" />
<ComboBoxItem Content="Left" />
<ComboBoxItem Content="Right" />
</ComboBox>
<Separator />
<TextBlock Text="Status" FontWeight="SemiBold" FontSize="14" />
<TextBlock Name="StatusText"
Text="3 tabs | Selected: Home (0)"
Opacity="0.7"
TextWrapping="Wrap" />
</StackPanel>
</ScrollViewer>
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SemiColorBackground0}" />
<Border Margin="12"
BorderBrush="{DynamicResource SemiColorBorder}"
BorderThickness="1"
CornerRadius="6"
ClipToBounds="True">
<TabbedPage Name="DemoTabs"
TabPlacement="Top"
SelectionChanged="OnSelectionChanged">
<ContentPage Icon="{DynamicResource SemiIconHome}" Header="Home">
<StackPanel Margin="16" Spacing="8">
<TextBlock Text="Home Tab" FontSize="24" FontWeight="Bold" />
<TextBlock Text="Welcome to the Home tab. This is a TabbedPage sample."
TextWrapping="Wrap" />
<TextBlock Text="Use the panel on the right to add or remove tabs dynamically."
TextWrapping="Wrap" Opacity="0.7" />
</StackPanel>
</ContentPage>
<ContentPage Icon="{DynamicResource SemiIconSearch}" Header="Search">
<StackPanel Margin="16" Spacing="8">
<TextBlock Text="Search Tab" FontSize="24" FontWeight="Bold" />
<TextBox PlaceholderText="Type to search..." />
<TextBlock Text="Search results will appear here." Opacity="0.7" />
</StackPanel>
</ContentPage>
<ContentPage Icon="{DynamicResource SemiIconSetting}" Header="Settings">
<StackPanel Margin="16" Spacing="8">
<TextBlock Text="Settings Tab" FontSize="24" FontWeight="Bold" />
<CheckBox Content="Enable notifications" />
<CheckBox Content="Dark mode" />
<CheckBox Content="Auto-save" IsChecked="True" />
</StackPanel>
</ContentPage>
</TabbedPage>
</Border>
</DockPanel>
</UserControl>
@@ -0,0 +1,84 @@
using System.Collections;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
namespace Semi.Avalonia.Demo.Pages;
public partial class TabbedPageDemo : UserControl
{
private int _tabCounter = 3;
public TabbedPageDemo()
{
InitializeComponent();
}
private void OnAddTab(object? sender, RoutedEventArgs e)
{
var idx = ++_tabCounter;
var page = new ContentPage
{
Header = $"Tab {idx}",
Content = new StackPanel
{
Margin = new Thickness(16),
Spacing = 8,
Children =
{
new TextBlock
{
Text = $"Tab {idx}",
FontSize = 24,
FontWeight = FontWeight.Bold,
},
new TextBlock
{
Text = $"This tab was added dynamically (tab #{idx}).",
Opacity = 0.7,
TextWrapping = TextWrapping.Wrap,
}
}
}
};
((IList)DemoTabs.Pages!).Add(page);
UpdateStatus();
}
private void OnRemoveTab(object? sender, RoutedEventArgs e)
{
var pages = (IList)DemoTabs.Pages!;
if (pages.Count > 1)
{
pages.RemoveAt(pages.Count - 1);
UpdateStatus();
}
}
private void OnPlacementChanged(object? sender, SelectionChangedEventArgs e)
{
if (DemoTabs == null) return;
DemoTabs.TabPlacement = PlacementCombo.SelectedIndex switch
{
1 => TabPlacement.Bottom,
2 => TabPlacement.Left,
3 => TabPlacement.Right,
_ => TabPlacement.Top
};
}
private void OnSelectionChanged(object? sender, PageSelectionChangedEventArgs e)
{
UpdateStatus();
}
private void UpdateStatus()
{
if (StatusText == null) return;
var pages = (IList)DemoTabs.Pages!;
var pageName = (DemoTabs.SelectedPage as ContentPage)?.Header?.ToString() ?? "—";
StatusText.Text = $"{pages.Count} tab{(pages.Count != 1 ? "s" : "")} | Selected: {pageName} ({DemoTabs.SelectedIndex})";
}
}
@@ -23,36 +23,36 @@
<TextBox <TextBox
Width="100" Width="100"
Classes="Large" Classes="Large"
Watermark="Large" /> PlaceholderText="Large" />
<TextBox <TextBox
Width="100" Width="100"
Watermark="Default" /> PlaceholderText="Default" />
<TextBox <TextBox
Width="100" Width="100"
Classes="Small" Classes="Small"
Watermark="Small" /> PlaceholderText="Small" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBox <TextBox
Width="100" Width="100"
IsEnabled="False" IsEnabled="False"
Watermark="Disabled" /> PlaceholderText="Disabled" />
<TextBox <TextBox
Width="100" Width="100"
Classes="Bordered" Classes="Bordered"
Watermark="Bordered" /> PlaceholderText="Bordered" />
<TextBox <TextBox
Width="100" Width="100"
Classes="Bordered" Classes="Bordered"
IsEnabled="False" /> IsEnabled="False" />
</StackPanel> </StackPanel>
<TextBox Width="300" Classes="TextArea" Watermark="TextArea TextBox" /> <TextBox Width="300" Classes="TextArea" PlaceholderText="TextArea TextBox" />
<TextBox Width="300" Classes="TextArea ClearButton" Text="TextArea with ClearButton - text should be clearable" /> <TextBox Width="300" Classes="TextArea ClearButton" Text="TextArea with ClearButton - text should be clearable" />
<TextBox <TextBox
Width="300" Width="300"
Theme="{StaticResource LooklessTextBox}" Theme="{StaticResource LooklessTextBox}"
Watermark="Lookless TextBox" PlaceholderText="Lookless TextBox"
InnerLeftContent="https://" InnerLeftContent="https://"
InnerRightContent=".com" /> InnerRightContent=".com" />
</StackPanel> </StackPanel>
@@ -1,126 +0,0 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Semi.Avalonia.Demo.ViewModels"
xmlns:converters="clr-namespace:Semi.Avalonia.Demo.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Semi.Avalonia.Demo.Pages.TreeDataGridDemo"
x:DataType="vm:TreeDataGridDemoViewModel">
<UserControl.Resources>
<converters:FileIconConverter x:Key="FileIconConverter">
<StaticResource x:Key="file" ResourceKey="SemiIconFile" />
<StaticResource x:Key="folderOpen" ResourceKey="SemiIconFolderOpen" />
<StaticResource x:Key="folderClosed" ResourceKey="SemiIconFolder" />
</converters:FileIconConverter>
</UserControl.Resources>
<TabControl>
<TabItem Header="Songs">
<TreeDataGrid
AutoDragDropRows="True"
DataContext="{Binding SongsContext}"
Source="{Binding Songs}">
<TreeDataGrid.Resources>
<DataTemplate x:Key="AlbumCell" DataType="vm:SongViewModel">
<TextBlock
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Background="Transparent"
Text="{Binding Album}" />
</DataTemplate>
<DataTemplate x:Key="AlbumEditCell" DataType="vm:SongViewModel">
<ComboBox
VerticalAlignment="Center"
Classes="Small"
ItemsSource="{x:Static vm:Song.Albums}"
SelectedItem="{Binding Album}" />
</DataTemplate>
<DataTemplate x:Key="CommentsCell" DataType="vm:SongViewModel">
<TextBlock VerticalAlignment="Center" Text="{Binding CountOfComment}" />
</DataTemplate>
<DataTemplate x:Key="CommentsEditCell" DataType="vm:SongViewModel">
<NumericUpDown
Width="100"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Small"
Value="{Binding CountOfComment}" />
</DataTemplate>
</TreeDataGrid.Resources>
<TreeDataGrid.Styles>
<Style Selector="TreeDataGrid TreeDataGridRow:nth-last-child(2n)">
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
</Style>
</TreeDataGrid.Styles>
</TreeDataGrid>
</TabItem>
<TabItem Header="Files">
<Grid DataContext="{Binding FilesContext}" RowDefinitions="Auto, *">
<DockPanel Margin="0,4" DockPanel.Dock="Top">
<ComboBox
DockPanel.Dock="Left"
ItemsSource="{Binding Drives}"
SelectedItem="{Binding SelectedDrive}" />
<TextBox
Margin="4,0,0,0"
VerticalContentAlignment="Center"
KeyDown="SelectedPath_KeyDown"
Text="{Binding SelectedPath, Mode=OneWay}" />
</DockPanel>
<TreeDataGrid
Name="fileViewer"
Grid.Row="1"
Source="{Binding Source}">
<TreeDataGrid.Resources>
<!-- Template for Name column cells -->
<DataTemplate x:Key="FileNameCell" DataType="vm:FileNodeViewModel">
<StackPanel Orientation="Horizontal">
<PathIcon
Theme="{StaticResource InnerPathIcon}"
Margin="8,0">
<PathIcon.Data>
<MultiBinding Converter="{StaticResource FileIconConverter}">
<Binding Path="IsDirectory" />
<Binding Path="IsExpanded" />
</MultiBinding>
</PathIcon.Data>
</PathIcon>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<!-- Edit template for Name column cells -->
<DataTemplate x:Key="FileNameEditCell" DataType="vm:FileNodeViewModel">
<StackPanel Orientation="Horizontal">
<Image Margin="0,0,4,0" VerticalAlignment="Center">
<Image.Source>
<MultiBinding Converter="{StaticResource FileIconConverter}">
<Binding Path="IsDirectory" />
<Binding Path="IsExpanded" />
</MultiBinding>
</Image.Source>
</Image>
<TextBox
VerticalAlignment="Center"
Classes="Small"
Text="{Binding Name}">
<TextBox.Styles>
<Style Selector="DataValidationErrors">
<Setter Property="Theme" Value="{DynamicResource TooltipDataValidationErrors}" />
</Style>
</TextBox.Styles>
</TextBox>
</StackPanel>
</DataTemplate>
</TreeDataGrid.Resources>
<TreeDataGrid.Styles>
<Style Selector="TreeDataGrid TreeDataGridRow:nth-child(2n)">
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
</Style>
</TreeDataGrid.Styles>
</TreeDataGrid>
</Grid>
</TabItem>
</TabControl>
</UserControl>
@@ -1,22 +0,0 @@
using Avalonia.Controls;
using Avalonia.Input;
using Semi.Avalonia.Demo.ViewModels;
namespace Semi.Avalonia.Demo.Pages;
public partial class TreeDataGridDemo : UserControl
{
public TreeDataGridDemo()
{
InitializeComponent();
this.DataContext = new TreeDataGridDemoViewModel();
}
private void SelectedPath_KeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && DataContext is TreeDataGridDemoViewModel vm)
{
vm.FilesContext.SelectedPath = (sender as TextBox)?.Text;
}
}
}
@@ -1,4 +1,4 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -17,7 +17,7 @@
Margin="8" Margin="8"
Classes="ClearButton" Classes="ClearButton"
Text="{Binding SearchText}" Text="{Binding SearchText}"
Watermark="Input Variable Category/ResourceKey/Type/Value/Description" /> PlaceholderText="Input Variable Category/ResourceKey/Type/Value/Description" />
<DataGrid <DataGrid
Grid.Row="1" Grid.Row="1"
@@ -86,8 +86,7 @@
<DataGridTemplateColumn <DataGridTemplateColumn
Width="100" Width="100"
x:DataType="vm:VariableItem" x:DataType="vm:VariableItem"
Header="CopyText" Header="CopyText">
SortMemberPath="Duration">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="vm:VariableItem"> <DataTemplate DataType="vm:VariableItem">
<Button <Button
@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input.Platform;
using Semi.Avalonia.Demo.ViewModels; using Semi.Avalonia.Demo.ViewModels;
namespace Semi.Avalonia.Demo.Pages; namespace Semi.Avalonia.Demo.Pages;
@@ -0,0 +1,31 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Semi.Avalonia.Demo.Pages.WindowCustomizationsPage">
<StackPanel
Spacing="10"
IsEnabled="{OnFormFactor False, Desktop=True}">
<TextBlock Classes="H2" Text="Desktop properties" />
<CheckBox Content="Extend Client Area to Decorations"
IsChecked="{Binding $parent[Window].ExtendClientAreaToDecorationsHint}" />
<Slider IsEnabled="{Binding $parent[Window].ExtendClientAreaToDecorationsHint}"
HorizontalAlignment="Left"
Width="201" Minimum="-1" Maximum="200"
Value="{Binding $parent[Window].ExtendClientAreaTitleBarHeightHint}" />
<CheckBox Content="Can Resize"
IsChecked="{Binding $parent[Window].CanResize}" />
<CheckBox Content="Can Minimize"
IsChecked="{Binding $parent[Window].CanMinimize}" />
<CheckBox Content="Can Maximize"
IsChecked="{Binding $parent[Window].CanMaximize}"
IsEnabled="{Binding $parent[Window].CanResize}" />
</StackPanel>
</UserControl>
@@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace Semi.Avalonia.Demo.Pages
{
public partial class WindowCustomizationsPage : UserControl
{
public WindowCustomizationsPage()
{
InitializeComponent();
}
}
}
@@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -14,19 +13,18 @@
<PackageReference Include="Avalonia"/> <PackageReference Include="Avalonia"/>
<PackageReference Include="Avalonia.Controls.ColorPicker"/> <PackageReference Include="Avalonia.Controls.ColorPicker"/>
<PackageReference Include="Avalonia.Controls.DataGrid"/> <PackageReference Include="Avalonia.Controls.DataGrid"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove AvaloniaUI.DiagnosticsSupport package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics"> <PackageReference Include="AvaloniaUI.DiagnosticsSupport">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm"/> <PackageReference Include="CommunityToolkit.Mvvm"/>
<PackageReference Include="Irihi.Avalonia.Shared"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Semi.Avalonia\Semi.Avalonia.csproj"/> <ProjectReference Include="..\..\src\Semi.Avalonia\Semi.Avalonia.csproj"/>
<ProjectReference Include="..\..\src\Semi.Avalonia.ColorPicker\Semi.Avalonia.ColorPicker.csproj"/> <ProjectReference Include="..\..\src\Semi.Avalonia.ColorPicker\Semi.Avalonia.ColorPicker.csproj"/>
<ProjectReference Include="..\..\src\Semi.Avalonia.DataGrid\Semi.Avalonia.DataGrid.csproj"/> <ProjectReference Include="..\..\src\Semi.Avalonia.DataGrid\Semi.Avalonia.DataGrid.csproj"/>
<ProjectReference Include="..\..\src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj"/> <!-- <ProjectReference Include="..\..\src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj"/>-->
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -0,0 +1,353 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Layout;
using Avalonia.Styling;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Semi.Avalonia.Demo.Pages;
namespace Semi.Avalonia.Demo.ViewModels;
public partial class MainViewModel : ObservableObject
{
private readonly Dictionary<string, NavigationItemViewModel> _itemsByTitle = new(StringComparer.Ordinal);
private readonly IReadOnlyList<NavigationSectionViewModel> _allSections;
[ObservableProperty] public partial string? SearchText { get; set; }
public string DocumentationUrl => "https://docs.irihi.tech/semi";
public string RepoUrl => "https://github.com/irihitech/Semi.Avalonia";
public IReadOnlyList<MenuItemViewModel> MenuItems { get; }
public IReadOnlyList<NavigationSectionViewModel> Sections { get; }
public ObservableCollection<NavigationSectionViewModel> FilteredSections { get; } = [];
public bool ShowEmptySearchState => FilteredSections.Count == 0 && !string.IsNullOrWhiteSpace(SearchText);
public ContentPage? CurrentPage => SelectedItem?.Page;
public string SelectedPageTitle => SelectedItem?.Title ?? "Overview";
public NavigationItemViewModel? SelectedItem
{
get;
private set
{
if (ReferenceEquals(field, value))
{
return;
}
var previous = field;
if (SetProperty(ref field, value))
{
previous?.IsSelected = false;
value?.IsSelected = true;
OnPropertyChanged(nameof(CurrentPage));
OnPropertyChanged(nameof(SelectedPageTitle));
}
}
}
public MainViewModel()
{
MenuItems =
[
new MenuItemViewModel
{
Header = "Theme",
Items =
[
new MenuItemViewModel { Header = "Auto", Command = FollowSystemThemeCommand },
new MenuItemViewModel { Header = "Aquatic", Command = SelectThemeCommand, CommandParameter = SemiTheme.Aquatic },
new MenuItemViewModel { Header = "Desert", Command = SelectThemeCommand, CommandParameter = SemiTheme.Desert },
new MenuItemViewModel { Header = "Dusk", Command = SelectThemeCommand, CommandParameter = SemiTheme.Dusk },
new MenuItemViewModel { Header = "NightSky", Command = SelectThemeCommand, CommandParameter = SemiTheme.NightSky },
]
},
new MenuItemViewModel
{
Header = "Locale",
Items =
[
new MenuItemViewModel { Header = "简体中文", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("zh-CN") },
new MenuItemViewModel { Header = "English", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("en-US") },
new MenuItemViewModel { Header = "日本語", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("ja-JP") },
new MenuItemViewModel { Header = "한국어", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("ko-KR") },
new MenuItemViewModel { Header = "English (UK)", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("en-GB") },
new MenuItemViewModel { Header = "Italiano", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("it-IT") },
new MenuItemViewModel { Header = "Italiano (Switzerland)", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("it-CH") },
new MenuItemViewModel { Header = "Nederlands", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("nl-NL") },
new MenuItemViewModel { Header = "Nederlands (Belgium)", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("nl-BE") },
new MenuItemViewModel { Header = "Українська", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("uk-UA") },
new MenuItemViewModel { Header = "Русский", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("ru-RU") },
new MenuItemViewModel { Header = "繁體中文", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("zh-TW") },
new MenuItemViewModel { Header = "Deutsch", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("de-DE") },
new MenuItemViewModel { Header = "Español", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("es-ES") },
new MenuItemViewModel { Header = "Polski", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("pl-PL") },
new MenuItemViewModel { Header = "Français", Command = SelectLocaleCommand, CommandParameter = new CultureInfo("fr-FR") },
]
}
];
Sections = _allSections =
[
new NavigationSectionViewModel("Overview",
[
CreateItem("Overview", static () => new Overview()),
CreateItem("About Us", static () => new AboutUs()),
]),
new NavigationSectionViewModel("Resource Browser",
[
CreateItem("Palette", static () => new PaletteDemo()),
CreateItem("HighContrastTheme", static () => new HighContrastDemo()),
CreateItem("Variables", static () => new VariablesDemo()),
CreateItem("Icon", static () => new IconDemo()),
]),
new NavigationSectionViewModel("Separate Pack",
[
CreateItem("ColorPicker", static () => new ColorPickerDemo()),
CreateItem("DataGrid", static () => new DataGridDemo()),
]),
new NavigationSectionViewModel("Basic",
[
CreateItem("TextBlock", static () => new TextBlockDemo()),
CreateItem("SelectableTextBlock", static () => new SelectableTextBlockDemo()),
CreateItem("Border", static () => new BorderDemo()),
CreateItem("PathIcon", static () => new PathIconDemo()),
]),
new NavigationSectionViewModel("Button",
[
CreateItem("Button", static () => new ButtonDemo()),
CreateItem("HyperlinkButton", static () => new HyperlinkButtonDemo()),
CreateItem("CheckBox", static () => new CheckBoxDemo()),
CreateItem("RadioButton", static () => new RadioButtonDemo()),
CreateItem("ToggleSwitch", static () => new ToggleSwitchDemo()),
]),
new NavigationSectionViewModel("Input",
[
CreateItem("TextBox", static () => new TextBoxDemo()),
CreateItem("AutoCompleteBox", static () => new AutoCompleteBoxDemo()),
CreateItem("ComboBox", static () => new ComboBoxDemo()),
CreateItem("ButtonSpinner", static () => new ButtonSpinnerDemo()),
CreateItem("NumericUpDown", static () => new NumericUpDownDemo()),
CreateItem("Slider", static () => new SliderDemo()),
CreateItem("ManagedFileChooser", static () => new ManagedFileChooserDemo()),
]),
new NavigationSectionViewModel("Date/Time",
[
CreateItem("Calendar", static () => new CalendarDemo()),
CreateItem("CalendarDatePicker", static () => new CalendarDatePickerDemo()),
CreateItem("DatePicker", static () => new DatePickerDemo()),
CreateItem("TimePicker", static () => new TimePickerDemo()),
]),
new NavigationSectionViewModel("Navigation",
[
CreateItem("ContentPage", static () => new ContentPageDemo()),
CreateItem("CarouselPage", static () => new CarouselPageDemo()),
CreateItem("DrawerPage", static () => new DrawerPageDemo()),
CreateItem("NavigationPage", static () => new NavigationPageDemo()),
CreateItem("TabbedPage", static () => new TabbedPageDemo()),
CreateItem("TabControl", static () => new TabControlDemo()),
CreateItem("TabStrip", static () => new TabStripDemo()),
CreateItem("TreeView", static () => new TreeViewDemo()),
]),
new NavigationSectionViewModel("Show",
[
CreateItem("Carousel", static () => new CarouselDemo()),
CreateItem("PipsPager", static () => new PipsPagerDemo()),
CreateItem("Expander", static () => new ExpanderDemo()),
CreateItem("Flyout", static () => new FlyoutDemo()),
CreateItem("HeaderedContentControl", static () => new HeaderedContentControlDemo()),
CreateItem("Label", static () => new LabelDemo()),
CreateItem("ListBox", static () => new ListBoxDemo()),
CreateItem("SplitView", static () => new SplitViewDemo()),
CreateItem("ToolTip", static () => new ToolTipDemo()),
]),
new NavigationSectionViewModel("Feedback",
[
CreateItem("DataValidationErrors", static () => new DataValidationErrorsDemo()),
CreateItem("Notification", static () => new NotificationDemo()),
CreateItem("ProgressBar", static () => new ProgressBarDemo()),
CreateItem("RefreshContainer", static () => new RefreshContainerDemo()),
]),
new NavigationSectionViewModel("Other",
[
CreateItem("CommandBar", static () => new CommandBarDemo()),
CreateItem("GridSplitter", static () => new GridSplitterDemo()),
CreateItem("Menu", static () => new MenuDemo()),
CreateItem("ScrollViewer", static () => new ScrollViewerDemo()),
CreateItem("ThemeVariantScope", static () => new ThemeVariantDemo()),
CreateItem("WindowCustomizationsPage", static () => new WindowCustomizationsPage()),
]),
];
SelectedItem = Sections[0].Items[0];
RefreshFilteredSections();
}
public bool TryNavigateTo(string title)
{
if (_itemsByTitle.TryGetValue(title, out var item))
{
SelectedItem = item;
return true;
}
return false;
}
partial void OnSearchTextChanged(string? value)
{
RefreshFilteredSections();
}
[RelayCommand]
private void NavigateTo(object? parameter)
{
if (parameter is NavigationItemViewModel item)
{
SelectedItem = item;
}
}
[RelayCommand]
private void FollowSystemTheme()
{
Application.Current?.RegisterFollowSystemTheme();
}
[RelayCommand]
private void ToggleTheme()
{
var app = Application.Current;
if (app is null) return;
var theme = app.ActualThemeVariant;
app.RequestedThemeVariant = theme == ThemeVariant.Dark ? ThemeVariant.Light : ThemeVariant.Dark;
app.UnregisterFollowSystemTheme();
}
[RelayCommand]
private void SelectTheme(object? obj)
{
var app = Application.Current;
if (app is null) return;
app.RequestedThemeVariant = obj as ThemeVariant;
app.UnregisterFollowSystemTheme();
}
[RelayCommand]
private void SelectLocale(object? obj)
{
var app = Application.Current;
if (app is null) return;
SemiTheme.OverrideLocaleResources(app, obj as CultureInfo);
}
[RelayCommand]
private static async Task OpenUrl(string url)
{
var launcher = ResolveDefaultTopLevel()?.Launcher;
if (launcher is not null)
{
await launcher.LaunchUriAsync(new Uri(url));
}
}
private NavigationItemViewModel CreateItem(string title, Func<Control> contentFactory)
{
var item = new NavigationItemViewModel(title, NavigateToCommand, contentFactory);
_itemsByTitle.Add(title, item);
return item;
}
private void RefreshFilteredSections()
{
var search = string.IsNullOrWhiteSpace(SearchText) ? string.Empty : SearchText.Trim();
FilteredSections.Clear();
foreach (var section in _allSections)
{
if (search.Length == 0 ||
section.Header.Contains(search, StringComparison.InvariantCultureIgnoreCase))
{
FilteredSections.Add(section);
continue;
}
var matchedItems = section.Items
.Where(item => item.Title.Contains(search, StringComparison.InvariantCultureIgnoreCase))
.ToArray();
if (matchedItems.Length > 0)
{
FilteredSections.Add(new NavigationSectionViewModel(section.Header, matchedItems));
}
}
OnPropertyChanged(nameof(ShowEmptySearchState));
}
private static TopLevel? ResolveDefaultTopLevel()
{
return Application.Current?.ApplicationLifetime switch
{
IClassicDesktopStyleApplicationLifetime desktopLifetime => desktopLifetime.MainWindow,
ISingleViewApplicationLifetime singleView => TopLevel.GetTopLevel(singleView.MainView),
_ => null
};
}
}
public class NavigationSectionViewModel
{
public NavigationSectionViewModel(string header, IReadOnlyList<NavigationItemViewModel> items)
{
Header = header;
Items = items;
}
public string Header { get; }
public IReadOnlyList<NavigationItemViewModel> Items { get; }
}
public partial class NavigationItemViewModel : ObservableObject
{
private readonly Func<Control> _contentFactory;
public NavigationItemViewModel(string title, ICommand navigateCommand, Func<Control> contentFactory)
{
Title = title;
NavigateCommand = navigateCommand;
_contentFactory = contentFactory;
}
public string Title { get; }
public ICommand NavigateCommand { get; }
public ContentPage Page => field ??= new ContentPage
{
Header = Title,
Background = null,
HorizontalContentAlignment = HorizontalAlignment.Stretch,
VerticalContentAlignment = VerticalAlignment.Stretch,
Content = _contentFactory()
};
[ObservableProperty] public partial bool IsSelected { get; set; }
}
public class MenuItemViewModel
{
public string? Header { get; set; }
public ICommand? Command { get; set; }
public object? CommandParameter { get; set; }
public IList<MenuItemViewModel>? Items { get; set; }
}
@@ -14,6 +14,8 @@ namespace Semi.Avalonia.Demo.ViewModels;
public partial class PaletteDemoViewModel : ObservableObject public partial class PaletteDemoViewModel : ObservableObject
{ {
public static Lazy<PaletteDemoViewModel> Instance { get; } = new(() => new PaletteDemoViewModel());
public bool IsInitialized { get; private set; }
private readonly string[] _predefinedColorNames = private readonly string[] _predefinedColorNames =
[ [
"Red", "Pink", "Purple", "Violet", "Indigo", "Red", "Pink", "Purple", "Violet", "Indigo",
@@ -44,6 +46,7 @@ public partial class PaletteDemoViewModel : ObservableObject
InitializePalette(); InitializePalette();
InitializeFunctionalColors(); InitializeFunctionalColors();
InitializeShadows(); InitializeShadows();
IsInitialized = true;
} }
private void InitializePalette() private void InitializePalette()
@@ -289,4 +292,4 @@ public partial class ShadowGroupViewModel : ObservableObject
} }
} }
} }
} }
@@ -1,363 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Controls.Models.TreeDataGrid;
using Avalonia.Controls.Selection;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Semi.Avalonia.Demo.ViewModels;
public partial class FilesPageViewModel : ObservableObject
{
public IList<string> Drives { get; }
public HierarchicalTreeDataGridSource<FileNodeViewModel> Source { get; }
[ObservableProperty] private string _selectedDrive;
private string? _selectedPath;
[ObservableProperty] private FileNodeViewModel? _root;
public string? SelectedPath
{
get => _selectedPath;
set => SetSelectedPath(value);
}
partial void OnSelectedDriveChanged(string value)
{
Root = new FileNodeViewModel(value, true, true);
if (Source is not null)
{
Source.Items = [Root];
}
}
public FilesPageViewModel()
{
Drives = DriveInfo.GetDrives().Select(x => x.Name).ToList();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
SelectedDrive = @"C:\";
}
else
{
SelectedDrive = Drives.FirstOrDefault() ?? "/";
}
Source = new HierarchicalTreeDataGridSource<FileNodeViewModel>([])
{
Columns =
{
new CheckBoxColumn<FileNodeViewModel>(
null,
x => x.IsChecked,
(o, v) => o.IsChecked = v,
options: new CheckBoxColumnOptions<FileNodeViewModel>
{
CanUserResizeColumn = false,
}),
new HierarchicalExpanderColumn<FileNodeViewModel>(
new TemplateColumn<FileNodeViewModel>(
"Name",
"FileNameCell",
"FileNameEditCell",
new GridLength(1, GridUnitType.Star),
new TemplateColumnOptions<FileNodeViewModel>
{
CompareAscending = FileNodeViewModel.SortAscending(vm => vm.Name),
CompareDescending = FileNodeViewModel.SortDescending(vm => vm.Name),
IsTextSearchEnabled = true,
TextSearchValueSelector = vm => vm.Name
}),
vm => vm.Children,
vm => vm.HasChildren,
vm => vm.IsExpanded),
new TextColumn<FileNodeViewModel, long?>(
"Size",
vm => vm.Size,
options: new TextColumnOptions<FileNodeViewModel>
{
CompareAscending = FileNodeViewModel.SortAscending(x => x.Size),
CompareDescending = FileNodeViewModel.SortDescending(x => x.Size),
}),
new TextColumn<FileNodeViewModel, DateTimeOffset?>(
"Modified",
x => x.Modified,
options: new TextColumnOptions<FileNodeViewModel>
{
CompareAscending = FileNodeViewModel.SortAscending(x => x.Modified),
CompareDescending = FileNodeViewModel.SortDescending(x => x.Modified),
}),
}
};
Source.RowSelection!.SingleSelect = false;
Source.RowSelection.SelectionChanged += SelectionChanged;
}
private void SelectionChanged(object? sender, TreeSelectionModelSelectionChangedEventArgs<FileNodeViewModel> e)
{
var selectedPath = Source.RowSelection?.SelectedItem?.Path;
this.SetProperty(ref _selectedPath, selectedPath, nameof(SelectedPath));
foreach (var i in e.DeselectedItems)
Trace.WriteLine($"Deselected '{i?.Path}'");
foreach (var i in e.SelectedItems)
Trace.WriteLine($"Selected '{i?.Path}'");
}
private void SetSelectedPath(string? path)
{
if (string.IsNullOrEmpty(path))
{
Source.RowSelection!.Clear();
return;
}
var components = new Stack<string>();
DirectoryInfo? d = null;
if (File.Exists(path))
{
var f = new FileInfo(path);
components.Push(f.Name);
d = f.Directory;
}
else if (Directory.Exists(path))
{
d = new DirectoryInfo(path);
}
while (d is not null)
{
components.Push(d.Name);
d = d.Parent;
}
var index = IndexPath.Unselected;
if (components.Count > 0)
{
var drive = components.Pop();
var driveIndex = Drives.FindIndex(x => string.Equals(x, drive, StringComparison.OrdinalIgnoreCase));
if (driveIndex >= 0)
SelectedDrive = Drives[driveIndex];
var node = Root;
index = new IndexPath(0);
while (node is not null && components.Count > 0)
{
node.IsExpanded = true;
var component = components.Pop();
var i = node.Children.FindIndex(x => string.Equals(x.Name, component, StringComparison.OrdinalIgnoreCase));
node = i >= 0 ? node.Children[i] : null;
index = i >= 0 ? index.Append(i) : default;
}
}
Source.Items = [Root!];
Source.RowSelection!.SelectedIndex = index;
}
}
public partial class FileNodeViewModel : ObservableObject, IEditableObject
{
[ObservableProperty] private string _path;
[ObservableProperty] private string _name;
private string? _undoName;
[ObservableProperty] private long? _size;
[ObservableProperty] private DateTimeOffset? _modified;
private FileSystemWatcher? _watcher;
private ObservableCollection<FileNodeViewModel>? _children;
[ObservableProperty] private bool _hasChildren = true;
[ObservableProperty] private bool _isExpanded;
public FileNodeViewModel(string path, bool isDirectory, bool isRoot = false)
{
Path = path;
Name = isRoot ? path : System.IO.Path.GetFileName(Path);
IsExpanded = isRoot;
IsDirectory = isDirectory;
HasChildren = isDirectory;
if (!isDirectory)
{
var info = new FileInfo(path);
Size = info.Length;
Modified = info.LastWriteTimeUtc;
}
}
public bool IsChecked { get; set; }
public bool IsDirectory { get; }
public IReadOnlyList<FileNodeViewModel> Children => _children ??= LoadChildren();
private ObservableCollection<FileNodeViewModel> LoadChildren()
{
if (!IsDirectory)
{
throw new NotSupportedException();
}
var options = new EnumerationOptions { IgnoreInaccessible = true };
var result = new ObservableCollection<FileNodeViewModel>();
foreach (var d in Directory.EnumerateDirectories(Path, "*", options))
{
result.Add(new FileNodeViewModel(d, true));
}
foreach (var f in Directory.EnumerateFiles(Path, "*", options))
{
result.Add(new FileNodeViewModel(f, false));
}
_watcher = new FileSystemWatcher
{
Path = Path,
NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite,
};
_watcher.Changed += OnChanged;
_watcher.Created += OnCreated;
_watcher.Deleted += OnDeleted;
_watcher.Renamed += OnRenamed;
_watcher.EnableRaisingEvents = true;
if (result.Count == 0)
HasChildren = false;
return result;
}
public static Comparison<FileNodeViewModel?> SortAscending<T>(Func<FileNodeViewModel, T> selector)
{
return (x, y) =>
{
if (x is null && y is null)
return 0;
else if (x is null)
return -1;
else if (y is null)
return 1;
if (x.IsDirectory == y.IsDirectory)
return Comparer<T>.Default.Compare(selector(x), selector(y));
else if (x.IsDirectory)
return -1;
else
return 1;
};
}
public static Comparison<FileNodeViewModel?> SortDescending<T>(Func<FileNodeViewModel, T> selector)
{
return (x, y) =>
{
if (x is null && y is null)
return 0;
else if (x is null)
return 1;
else if (y is null)
return -1;
if (x.IsDirectory == y.IsDirectory)
return Comparer<T>.Default.Compare(selector(y), selector(x));
else if (x.IsDirectory)
return -1;
else
return 1;
};
}
void IEditableObject.BeginEdit() => _undoName = Name;
void IEditableObject.CancelEdit() => Name = _undoName ?? string.Empty;
void IEditableObject.EndEdit() => _undoName = null;
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Changed && File.Exists(e.FullPath))
{
Dispatcher.UIThread.Post(() =>
{
foreach (var child in _children!)
{
if (child.Path == e.FullPath)
{
if (!child.IsDirectory)
{
var info = new FileInfo(e.FullPath);
child.Size = info.Length;
child.Modified = info.LastWriteTimeUtc;
}
break;
}
}
});
}
}
private void OnCreated(object sender, FileSystemEventArgs e)
{
Dispatcher.UIThread.Post(() =>
{
var node = new FileNodeViewModel(
e.FullPath,
File.GetAttributes(e.FullPath).HasFlag(FileAttributes.Directory));
_children!.Add(node);
});
}
private void OnDeleted(object sender, FileSystemEventArgs e)
{
Dispatcher.UIThread.Post(() =>
{
for (var i = 0; i < _children!.Count; ++i)
{
if (_children[i].Path == e.FullPath)
{
_children.RemoveAt(i);
Debug.WriteLine($"Removed {e.FullPath}");
break;
}
}
});
}
private void OnRenamed(object sender, RenamedEventArgs e)
{
Dispatcher.UIThread.Post(() =>
{
foreach (var child in _children!)
{
if (child.Path == e.OldFullPath)
{
child.Path = e.FullPath;
child.Name = e.Name ?? string.Empty;
break;
}
}
});
}
}
internal static class ListExtensions
{
public static int FindIndex<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int i = 0;
foreach (var item in source)
{
if (predicate(item))
return i;
i++;
}
return -1;
}
}
@@ -1,54 +0,0 @@
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Controls.Models.TreeDataGrid;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Semi.Avalonia.Demo.ViewModels;
public class SongsPageViewModel : ObservableObject
{
public FlatTreeDataGridSource<SongViewModel> Songs { get; }
public SongsPageViewModel()
{
var songs = new ObservableCollection<SongViewModel>(Song.Songs.Select(a => new SongViewModel()
{
Title = a.Title,
Artist = a.Artist,
Album = a.Album,
CountOfComment = a.CountOfComment,
IsSelected = false
}));
Songs = new FlatTreeDataGridSource<SongViewModel>(songs)
{
Columns =
{
new CheckBoxColumn<SongViewModel>(
"IsSelected",
a => a.IsSelected,
(model, b) => { model.IsSelected = b; },
new GridLength(108, GridUnitType.Pixel)),
new TextColumn<SongViewModel, string>(
"Title",
a => a.Title,
(o, a) => o.Title = a,
new GridLength(6, GridUnitType.Star)),
new TextColumn<SongViewModel, string>("Artist",
a => a.Artist,
(o, a) => o.Artist = a,
new GridLength(6, GridUnitType.Star)),
new TemplateColumn<SongViewModel>("Album",
"AlbumCell",
"AlbumEditCell",
new GridLength(6, GridUnitType.Star)),
new TemplateColumn<SongViewModel>(
"Comments",
"CommentsCell",
"CommentsEditCell",
new GridLength(6, GridUnitType.Star)),
}
};
}
}
@@ -1,9 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Semi.Avalonia.Demo.ViewModels;
public class TreeDataGridDemoViewModel : ObservableObject
{
public SongsPageViewModel SongsContext { get; } = new();
public FilesPageViewModel FilesContext { get; } = new();
}
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using Avalonia; using Avalonia;
+131 -272
View File
@@ -4,283 +4,142 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="using:Semi.Avalonia.Demo.Pages" xmlns:vm="clr-namespace:Semi.Avalonia.Demo.ViewModels"
xmlns:views="clr-namespace:Semi.Avalonia.Demo.Views"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
x:DataType="views:MainViewModel" x:DataType="vm:MainViewModel"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Styles>
<ControlTheme x:Key="CategoryTabItem" TargetType="TabItem"> <Style Selector="TextBlock.NavSectionHeader">
<Setter Property="IsEnabled" Value="False" /> <Setter Property="Margin" Value="12,10,12,2" />
<Setter Property="Template"> <Setter Property="FontSize" Value="12" />
<ControlTemplate TargetType="TabItem"> <Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="{DynamicResource SemiColorText1}" />
</Style>
<Style Selector="Border.NavItemHost">
<Setter Property="Margin" Value="6,0" />
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="Border.NavItemHost.Selected">
<Setter Property="Background" Value="{DynamicResource SemiColorPrimaryLight}" />
</Style>
<Style Selector="Button.NavItem">
<Setter Property="Theme" Value="{DynamicResource BorderlessButton}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="Padding" Value="12,8" />
<Setter Property="Foreground" Value="{DynamicResource SemiColorText0}" />
</Style>
<Style Selector="Button.NavItem.Selected">
<Setter Property="Foreground" Value="{DynamicResource SemiColorPrimary}" />
</Style>
</UserControl.Styles>
<DrawerPage
Name="MainDrawer"
Margin="8"
Background="Transparent"
Content="{Binding CurrentPage}"
DrawerLayoutBehavior="{OnFormFactor Split, Mobile=Overlay}"
DrawerLength="300"
IsOpen="True">
<DrawerPage.Header>
<StackPanel Orientation="Horizontal" Spacing="8">
<SelectableTextBlock
VerticalAlignment="Center"
Classes="H6"
Text="Semi Avalonia"
Theme="{DynamicResource TitleSelectableTextBlock}" />
<TextBlock VerticalAlignment="Center" Text="/" />
<SelectableTextBlock
VerticalAlignment="Center"
Classes="Secondary"
Text="{Binding SelectedPageTitle}" />
</StackPanel>
</DrawerPage.Header>
<DrawerPage.DrawerHeader>
<TextBox
Margin="8"
Classes="ClearButton"
PlaceholderText="Search demos or sections"
Text="{Binding SearchText}" />
</DrawerPage.DrawerHeader>
<DrawerPage.Drawer>
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
<StackPanel>
<ItemsControl ItemsSource="{Binding FilteredSections}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:NavigationSectionViewModel">
<StackPanel Margin="0,0,0,10">
<TextBlock Classes="NavSectionHeader" Text="{Binding Header}" />
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:NavigationItemViewModel">
<Border Classes="NavItemHost" Classes.Selected="{Binding IsSelected}">
<Button
Classes="NavItem"
FontWeight="Normal"
Classes.Selected="{Binding IsSelected}"
Command="{Binding NavigateCommand}"
CommandParameter="{Binding}"
Content="{Binding Title}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock <TextBlock
FontWeight="Bold" Margin="16,12,16,0"
FontSize="12" Foreground="{DynamicResource SemiColorText1}"
Margin="4" IsVisible="{Binding ShowEmptySearchState}"
Text="{TemplateBinding Header}" /> Text="No demo pages matched your search." />
</ControlTemplate>
</Setter>
<Style Selector="^:disabled /template/ TextBlock">
<Setter Property="Foreground" Value="{DynamicResource SemiColorText1}" />
</Style>
</ControlTheme>
</UserControl.Resources>
<Grid RowDefinitions="Auto, *">
<Border
Grid.Row="0"
Margin="8"
Padding="12,4"
Theme="{DynamicResource CardBorder}">
<Panel>
<StackPanel Orientation="Horizontal" Spacing="8">
<ToggleSwitch
Name="ExpandButton"
Theme="{DynamicResource IconBorderlessToggleSwitch}"
Content="{StaticResource SemiIconSidebar}" />
<SelectableTextBlock
VerticalAlignment="Center"
Classes="H6"
Text="Semi Avalonia"
Theme="{DynamicResource TitleSelectableTextBlock}" />
<SelectableTextBlock
VerticalAlignment="Center"
Text="/" />
<SelectableTextBlock
VerticalAlignment="Center"
Classes="Secondary"
Text="{ReflectionBinding #tab.SelectedItem.Header}" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> </ScrollViewer>
<Button </DrawerPage.Drawer>
Theme="{DynamicResource IconBorderlessButton}"
Command="{Binding OpenUrlCommand}"
CommandParameter="{Binding DocumentationUrl}"
Content="{StaticResource SemiIconGlobe}" />
<Button <DrawerPage.DrawerFooter>
Theme="{DynamicResource IconBorderlessButton}" <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
Command="{Binding OpenUrlCommand}" <Button
CommandParameter="{Binding RepoUrl}" Command="{Binding OpenUrlCommand}"
Content="{StaticResource SemiIconGithubLogo}" /> CommandParameter="{Binding DocumentationUrl}"
Content="{StaticResource SemiIconGlobe}"
Theme="{DynamicResource IconBorderlessButton}" />
<ToggleSwitch <Button
Theme="{DynamicResource IconBorderlessToggleSwitch}" Command="{Binding OpenUrlCommand}"
Command="{Binding ToggleThemeCommand}" CommandParameter="{Binding RepoUrl}"
OnContent="{StaticResource SemiIconMoon}" Content="{StaticResource SemiIconGithubLogo}"
OffContent="{StaticResource SemiIconSun}" /> Theme="{DynamicResource IconBorderlessButton}" />
<Button <ToggleSwitch
Theme="{DynamicResource IconBorderlessButton}" Command="{Binding ToggleThemeCommand}"
Content="{StaticResource SemiIconMenu}"> OffContent="{StaticResource SemiIconSun}"
<Button.Flyout> OnContent="{StaticResource SemiIconMoon}"
<MenuFlyout Placement="Bottom" ItemsSource="{Binding MenuItems}" /> Theme="{DynamicResource IconBorderlessToggleSwitch}" />
</Button.Flyout>
<Button.Styles> <Button Content="{StaticResource SemiIconMenu}" Theme="{DynamicResource IconBorderlessButton}">
<Style Selector="MenuItem" x:DataType="views:MenuItemViewModel"> <Button.Flyout>
<Setter Property="Header" Value="{Binding Header}" /> <MenuFlyout ItemsSource="{Binding MenuItems}" Placement="Bottom" />
<Setter Property="ItemsSource" Value="{Binding Items}" /> </Button.Flyout>
<Setter Property="Command" Value="{Binding Command}" /> <Button.Styles>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}" /> <Style x:DataType="vm:MenuItemViewModel" Selector="MenuItem">
</Style> <Setter Property="Header" Value="{Binding Header}" />
</Button.Styles> <Setter Property="ItemsSource" Value="{Binding Items}" />
</Button> <Setter Property="Command" Value="{Binding Command}" />
</StackPanel> <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
</Panel> </Style>
</Border> </Button.Styles>
<TabControl </Button>
Name="tab" </StackPanel>
Grid.Row="1" </DrawerPage.DrawerFooter>
Margin="8" </DrawerPage>
Padding="20,0,0,0" </UserControl>
TabStripPlacement="Left"
Classes.Dismiss="{Binding #ExpandButton.IsChecked}"
Theme="{DynamicResource ScrollLineTabControl}">
<TabControl.Styles>
<Style Selector=".Dismiss /template/ ScrollViewer#PART_ScrollViewer">
<Setter Property="IsVisible" Value="False" />
</Style>
</TabControl.Styles>
<TabControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</TabControl.ItemsPanel>
<TabItem Header="Overview">
<pages:Overview />
</TabItem>
<TabItem Header="About Us">
<pages:AboutUs />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Resource Browser" />
<TabItem Header="Palette">
<pages:PaletteDemo />
</TabItem>
<TabItem Header="HighContrastTheme">
<pages:HighContrastDemo />
</TabItem>
<TabItem Header="Variables">
<pages:VariablesDemo />
</TabItem>
<TabItem Header="Icon">
<pages:IconDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Separate Pack" />
<TabItem Header="ColorPicker">
<pages:ColorPickerDemo />
</TabItem>
<TabItem Header="DataGrid">
<pages:DataGridDemo />
</TabItem>
<TabItem Header="TreeDataGrid">
<pages:TreeDataGridDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Basic" />
<TabItem Header="TextBlock">
<pages:TextBlockDemo />
</TabItem>
<TabItem Header="SelectableTextBlock">
<pages:SelectableTextBlockDemo />
</TabItem>
<TabItem Header="Border">
<pages:BorderDemo />
</TabItem>
<TabItem Header="PathIcon">
<pages:PathIconDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Button" />
<TabItem Header="Button">
<pages:ButtonDemo />
</TabItem>
<TabItem Header="HyperlinkButton">
<pages:HyperlinkButtonDemo />
</TabItem>
<TabItem Header="CheckBox">
<pages:CheckBoxDemo />
</TabItem>
<TabItem Header="RadioButton">
<pages:RadioButtonDemo />
</TabItem>
<TabItem Header="ToggleSwitch">
<pages:ToggleSwitchDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Input" />
<TabItem Header="TextBox">
<pages:TextBoxDemo />
</TabItem>
<TabItem Header="AutoCompleteBox">
<pages:AutoCompleteBoxDemo />
</TabItem>
<TabItem Header="ComboBox">
<pages:ComboBoxDemo />
</TabItem>
<TabItem Header="ButtonSpinner">
<pages:ButtonSpinnerDemo />
</TabItem>
<TabItem Header="NumericUpDown">
<pages:NumericUpDownDemo />
</TabItem>
<TabItem Header="Slider">
<pages:SliderDemo />
</TabItem>
<TabItem Header="ManagedFileChooser">
<pages:ManagedFileChooserDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Date/Time" />
<TabItem Header="Calendar">
<pages:CalendarDemo />
</TabItem>
<TabItem Header="CalendarDatePicker">
<pages:CalendarDatePickerDemo />
</TabItem>
<TabItem Header="DatePicker">
<pages:DatePickerDemo />
</TabItem>
<TabItem Header="TimePicker">
<pages:TimePickerDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Navigation" />
<TabItem Header="TabControl">
<pages:TabControlDemo />
</TabItem>
<TabItem Header="TabStrip">
<pages:TabStripDemo />
</TabItem>
<TabItem Header="TreeView">
<pages:TreeViewDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Show" />
<TabItem Header="Carousel">
<pages:CarouselDemo />
</TabItem>
<TabItem Header="Expander">
<pages:ExpanderDemo />
</TabItem>
<TabItem Header="Flyout">
<pages:FlyoutDemo />
</TabItem>
<TabItem Header="HeaderedContentControl">
<pages:HeaderedContentControlDemo />
</TabItem>
<TabItem Header="Label">
<pages:LabelDemo />
</TabItem>
<TabItem Header="ListBox">
<pages:ListBoxDemo />
</TabItem>
<TabItem Header="SplitView">
<pages:SplitViewDemo />
</TabItem>
<TabItem Header="ToolTip">
<pages:ToolTipDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Feedback" />
<TabItem Header="DataValidationErrors">
<pages:DataValidationErrorsDemo />
</TabItem>
<TabItem Header="Notification">
<pages:NotificationDemo />
</TabItem>
<TabItem Header="ProgressBar">
<pages:ProgressBarDemo />
</TabItem>
<TabItem Header="RefreshContainer">
<pages:RefreshContainerDemo />
</TabItem>
<TabItem
Theme="{DynamicResource CategoryTabItem}"
Header="Other" />
<TabItem Header="GridSplitter">
<pages:GridSplitterDemo />
</TabItem>
<TabItem Header="Menu">
<pages:MenuDemo />
</TabItem>
<TabItem Header="ScrollViewer">
<pages:ScrollViewerDemo />
</TabItem>
<TabItem Header="ThemeVariantScope">
<pages:ThemeVariantDemo />
</TabItem>
</TabControl>
</Grid>
</UserControl>
+5 -233
View File
@@ -1,250 +1,22 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Styling;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Semi.Avalonia.Demo.ViewModels;
namespace Semi.Avalonia.Demo.Views; namespace Semi.Avalonia.Demo.Views;
public partial class MainView : UserControl public partial class MainView : UserControl
{ {
private readonly MainViewModel _viewModel;
public MainView() public MainView()
{ {
InitializeComponent(); InitializeComponent();
this.DataContext = new MainViewModel(); DataContext = _viewModel = new MainViewModel();
WeakReferenceMessenger.Default.Register<string, string>(this, "JumpTo", MessageHandler); WeakReferenceMessenger.Default.Register<string, string>(this, "JumpTo", MessageHandler);
} }
private void MessageHandler(object _, string message) private void MessageHandler(object _, string message)
{ {
foreach (var item in tab.ItemsView) _viewModel.TryNavigateTo(message);
{
if (item is TabItem tabItem && tabItem.Header is not null && tabItem.Header.Equals(message))
{
tab.SelectedItem = tabItem;
break;
}
}
} }
} }
public partial class MainViewModel : ObservableObject
{
public string DocumentationUrl => "https://docs.irihi.tech/semi";
public string RepoUrl => "https://github.com/irihitech/Semi.Avalonia";
public IReadOnlyList<MenuItemViewModel> MenuItems { get; }
public MainViewModel()
{
MenuItems =
[
new MenuItemViewModel
{
Header = "Theme",
Items =
[
new MenuItemViewModel
{
Header = "Auto",
Command = FollowSystemThemeCommand
},
new MenuItemViewModel
{
Header = "Aquatic",
Command = SelectThemeCommand,
CommandParameter = SemiTheme.Aquatic
},
new MenuItemViewModel
{
Header = "Desert",
Command = SelectThemeCommand,
CommandParameter = SemiTheme.Desert
},
new MenuItemViewModel
{
Header = "Dusk",
Command = SelectThemeCommand,
CommandParameter = SemiTheme.Dusk
},
new MenuItemViewModel
{
Header = "NightSky",
Command = SelectThemeCommand,
CommandParameter = SemiTheme.NightSky
},
]
},
new MenuItemViewModel
{
Header = "Locale",
Items =
[
new MenuItemViewModel
{
Header = "简体中文",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("zh-CN")
},
new MenuItemViewModel
{
Header = "English",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("en-US")
},
new MenuItemViewModel
{
Header = "日本語",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ja-JP")
},
new MenuItemViewModel
{
Header = "한국어",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ko-KR")
},
new MenuItemViewModel
{
Header = "English (UK)",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("en-GB")
},
new MenuItemViewModel
{
Header = "Italiano",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("it-IT")
},
new MenuItemViewModel
{
Header = "Italiano (Switzerland)",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("it-CH")
},
new MenuItemViewModel
{
Header = "Nederlands",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("nl-NL")
},
new MenuItemViewModel
{
Header = "Nederlands (Belgium)",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("nl-BE")
},
new MenuItemViewModel
{
Header = "Українська",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("uk-UA")
},
new MenuItemViewModel
{
Header = "Русский",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ru-RU")
},
new MenuItemViewModel
{
Header = "繁體中文",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("zh-TW")
},
new MenuItemViewModel
{
Header = "Deutsch",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("de-DE")
},
new MenuItemViewModel
{
Header = "Español",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("es-ES")
},
new MenuItemViewModel
{
Header = "Polski",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("pl-PL")
},
new MenuItemViewModel
{
Header = "Français",
Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("fr-FR")
},
]
}
];
}
[RelayCommand]
private void FollowSystemTheme()
{
Application.Current?.RegisterFollowSystemTheme();
}
[RelayCommand]
private void ToggleTheme()
{
var app = Application.Current;
if (app is null) return;
var theme = app.ActualThemeVariant;
app.RequestedThemeVariant = theme == ThemeVariant.Dark ? ThemeVariant.Light : ThemeVariant.Dark;
app.UnregisterFollowSystemTheme();
}
[RelayCommand]
private void SelectTheme(object? obj)
{
var app = Application.Current;
if (app is null) return;
app.RequestedThemeVariant = obj as ThemeVariant;
app.UnregisterFollowSystemTheme();
}
[RelayCommand]
private void SelectLocale(object? obj)
{
var app = Application.Current;
if (app is null) return;
SemiTheme.OverrideLocaleResources(app, obj as CultureInfo);
}
[RelayCommand]
private static async Task OpenUrl(string url)
{
var launcher = ResolveDefaultTopLevel()?.Launcher;
if (launcher is not null)
{
await launcher.LaunchUriAsync(new Uri(url));
}
}
private static TopLevel? ResolveDefaultTopLevel()
{
return Application.Current?.ApplicationLifetime switch
{
IClassicDesktopStyleApplicationLifetime desktopLifetime => desktopLifetime.MainWindow,
ISingleViewApplicationLifetime singleView => TopLevel.GetTopLevel(singleView.MainView),
_ => null
};
}
}
public class MenuItemViewModel
{
public string? Header { get; set; }
public ICommand? Command { get; set; }
public object? CommandParameter { get; set; }
public IList<MenuItemViewModel>? Items { get; set; }
}
@@ -5,10 +5,11 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:Semi.Avalonia.Demo.Views" xmlns:views="clr-namespace:Semi.Avalonia.Demo.Views"
Title="Semi.Avalonia.Demo" Title="Semi Avalonia Demo"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
ExtendClientAreaToDecorationsHint="True"
Icon="/Assets/irihi.ico" Icon="/Assets/irihi.ico"
mc:Ignorable="d"> mc:Ignorable="d">
<views:MainView /> <views:MainView Margin="{Binding $parent[Window].WindowDecorationMargin}" />
</Window> </Window>
@@ -1,11 +1,38 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
namespace Semi.Avalonia.Demo.Views; namespace Semi.Avalonia.Demo.Views;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private WindowState _stateBeforeFullScreen = WindowState.Normal;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
KeyDown += FullScreenKeyDown;
}
private void FullScreenKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.F11)
{
ToggleFullScreen();
e.Handled = true;
}
}
private void ToggleFullScreen()
{
if (WindowState is not WindowState.FullScreen)
{
_stateBeforeFullScreen = WindowState;
WindowState = WindowState.FullScreen;
}
else
{
WindowState = _stateBeforeFullScreen;
}
} }
} }
-5
View File
@@ -1,5 +0,0 @@
{
"sdk": {
"version": "8.0"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "8.0.0", "version": "10.0.0",
"rollForward": "latestMajor", "rollForward": "latestMajor",
"allowPrerelease": true "allowPrerelease": true
} }
+1 -1
View File
@@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))"> <PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
@@ -16,6 +15,7 @@
<PackageProjectUrl>https://github.com/irihitech/Semi.Avalonia</PackageProjectUrl> <PackageProjectUrl>https://github.com/irihitech/Semi.Avalonia</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>irihi.png</PackageIcon> <PackageIcon>irihi.png</PackageIcon>
<PackageProjectUrl>https://github.com/irihitech/Semi.Avalonia</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup> </PropertyGroup>
-13
View File
@@ -1,13 +0,0 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<AvaloniaVersion>11.3.7</AvaloniaVersion>
<DataGridVersion>11.3.7</DataGridVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersion)"/>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(DataGridVersion)"/>
<PackageVersion Include="Avalonia.Controls.TreeDataGrid" Version="11.1.1"/>
</ItemGroup>
</Project>
@@ -6,6 +6,7 @@
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.ThemeDictionaries> <ResourceDictionary.ThemeDictionaries>
<ResourceInclude x:Key="Default" Source="Light.axaml" /> <ResourceInclude x:Key="Default" Source="Light.axaml" />
<ResourceInclude x:Key="Light" Source="Light.axaml" />
<ResourceInclude x:Key="Dark" Source="Dark.axaml" /> <ResourceInclude x:Key="Dark" Source="Dark.axaml" />
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@@ -1,39 +1,49 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Avalonia.Controls.Converters"> xmlns:iri="https://irihi.tech/shared"
<converters:CornerRadiusFilterConverter x:Key="LeftCornerRadiusFilterConverter" Filter="TopLeft, BottomLeft" /> xmlns:semi="https://irihi.tech/semi">
<converters:ToBrushConverter x:Key="ToBrushConverter" /> <Design.PreviewWith>
<StackPanel Width="500" Height="500">
<ColorPicker Name="cp" Color="#AAAAAAAA" IsAlphaVisible="True" IsAlphaEnabled="True" />
<ColorPicker Theme="{DynamicResource SimpleColorPicker}" Color="{Binding #cp.Color}" IsAlphaEnabled="{Binding #cp.IsAlphaEnabled}" IsAlphaVisible="{Binding #cp.IsAlphaVisible}" />
<ColorPicker Theme="{DynamicResource HexSimpleColorPicker}" Color="{Binding #cp.Color}" IsAlphaEnabled="{Binding #cp.IsAlphaEnabled}" IsAlphaVisible="{Binding #cp.IsAlphaVisible}" />
<ColorView Color="{Binding #cp.Color}" IsAlphaEnabled="{Binding #cp.IsAlphaEnabled}" IsAlphaVisible="{Binding #cp.IsAlphaVisible}" />
</StackPanel>
</Design.PreviewWith>
<ControlTheme x:Key="{x:Type ColorPicker}" TargetType="ColorPicker"> <ControlTheme x:Key="{x:Type ColorPicker}" TargetType="ColorPicker">
<Setter Property="MinWidth" Value="64" /> <!-- Alpha position should match CSS (and default slider order) instead of XAML/WinUI -->
<Setter Property="HexInputAlphaPosition" Value="Trailing" />
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Padding" Value="0 0 10 0" />
<Setter Property="MinHeight" Value="{DynamicResource ColorPickerMinHeight}" /> <Setter Property="MinHeight" Value="{DynamicResource ColorPickerMinHeight}" />
<Setter Property="CornerRadius" Value="{DynamicResource ColorPickerCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorPickerCornerRadius}" />
<Setter Property="Palette" Value="{DynamicResource SemiColorPalette}" />
<Setter Property="Content"> <Setter Property="Content">
<Template> <Template>
<Panel> <Panel>
<Border <Border
Margin="1,1,0,1" Margin="1,1,0,1"
Width="{Binding $self.Bounds.Height}"
Background="{DynamicResource ColorControlCheckeredBackgroundBrush}" Background="{DynamicResource ColorControlCheckeredBackgroundBrush}"
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" /> CornerRadius="{TemplateBinding CornerRadius, Converter={iri:CornerRadiusMixerConverter Left}}" />
<Border <Border
Margin="1,1,0,1" Margin="1,1,0,1"
Width="{Binding $self.Bounds.Height}"
Background="{TemplateBinding HsvColor, Converter={StaticResource ToBrushConverter}}" Background="{TemplateBinding HsvColor, Converter={StaticResource ToBrushConverter}}"
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" /> CornerRadius="{TemplateBinding CornerRadius, Converter={iri:CornerRadiusMixerConverter Left}}" />
</Panel> </Panel>
</Template> </Template>
</Setter> </Setter>
<Setter Property="Palette">
<FluentColorPalette />
</Setter>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorPicker}"> <ControlTemplate TargetType="ColorPicker">
<DropDownButton <DropDownButton
Width="{TemplateBinding Width}" Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" Height="{TemplateBinding Height}"
MinWidth="{TemplateBinding MinWidth}" MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}" MinHeight="{TemplateBinding MinHeight}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
@@ -49,7 +59,9 @@
</Style> </Style>
</DropDownButton.Styles> </DropDownButton.Styles>
<DropDownButton.Flyout> <DropDownButton.Flyout>
<Flyout FlyoutPresenterClasses="nopadding" Placement="{DynamicResource ColorPickerFlyoutPlacement}"> <Flyout
FlyoutPresenterClasses="nopadding"
Placement="{DynamicResource ColorPickerFlyoutPlacement}">
<!-- <!--
The following is copy-pasted from the ColorView's control template. The following is copy-pasted from the ColorView's control template.
@@ -57,7 +69,6 @@
Note the only changes are resources specific to the ColorPicker. Note the only changes are resources specific to the ColorPicker.
--> -->
<Grid <Grid
Name="RootGrid"
Width="300" Width="300"
Height="300" Height="300"
RowDefinitions="*,Auto"> RowDefinitions="*,Auto">
@@ -81,7 +92,7 @@
Padding="0" Padding="0"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
SelectedIndex="{Binding SelectedIndex, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"> SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabControl.Styles> <TabControl.Styles>
<Style Selector="TabItem"> <Style Selector="TabItem">
<Setter Property="MinHeight" Value="32" /> <Setter Property="MinHeight" Value="32" />
@@ -116,11 +127,11 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
AutomationProperties.Name="Third Component" AutomationProperties.Name="Third Component"
ColorComponent="{Binding ThirdComponent, ElementName=ColorSpectrum}" ColorComponent="{Binding #ColorSpectrum.ThirdComponent}"
ColorModel="Hsva" ColorModel="Hsva"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" HsvColor="{Binding #ColorSpectrum.HsvColor}"
IsAlphaVisible="True" IsAlphaVisible="False"
IsPerceptive="False" IsPerceptive="True"
IsVisible="{TemplateBinding IsColorSpectrumSliderVisible}" IsVisible="{TemplateBinding IsColorSpectrumSliderVisible}"
Orientation="Vertical" /> Orientation="Vertical" />
<ColorSpectrum <ColorSpectrum
@@ -129,7 +140,7 @@
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Components="{TemplateBinding ColorSpectrumComponents}" Components="{TemplateBinding ColorSpectrumComponents}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
MaxHue="{TemplateBinding MaxHue}" MaxHue="{TemplateBinding MaxHue}"
MaxSaturation="{TemplateBinding MaxSaturation}" MaxSaturation="{TemplateBinding MaxSaturation}"
MaxValue="{TemplateBinding MaxValue}" MaxValue="{TemplateBinding MaxValue}"
@@ -146,14 +157,10 @@
AutomationProperties.Name="Alpha Component" AutomationProperties.Name="Alpha Component"
ColorComponent="Alpha" ColorComponent="Alpha"
ColorModel="Hsva" ColorModel="Hsva"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" HsvColor="{Binding #ColorSpectrum.HsvColor}"
IsVisible="{TemplateBinding IsAlphaVisible}"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Orientation="Vertical"> Orientation="Vertical">
<ColorSlider.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</ColorSlider.IsVisible>
</ColorSlider> </ColorSlider>
</Grid> </Grid>
</TabItem> </TabItem>
@@ -168,13 +175,13 @@
<ListBox <ListBox
Margin="12" Margin="12"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
ItemContainerTheme="{DynamicResource ColorViewPaletteListBoxItemTheme}" ItemContainerTheme="{StaticResource ColorViewPaletteListBoxItemTheme}"
ItemsSource="{TemplateBinding PaletteColors}" ItemsSource="{TemplateBinding PaletteColors}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DoNothingForNullConverter}, Mode=TwoWay}" SelectedItem="{TemplateBinding Color, Mode=TwoWay, Converter={StaticResource DoNothingForNullConverter}}"
Theme="{DynamicResource ColorViewPaletteListBoxTheme}" Theme="{StaticResource ColorViewPaletteListBoxTheme}"
UseLayoutRounding="False"> UseLayoutRounding="False">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type Color}"> <DataTemplate DataType="Color">
<Border <Border
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
@@ -205,7 +212,11 @@
Margin="12" Margin="12"
ColumnDefinitions="Auto,*" ColumnDefinitions="Auto,*"
RowDefinitions="Auto,24,*,*,*,*,12" RowDefinitions="Auto,24,*,*,*,*,12"
Tag="{TemplateBinding ColorModel}"> UseLayoutRounding="False">
<Grid.Resources>
<Thickness x:Key="TextBoxContentPadding">8 0</Thickness>
<Thickness x:Key="TextBoxInnerLeftContentPadding">0 0 8 0</Thickness>
</Grid.Resources>
<Grid.Styles> <Grid.Styles>
<Style Selector="NumericUpDown"> <Style Selector="NumericUpDown">
<Setter Property="InnerLeftContent"> <Setter Property="InnerLeftContent">
@@ -214,34 +225,6 @@
</Template> </Template>
</Setter> </Setter>
</Style> </Style>
<Style Selector="Grid[Tag=Rgba]">
<Style Selector="^ NumericUpDown#Component1NumericUpDown">
<Setter Property="Tag" Value="R" />
</Style>
<Style Selector="^ NumericUpDown#Component2NumericUpDown">
<Setter Property="Tag" Value="G" />
</Style>
<Style Selector="^ NumericUpDown#Component3NumericUpDown">
<Setter Property="Tag" Value="B" />
</Style>
<Style Selector="^ NumericUpDown#AlphaComponentNumericUpDown">
<Setter Property="Tag" Value="A" />
</Style>
</Style>
<Style Selector="Grid[Tag=Hsva]">
<Style Selector="^ NumericUpDown#Component1NumericUpDown">
<Setter Property="Tag" Value="H" />
</Style>
<Style Selector="^ NumericUpDown#Component2NumericUpDown">
<Setter Property="Tag" Value="S" />
</Style>
<Style Selector="^ NumericUpDown#Component3NumericUpDown">
<Setter Property="Tag" Value="V" />
</Style>
<Style Selector="^ NumericUpDown#AlphaComponentNumericUpDown">
<Setter Property="Tag" Value="A" />
</Style>
</Style>
</Grid.Styles> </Grid.Styles>
<!-- Top color model & Hex input --> <!-- Top color model & Hex input -->
<Grid <Grid
@@ -263,9 +246,9 @@
Content="RGB" Content="RGB"
CornerRadius="3,0,0,3" CornerRadius="3,0,0,3"
IsChecked="{TemplateBinding ColorModel, IsChecked="{TemplateBinding ColorModel,
Converter={StaticResource EnumToBoolConverter}, Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static ColorModel.Rgba}, ConverterParameter={x:Static ColorModel.Rgba},
Mode=TwoWay}" Mode=TwoWay}"
Theme="{DynamicResource ColorViewRadioButton}" /> Theme="{DynamicResource ColorViewRadioButton}" />
<RadioButton <RadioButton
Name="HsvRadioButton" Name="HsvRadioButton"
@@ -275,9 +258,9 @@
Content="HSV" Content="HSV"
CornerRadius="0,3,3,0" CornerRadius="0,3,3,0"
IsChecked="{TemplateBinding ColorModel, IsChecked="{TemplateBinding ColorModel,
Converter={StaticResource EnumToBoolConverter}, Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static ColorModel.Hsva}, ConverterParameter={x:Static ColorModel.Hsva},
Mode=TwoWay}" Mode=TwoWay}"
Theme="{DynamicResource ColorViewRadioButton}" /> Theme="{DynamicResource ColorViewRadioButton}" />
</Grid> </Grid>
</Border> </Border>
@@ -302,11 +285,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component1Slider}" Maximum="{Binding #Component1Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component1Slider}" Minimum="{Binding #Component1Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component1Slider}" /> Value="{Binding #Component1Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component1Slider" Name="Component1Slider"
Grid.Row="2" Grid.Row="2"
@@ -315,7 +298,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component1" ColorComponent="Component1"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -332,11 +315,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component2Slider}" Maximum="{Binding #Component2Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component2Slider}" Minimum="{Binding #Component2Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component2Slider}" /> Value="{Binding #Component2Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component2Slider" Name="Component2Slider"
Grid.Row="3" Grid.Row="3"
@@ -345,7 +328,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component2" ColorComponent="Component2"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -362,11 +345,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component3Slider}" Maximum="{Binding #Component3Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component3Slider}" Minimum="{Binding #Component3Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component3Slider}" /> Value="{Binding #Component3Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component3Slider" Name="Component3Slider"
Grid.Row="4" Grid.Row="4"
@@ -375,7 +358,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component3" ColorComponent="Component3"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -392,15 +375,15 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Maximum="{Binding Maximum, ElementName=AlphaComponentSlider}" Maximum="{Binding #AlphaComponentSlider.Maximum}"
Minimum="{Binding Minimum, ElementName=AlphaComponentSlider}" Minimum="{Binding #AlphaComponentSlider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=AlphaComponentSlider}"> Value="{Binding #AlphaComponentSlider.Value,Converter={StaticResource DoNothingForNullConverter}}">
<NumericUpDown.IsVisible> <NumericUpDown.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}"> <MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsAlphaVisible" />
<Binding Path="IsComponentTextInputVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsComponentTextInputVisible" />
</MultiBinding> </MultiBinding>
</NumericUpDown.IsVisible> </NumericUpDown.IsVisible>
</NumericUpDown> </NumericUpDown>
@@ -412,7 +395,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Alpha" ColorComponent="Alpha"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
@@ -420,8 +403,8 @@
TickFrequency="1"> TickFrequency="1">
<ColorSlider.IsVisible> <ColorSlider.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}"> <MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsAlphaVisible" />
<Binding Path="IsComponentSliderVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsComponentSliderVisible" />
</MultiBinding> </MultiBinding>
</ColorSlider.IsVisible> </ColorSlider.IsVisible>
</ColorSlider> </ColorSlider>
@@ -429,11 +412,11 @@
</TabItem> </TabItem>
</TabControl> </TabControl>
<!-- Previewer --> <!-- Previewer -->
<!-- Note that top/bottom margins have -5 to remove for drop shadow padding --> <!-- Note that the drop shadow is allowed to extend past the control bounds -->
<ColorPreviewer <ColorPreviewer
Grid.Row="1" Grid.Row="1"
Margin="12,-5,12,7" Margin="12,0,12,12"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}" IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}"
IsVisible="{TemplateBinding IsColorPreviewVisible}" /> IsVisible="{TemplateBinding IsColorPreviewVisible}" />
</Grid> </Grid>
@@ -442,9 +425,33 @@
</DropDownButton> </DropDownButton>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^[ColorModel=Rgba]">
<Style Selector="^ /template/ DropDownButton"> <Style Selector="^ /template/ NumericUpDown#Component1NumericUpDown">
<Setter Property="Padding" Value="0 0 10 0" /> <Setter Property="Tag" Value="R" />
</Style>
<Style Selector="^ /template/ NumericUpDown#Component2NumericUpDown">
<Setter Property="Tag" Value="G" />
</Style>
<Style Selector="^ /template/ NumericUpDown#Component3NumericUpDown">
<Setter Property="Tag" Value="B" />
</Style>
<Style Selector="^ /template/ NumericUpDown#AlphaComponentNumericUpDown">
<Setter Property="Tag" Value="A" />
</Style>
</Style>
<Style Selector="^[ColorModel=Hsva]">
<Style Selector="^ /template/ NumericUpDown#Component1NumericUpDown">
<Setter Property="Tag" Value="H" />
</Style>
<Style Selector="^ /template/ NumericUpDown#Component2NumericUpDown">
<Setter Property="Tag" Value="S" />
</Style>
<Style Selector="^ /template/ NumericUpDown#Component3NumericUpDown">
<Setter Property="Tag" Value="V" />
</Style>
<Style Selector="^ /template/ NumericUpDown#AlphaComponentNumericUpDown">
<Setter Property="Tag" Value="A" />
</Style>
</Style> </Style>
</ControlTheme> </ControlTheme>
@@ -452,38 +459,34 @@
x:Key="HexColorPicker" x:Key="HexColorPicker"
BasedOn="{StaticResource {x:Type ColorPicker}}" BasedOn="{StaticResource {x:Type ColorPicker}}"
TargetType="ColorPicker"> TargetType="ColorPicker">
<Setter Property="MinWidth" Value="200" /> <Setter Property="MinWidth" Value="180" />
<Setter Property="Content"> <Setter Property="Content" Value="{StaticResource HexColorPickerTemplate}" />
<Template>
<Grid ColumnDefinitions="Auto, *">
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource ColorControlCheckeredBackgroundBrush}"
CornerRadius="{TemplateBinding CornerRadius}" />
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{TemplateBinding HsvColor,Converter={StaticResource ToBrushConverter}}"
CornerRadius="{TemplateBinding CornerRadius}" />
<TextBlock
Grid.Column="1"
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontWeight="Regular"
Foreground="{DynamicResource TextBlockDefaultForeground}"
Text="{Binding $parent[ColorPicker].Color}" />
</Grid>
</Template>
</Setter>
</ControlTheme> </ControlTheme>
<Template x:Key="HexColorPickerTemplate">
<Grid ColumnDefinitions="Auto, *">
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
Background="{DynamicResource ColorControlCheckeredBackgroundBrush}"
CornerRadius="{Binding $parent[ColorPicker].CornerRadius}" />
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
Background="{Binding $parent[ColorPicker].HsvColor,Converter={StaticResource ToBrushConverter}}"
CornerRadius="{Binding $parent[ColorPicker].CornerRadius}" />
<TextBlock
Grid.Column="1"
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{DynamicResource TextBlockDefaultForeground}">
<Run Text="#" />
<Run Text="{Binding $parent[ColorPicker].Color, Converter={StaticResource ColorToHexConverter}}" />
</TextBlock>
</Grid>
</Template>
<ControlTheme <ControlTheme
x:Key="SimpleColorPicker" x:Key="SimpleColorPicker"
@@ -491,12 +494,13 @@
TargetType="ColorPicker"> TargetType="ColorPicker">
<Setter Property="ColorSpectrumComponents" Value="SaturationValue" /> <Setter Property="ColorSpectrumComponents" Value="SaturationValue" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorPicker}"> <ControlTemplate TargetType="ColorPicker">
<DropDownButton <DropDownButton
Width="{TemplateBinding Width}" Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" Height="{TemplateBinding Height}"
MinWidth="{TemplateBinding MinWidth}" MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}" MinHeight="{TemplateBinding MinHeight}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
@@ -511,14 +515,16 @@
</Style> </Style>
</DropDownButton.Styles> </DropDownButton.Styles>
<DropDownButton.Flyout> <DropDownButton.Flyout>
<Flyout FlyoutPresenterClasses="nopadding" Placement="{DynamicResource SimpleColorPickerFlyoutPlacement}"> <Flyout
FlyoutPresenterClasses="nopadding"
Placement="{DynamicResource SimpleColorPickerFlyoutPlacement}">
<!-- <!--
The following is copy-pasted from the ColorView's control template. The following is copy-pasted from the ColorView's control template.
It MUST always be kept in sync with the ColorView (which is master). It MUST always be kept in sync with the ColorView (which is master).
Note the only changes are resources specific to the ColorPicker. Note the only changes are resources specific to the ColorPicker.
--> -->
<Grid Width="280"> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="280" /> <RowDefinition Height="*" MinHeight="280" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@@ -534,6 +540,7 @@
Name="ColorSpectrum" Name="ColorSpectrum"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
CornerRadius="8 8 0 0"
Components="{TemplateBinding ColorSpectrumComponents}" Components="{TemplateBinding ColorSpectrumComponents}"
HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
MaxHue="{TemplateBinding MaxHue}" MaxHue="{TemplateBinding MaxHue}"
@@ -584,35 +591,43 @@
CornerRadius="4" /> CornerRadius="4" />
<Panel <Panel
Name="PART_TextBoxPanel" Name="PART_TextBoxPanel"
Width="106" Width="116"
Margin="4 0 0 0" Margin="4 0 0 0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center"> VerticalAlignment="Center">
<TextBox <TextBox
Name="PART_HexTextBox" Name="PART_HexTextBox"
AutomationProperties.Name="Hexadecimal Color"
Classes="Small" Classes="Small"
CornerRadius="3 0 0 3"
InnerLeftContent="#" InnerLeftContent="#"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Hex}" IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter=Hex}"
Text="{TemplateBinding Color, Converter={StaticResource ColorToHexConverter}, Mode=TwoWay}" MaxLength="8">
MaxLength="8" /> <TextBox.Resources>
<Thickness x:Key="TextBoxInnerLeftContentPadding">0 0 4 0</Thickness>
</TextBox.Resources>
</TextBox>
<TextBox <TextBox
Name="PART_RgbaTextBox" Name="PART_RgbaTextBox"
Classes="Small" Classes="Small"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Rgba}" CornerRadius="3 0 0 3"
Text="{TemplateBinding Color, Converter={StaticResource ColorToTextConverter}, Mode=TwoWay}" /> IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static ColorModel.Rgba}}"
Text="{TemplateBinding Color, Converter={semi:ColorToTextConverter}, Mode=TwoWay}" />
<TextBox <TextBox
Name="PART_HsvaTextBox" Name="PART_HsvaTextBox"
Classes="Small" Classes="Small"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Hsva}" CornerRadius="3 0 0 3"
Text="{TemplateBinding HsvColor, Converter={StaticResource HsvColorToTextConverter}, Mode=TwoWay}" /> IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static ColorModel.Hsva}}"
Text="{TemplateBinding HsvColor, Converter={semi:HsvColorToTextConverter}, Mode=TwoWay}" />
</Panel> </Panel>
<NumericUpDown <NumericUpDown
Name="AlphaComponentNumericUpDown" Name="AlphaComponentNumericUpDown"
Width="70" Width="60"
HorizontalAlignment="Right" HorizontalAlignment="Right"
VerticalAlignment="Center" VerticalAlignment="Center"
AllowSpin="True" AllowSpin="True"
CornerRadius="0"
Classes="Small" Classes="Small"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Maximum="{Binding #ColorSpectrumAlphaSlider.Maximum}" Maximum="{Binding #ColorSpectrumAlphaSlider.Maximum}"
@@ -621,14 +636,21 @@
ShowButtonSpinner="False" ShowButtonSpinner="False"
InnerRightContent="%" InnerRightContent="%"
IsVisible="{TemplateBinding IsAlphaVisible}" IsVisible="{TemplateBinding IsAlphaVisible}"
Value="{Binding #ColorSpectrumAlphaSlider.Value}" /> Value="{Binding #ColorSpectrumAlphaSlider.Value,Converter={StaticResource DoNothingForNullConverter}}">
<NumericUpDown.Resources>
<Thickness x:Key="TextBoxContentPadding">12 0 4 0</Thickness>
<Thickness x:Key="TextBoxInnerRightContentPadding">4 0 0 0</Thickness>
</NumericUpDown.Resources>
</NumericUpDown>
<ComboBox <ComboBox
Name="ColorModelComboBox" Name="ColorModelComboBox"
Width="80" Width="80"
CornerRadius="0 3 3 0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Small" Classes="Small"
SelectedValue="Hex"> SelectedValue="Hex">
Hex<ColorModel>Rgba</ColorModel> <x:String>Hex</x:String>
<ColorModel>Rgba</ColorModel>
<ColorModel>Hsva</ColorModel> <ColorModel>Hsva</ColorModel>
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
@@ -647,37 +669,8 @@
x:Key="HexSimpleColorPicker" x:Key="HexSimpleColorPicker"
BasedOn="{StaticResource SimpleColorPicker}" BasedOn="{StaticResource SimpleColorPicker}"
TargetType="ColorPicker"> TargetType="ColorPicker">
<Setter Property="MinWidth" Value="200" /> <Setter Property="MinWidth" Value="180" />
<Setter Property="Content"> <Setter Property="Content" Value="{StaticResource HexColorPickerTemplate}" />
<Template>
<Grid ColumnDefinitions="Auto, *">
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource ColorControlCheckeredBackgroundBrush}"
CornerRadius="{TemplateBinding CornerRadius}" />
<Border
Grid.Column="0"
Width="{Binding $self.Bounds.Height}"
Margin="1,1,0,1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{TemplateBinding HsvColor,Converter={StaticResource ToBrushConverter}}"
CornerRadius="{TemplateBinding CornerRadius}" />
<TextBlock
Grid.Column="1"
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontWeight="Regular"
Foreground="{DynamicResource TextBlockDefaultForeground}"
Text="{Binding $parent[ColorPicker].Color}" />
</Grid>
</Template>
</Setter>
</ControlTheme> </ControlTheme>
</ResourceDictionary> </ResourceDictionary>
@@ -1,17 +1,13 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Avalonia.Controls.Converters" xmlns:iri="https://irihi.tech/shared">
xmlns:pc="using:Avalonia.Controls.Primitives.Converters">
<pc:AccentColorConverter x:Key="AccentColorConverter" />
<converters:CornerRadiusFilterConverter x:Key="LeftCornerRadiusFilterConverter" Filter="TopLeft, BottomLeft" />
<converters:CornerRadiusFilterConverter x:Key="RightCornerRadiusFilterConverter" Filter="TopRight, BottomRight" />
<ControlTheme x:Key="{x:Type ColorPreviewer}" TargetType="ColorPreviewer"> <ControlTheme x:Key="{x:Type ColorPreviewer}" TargetType="ColorPreviewer">
<Setter Property="Height" Value="{DynamicResource ColorPreviewerHeight}" /> <Setter Property="Height" Value="{DynamicResource ColorPreviewerHeight}" />
<Setter Property="CornerRadius" Value="{DynamicResource ColorPreviewerCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorPreviewerCornerRadius}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorPreviewer}"> <ControlTemplate TargetType="ColorPreviewer">
<Panel> <Panel>
<!-- Preview color with accents to the left and right --> <!-- Preview color with accents to the left and right -->
<Grid ColumnDefinitions="Auto,*,Auto" IsVisible="{TemplateBinding IsAccentColorsVisible}"> <Grid ColumnDefinitions="Auto,*,Auto" IsVisible="{TemplateBinding IsAccentColorsVisible}">
@@ -34,7 +30,7 @@
Background="{TemplateBinding HsvColor, Background="{TemplateBinding HsvColor,
Converter={StaticResource AccentColorConverter}, Converter={StaticResource AccentColorConverter},
ConverterParameter='-2'}" ConverterParameter='-2'}"
CornerRadius="{TemplateBinding CornerRadius,Converter={StaticResource LeftCornerRadiusFilterConverter}}" CornerRadius="{TemplateBinding CornerRadius,Converter={iri:CornerRadiusMixerConverter Left}}"
Tag="-2" /> Tag="-2" />
<Border <Border
Name="PART_AccentDecrement1Border" Name="PART_AccentDecrement1Border"
@@ -70,7 +66,7 @@
Background="{TemplateBinding HsvColor, Background="{TemplateBinding HsvColor,
Converter={StaticResource AccentColorConverter}, Converter={StaticResource AccentColorConverter},
ConverterParameter='2'}" ConverterParameter='2'}"
CornerRadius="{TemplateBinding CornerRadius,Converter={StaticResource RightCornerRadiusFilterConverter}}" CornerRadius="{TemplateBinding CornerRadius,Converter={iri:CornerRadiusMixerConverter Right}}"
Tag="2" /> Tag="2" />
</Grid> </Grid>
<!-- Preview color: Must be last for drop shadow Z-index --> <!-- Preview color: Must be last for drop shadow Z-index -->
@@ -1,9 +1,6 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:converters="using:Avalonia.Controls.Converters">
<converters:CornerRadiusToDoubleConverter x:Key="TopLeftCornerRadiusConverter" Corner="TopLeft" />
<converters:CornerRadiusToDoubleConverter x:Key="BottomRightCornerRadiusConverter" Corner="BottomRight" />
<ControlTheme x:Key="ColorSliderThumbTheme" TargetType="Thumb"> <ControlTheme x:Key="ColorSliderThumbTheme" TargetType="Thumb">
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
@@ -12,7 +9,7 @@
<Setter Property="BorderThickness" Value="{DynamicResource ColorSliderThumbBorderBrush}" /> <Setter Property="BorderThickness" Value="{DynamicResource ColorSliderThumbBorderBrush}" />
<Setter Property="CornerRadius" Value="{DynamicResource ColorSliderThumbCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorSliderThumbCornerRadius}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate TargetType="Thumb">
<Border <Border
Margin="1" Margin="1"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
@@ -30,33 +27,30 @@
<Setter Property="CornerRadius" Value="{DynamicResource ColorSliderCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorSliderCornerRadius}" />
<Setter Property="Height" Value="{DynamicResource ColorSliderWidth}" /> <Setter Property="Height" Value="{DynamicResource ColorSliderWidth}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorSlider}"> <ControlTemplate TargetType="ColorSlider">
<Border <Border
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"> CornerRadius="{TemplateBinding CornerRadius}">
<Grid Margin="{TemplateBinding Padding}"> <Grid Margin="{TemplateBinding Padding}">
<Rectangle <Border
Width="{Binding #PART_Track.Bounds.Width}"
Height="{Binding #PART_Track.Bounds.Height}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Center"
Fill="{DynamicResource ColorControlCheckeredBackgroundBrush}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" />
<Rectangle
Width="{Binding #PART_Track.Bounds.Width}"
Height="{Binding #PART_Track.Bounds.Height}" Height="{Binding #PART_Track.Bounds.Height}"
Background="{StaticResource ColorControlCheckeredBackgroundBrush}"
CornerRadius="{DynamicResource ColorSliderCornerRadius}" />
<Border
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Center"
Fill="{TemplateBinding Background}" Height="{Binding #PART_Track.Bounds.Height}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}" Background="{TemplateBinding Background}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" /> CornerRadius="{DynamicResource ColorSliderCornerRadius}" />
<Track <Track
Name="PART_Track" Name="PART_Track"
Height="12" Height="12"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Center"
IsDirectionReversed="{TemplateBinding IsDirectionReversed}" IsDirectionReversed="{TemplateBinding IsDirectionReversed}"
Maximum="{TemplateBinding Maximum}" Maximum="{TemplateBinding Maximum}"
Minimum="{TemplateBinding Minimum}" Minimum="{TemplateBinding Minimum}"
@@ -101,7 +95,7 @@
Width="{TemplateBinding Height}" Width="{TemplateBinding Height}"
Height="{TemplateBinding Height}" Height="{TemplateBinding Height}"
DataContext="{TemplateBinding Value}" DataContext="{TemplateBinding Value}"
Theme="{StaticResource ColorSliderThumbTheme}" /> Theme="{DynamicResource ColorSliderThumbTheme}" />
</Track> </Track>
</Grid> </Grid>
</Border> </Border>
@@ -114,32 +108,28 @@
<Setter Property="CornerRadius" Value="{DynamicResource ColorSliderCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorSliderCornerRadius}" />
<Setter Property="Width" Value="{DynamicResource ColorSliderWidth}" /> <Setter Property="Width" Value="{DynamicResource ColorSliderWidth}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorSlider}"> <ControlTemplate TargetType="ColorSlider">
<Border <Border
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"> CornerRadius="{TemplateBinding CornerRadius}">
<Grid Margin="{TemplateBinding Padding}"> <Grid Margin="{TemplateBinding Padding}">
<Rectangle <Border
Width="{Binding #PART_Track.Bounds.Width}" HorizontalAlignment="Center"
Height="{Binding #PART_Track.Bounds.Height}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Fill="{DynamicResource ColorControlCheckeredBackgroundBrush}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" />
<Rectangle
Width="{Binding #PART_Track.Bounds.Width}" Width="{Binding #PART_Track.Bounds.Width}"
Height="{Binding #PART_Track.Bounds.Height}" Background="{StaticResource ColorControlCheckeredBackgroundBrush}"
HorizontalAlignment="Stretch" CornerRadius="{DynamicResource ColorSliderCornerRadius}" />
<Border
HorizontalAlignment="Center"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Fill="{TemplateBinding Background}" Width="{Binding #PART_Track.Bounds.Width}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}" Background="{TemplateBinding Background}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" /> CornerRadius="{DynamicResource ColorSliderCornerRadius}" />
<Track <Track
Name="PART_Track" Name="PART_Track"
Width="12" Width="12"
HorizontalAlignment="Stretch" HorizontalAlignment="Center"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsDirectionReversed="{TemplateBinding IsDirectionReversed}" IsDirectionReversed="{TemplateBinding IsDirectionReversed}"
Maximum="{TemplateBinding Maximum}" Maximum="{TemplateBinding Maximum}"
@@ -185,7 +175,7 @@
Width="{TemplateBinding Width}" Width="{TemplateBinding Width}"
Height="{TemplateBinding Width}" Height="{TemplateBinding Width}"
DataContext="{TemplateBinding Value}" DataContext="{TemplateBinding Value}"
Theme="{StaticResource ColorSliderThumbTheme}" /> Theme="{DynamicResource ColorSliderThumbTheme}" />
</Track> </Track>
</Grid> </Grid>
</Border> </Border>
@@ -1,15 +1,11 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:converters="using:Avalonia.Controls.Converters">
<converters:EnumToBoolConverter x:Key="EnumToBoolConverter" />
<converters:CornerRadiusToDoubleConverter x:Key="TopLeftCornerRadiusConverter" Corner="TopLeft" />
<converters:CornerRadiusToDoubleConverter x:Key="BottomRightCornerRadiusConverter" Corner="BottomRight" />
<ControlTheme x:Key="{x:Type ColorSpectrum}" TargetType="ColorSpectrum"> <ControlTheme x:Key="{x:Type ColorSpectrum}" TargetType="ColorSpectrum">
<Setter Property="CornerRadius" Value="{DynamicResource ColorSpectrumCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ColorSpectrumCornerRadius}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorSpectrum}"> <ControlTemplate TargetType="ColorSpectrum">
<Panel <Panel
Name="PART_LayoutRoot" Name="PART_LayoutRoot"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@@ -25,27 +21,27 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Box}}" ConverterParameter={x:Static ColorSpectrumShape.Box}}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}" RadiusX="{Binding CornerRadius.TopLeft,RelativeSource={RelativeSource TemplatedParent}}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" /> RadiusY="{Binding CornerRadius.BottomRight,RelativeSource={RelativeSource TemplatedParent}}" />
<Rectangle <Rectangle
Name="PART_SpectrumOverlayRectangle" Name="PART_SpectrumOverlayRectangle"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Box}}" ConverterParameter={x:Static ColorSpectrumShape.Box}}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}" RadiusX="{Binding CornerRadius.TopLeft,RelativeSource={RelativeSource TemplatedParent}}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" /> RadiusY="{Binding CornerRadius.BottomRight,RelativeSource={RelativeSource TemplatedParent}}" />
<Ellipse <Ellipse
Name="PART_SpectrumEllipse" Name="PART_SpectrumEllipse"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Ring}}" /> ConverterParameter={x:Static ColorSpectrumShape.Ring}}" />
<Ellipse <Ellipse
Name="PART_SpectrumOverlayEllipse" Name="PART_SpectrumOverlayEllipse"
@@ -53,7 +49,7 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Ring}}" /> ConverterParameter={x:Static ColorSpectrumShape.Ring}}" />
<Canvas <Canvas
Name="PART_InputTarget" Name="PART_InputTarget"
@@ -89,17 +85,17 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Box}}" ConverterParameter={x:Static ColorSpectrumShape.Box}}"
RadiusX="{TemplateBinding CornerRadius,Converter={StaticResource TopLeftCornerRadiusConverter}}" RadiusX="{Binding CornerRadius.TopLeft,RelativeSource={RelativeSource TemplatedParent}}"
RadiusY="{TemplateBinding CornerRadius,Converter={StaticResource BottomRightCornerRadiusConverter}}" /> RadiusY="{Binding CornerRadius.BottomRight,RelativeSource={RelativeSource TemplatedParent}}" />
<Ellipse <Ellipse
Name="BorderEllipse" Name="BorderEllipse"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
IsVisible="{TemplateBinding Shape, IsVisible="{TemplateBinding Shape,
Converter={StaticResource EnumToBoolConverter}, Converter={x:Static ObjectConverters.Equal},
ConverterParameter={x:Static ColorSpectrumShape.Ring}}" /> ConverterParameter={x:Static ColorSpectrumShape.Ring}}" />
</Panel> </Panel>
</Panel> </Panel>
@@ -1,28 +1,23 @@
<ResourceDictionary <ResourceDictionary
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Avalonia.Controls.Converters" xmlns:semi="https://irihi.tech/semi">
xmlns:globalization="using:System.Globalization"
xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
xmlns:cvts="clr-namespace:Semi.Avalonia.ColorPicker.Converters">
<pc:ContrastBrushConverter x:Key="ContrastBrushConverter" />
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
<converters:ColorToHexConverter x:Key="ColorToHexConverter" />
<converters:DoNothingForNullConverter x:Key="DoNothingForNullConverter" />
<converters:EnumToBoolConverter x:Key="EnumToBoolConverter" />
<converters:ToBrushConverter x:Key="ToBrushConverter" />
<cvts:HsvColorToTextConverter x:Key="HsvColorToTextConverter" />
<cvts:ColorToTextConverter x:Key="ColorToTextConverter" />
<cvts:ToColorModel x:Key="ToColorModel" />
<globalization:NumberFormatInfo x:Key="ColorViewComponentNumberFormat" NumberDecimalDigits="0" />
<Design.PreviewWith> <Design.PreviewWith>
<ColorView <StackPanel>
Theme="{StaticResource SimpleColorView}" <ColorView
IsAlphaVisible="True" SelectedIndex="2"
IsAlphaEnabled="True" IsAlphaVisible="True"
ColorModel="Hsva" IsAlphaEnabled="True"
HsvColor="hsv(120,7%,90%)" /> ColorModel="Hsva"
HsvColor="hsv(120,7%,90%)" />
<ColorView
Theme="{DynamicResource SimpleColorView}"
IsAlphaVisible="True"
IsAlphaEnabled="True"
ColorModel="Hsva"
HsvColor="hsv(120,7%,90%)" />
</StackPanel>
</Design.PreviewWith> </Design.PreviewWith>
<VisualBrush <VisualBrush
@@ -32,16 +27,12 @@
TileMode="Tile"> TileMode="Tile">
<VisualBrush.Visual> <VisualBrush.Visual>
<Image Width="8" Height="8"> <Image Width="8" Height="8">
<Image.Source> <DrawingImage>
<DrawingImage> <DrawingGroup>
<DrawingImage.Drawing> <GeometryDrawing Brush="Transparent" Geometry="M0 0H2V2H0Z" />
<DrawingGroup> <GeometryDrawing Brush="#19808080" Geometry="M0 1H2V2H1V0H0Z" />
<GeometryDrawing Brush="Transparent" Geometry="M0,0 L2,0 2,2, 0,2Z" /> </DrawingGroup>
<GeometryDrawing Brush="#19808080" Geometry="M0,1 L2,1 2,2, 1,2 1,0 0,0Z" /> </DrawingImage>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image> </Image>
</VisualBrush.Visual> </VisualBrush.Visual>
</VisualBrush> </VisualBrush>
@@ -61,11 +52,11 @@
CornerRadius="{TemplateBinding CornerRadius}"> CornerRadius="{TemplateBinding CornerRadius}">
<ScrollViewer <ScrollViewer
Name="PART_ScrollViewer" Name="PART_ScrollViewer"
AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}" AllowAutoHide="{TemplateBinding ScrollViewer.AllowAutoHide}"
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}" IsScrollChainingEnabled="{TemplateBinding ScrollViewer.IsScrollChainingEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding (ScrollViewer.IsDeferredScrollingEnabled)}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"> VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
<ItemsPresenter <ItemsPresenter
Name="PART_ItemsPresenter" Name="PART_ItemsPresenter"
Margin="{TemplateBinding Padding}" Margin="{TemplateBinding Padding}"
@@ -82,8 +73,8 @@
<Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" /> <Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ListBoxItem}"> <ControlTemplate TargetType="ListBoxItem">
<Grid UseLayoutRounding="False"> <Panel UseLayoutRounding="False">
<ContentPresenter <ContentPresenter
Name="PART_ContentPresenter" Name="PART_ContentPresenter"
Padding="{TemplateBinding Padding}" Padding="{TemplateBinding Padding}"
@@ -101,7 +92,7 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
IsHitTestVisible="False" IsHitTestVisible="False"
StrokeThickness="1" /> StrokeThickness="1" />
</Grid> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
@@ -141,12 +132,14 @@
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplate="{TemplateBinding ContentTemplate}"
CornerRadius="{TemplateBinding CornerRadius}" CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True"
TextElement.FontSize="{TemplateBinding FontSize}" TextElement.FontSize="{TemplateBinding FontSize}"
TextElement.FontWeight="{TemplateBinding FontWeight}" TextElement.FontWeight="{TemplateBinding FontWeight}"
UseLayoutRounding="False" /> UseLayoutRounding="False" />
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:checked"> <Style Selector="^:checked">
<Setter Property="Background" Value="{DynamicResource ColorViewRadioButtonCheckedBackground}" /> <Setter Property="Background" Value="{DynamicResource ColorViewRadioButtonCheckedBackground}" />
<Setter Property="Foreground" Value="{DynamicResource ColorViewRadioButtonCheckedForeground}" /> <Setter Property="Foreground" Value="{DynamicResource ColorViewRadioButtonCheckedForeground}" />
@@ -168,14 +161,14 @@
</ControlTheme> </ControlTheme>
<ControlTheme x:Key="{x:Type ColorView}" TargetType="ColorView"> <ControlTheme x:Key="{x:Type ColorView}" TargetType="ColorView">
<!-- Alpha position should match CSS (and default slider order) instead of XAML/WinUI -->
<Setter Property="HexInputAlphaPosition" Value="Trailing" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Width" Value="300" /> <Setter Property="Width" Value="300" />
<Setter Property="Height" Value="300" /> <Setter Property="Height" Value="300" />
<Setter Property="Palette"> <Setter Property="Palette" Value="{DynamicResource SemiColorPalette}" />
<FluentColorPalette />
</Setter>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorView}"> <ControlTemplate TargetType="ColorView">
<Grid RowDefinitions="*,Auto"> <Grid RowDefinitions="*,Auto">
<!-- Backgrounds --> <!-- Backgrounds -->
<!-- TODO: Background="{DynamicResource ColorViewTabBackgroundBrush}" --> <!-- TODO: Background="{DynamicResource ColorViewTabBackgroundBrush}" -->
@@ -197,7 +190,7 @@
Padding="0" Padding="0"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
SelectedIndex="{Binding SelectedIndex, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"> SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabControl.Styles> <TabControl.Styles>
<Style Selector="TabItem"> <Style Selector="TabItem">
<Setter Property="MinHeight" Value="32" /> <Setter Property="MinHeight" Value="32" />
@@ -232,11 +225,11 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
AutomationProperties.Name="Third Component" AutomationProperties.Name="Third Component"
ColorComponent="{Binding ThirdComponent, ElementName=ColorSpectrum}" ColorComponent="{Binding #ColorSpectrum.ThirdComponent}"
ColorModel="Hsva" ColorModel="Hsva"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" HsvColor="{Binding #ColorSpectrum.HsvColor}"
IsAlphaVisible="True" IsAlphaVisible="False"
IsPerceptive="False" IsPerceptive="True"
IsVisible="{TemplateBinding IsColorSpectrumSliderVisible}" IsVisible="{TemplateBinding IsColorSpectrumSliderVisible}"
Orientation="Vertical" /> Orientation="Vertical" />
<ColorSpectrum <ColorSpectrum
@@ -245,7 +238,7 @@
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
Components="{TemplateBinding ColorSpectrumComponents}" Components="{TemplateBinding ColorSpectrumComponents}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
MaxHue="{TemplateBinding MaxHue}" MaxHue="{TemplateBinding MaxHue}"
MaxSaturation="{TemplateBinding MaxSaturation}" MaxSaturation="{TemplateBinding MaxSaturation}"
MaxValue="{TemplateBinding MaxValue}" MaxValue="{TemplateBinding MaxValue}"
@@ -262,14 +255,10 @@
AutomationProperties.Name="Alpha Component" AutomationProperties.Name="Alpha Component"
ColorComponent="Alpha" ColorComponent="Alpha"
ColorModel="Hsva" ColorModel="Hsva"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" HsvColor="{Binding #ColorSpectrum.HsvColor}"
IsVisible="{TemplateBinding IsAlphaVisible}"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Orientation="Vertical"> Orientation="Vertical">
<ColorSlider.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</ColorSlider.IsVisible>
</ColorSlider> </ColorSlider>
</Grid> </Grid>
</TabItem> </TabItem>
@@ -286,11 +275,11 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
ItemContainerTheme="{StaticResource ColorViewPaletteListBoxItemTheme}" ItemContainerTheme="{StaticResource ColorViewPaletteListBoxItemTheme}"
ItemsSource="{TemplateBinding PaletteColors}" ItemsSource="{TemplateBinding PaletteColors}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DoNothingForNullConverter}, Mode=TwoWay}" SelectedItem="{TemplateBinding Color, Mode=TwoWay, Converter={StaticResource DoNothingForNullConverter}}"
Theme="{StaticResource ColorViewPaletteListBoxTheme}" Theme="{StaticResource ColorViewPaletteListBoxTheme}"
UseLayoutRounding="False"> UseLayoutRounding="False">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type Color}"> <DataTemplate DataType="Color">
<Border <Border
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
@@ -322,6 +311,10 @@
ColumnDefinitions="Auto,*" ColumnDefinitions="Auto,*"
RowDefinitions="Auto,24,*,*,*,*,12" RowDefinitions="Auto,24,*,*,*,*,12"
UseLayoutRounding="False"> UseLayoutRounding="False">
<Grid.Resources>
<Thickness x:Key="TextBoxContentPadding">8 0</Thickness>
<Thickness x:Key="TextBoxInnerLeftContentPadding">0 0 8 0</Thickness>
</Grid.Resources>
<Grid.Styles> <Grid.Styles>
<Style Selector="NumericUpDown"> <Style Selector="NumericUpDown">
<Setter Property="InnerLeftContent"> <Setter Property="InnerLeftContent">
@@ -351,9 +344,9 @@
Content="RGB" Content="RGB"
CornerRadius="3,0,0,3" CornerRadius="3,0,0,3"
IsChecked="{TemplateBinding ColorModel, IsChecked="{TemplateBinding ColorModel,
Converter={StaticResource EnumToBoolConverter}, Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static ColorModel.Rgba}, ConverterParameter={x:Static ColorModel.Rgba},
Mode=TwoWay}" Mode=TwoWay}"
Theme="{DynamicResource ColorViewRadioButton}" /> Theme="{DynamicResource ColorViewRadioButton}" />
<RadioButton <RadioButton
Name="HsvRadioButton" Name="HsvRadioButton"
@@ -363,9 +356,9 @@
Content="HSV" Content="HSV"
CornerRadius="0,3,3,0" CornerRadius="0,3,3,0"
IsChecked="{TemplateBinding ColorModel, IsChecked="{TemplateBinding ColorModel,
Converter={StaticResource EnumToBoolConverter}, Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static ColorModel.Hsva}, ConverterParameter={x:Static ColorModel.Hsva},
Mode=TwoWay}" Mode=TwoWay}"
Theme="{DynamicResource ColorViewRadioButton}" /> Theme="{DynamicResource ColorViewRadioButton}" />
</Grid> </Grid>
</Border> </Border>
@@ -390,11 +383,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component1Slider}" Maximum="{Binding #Component1Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component1Slider}" Minimum="{Binding #Component1Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component1Slider}" /> Value="{Binding #Component1Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component1Slider" Name="Component1Slider"
Grid.Row="2" Grid.Row="2"
@@ -403,7 +396,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component1" ColorComponent="Component1"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -420,11 +413,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component2Slider}" Maximum="{Binding #Component2Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component2Slider}" Minimum="{Binding #Component2Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component2Slider}" /> Value="{Binding #Component2Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component2Slider" Name="Component2Slider"
Grid.Row="3" Grid.Row="3"
@@ -433,7 +426,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component2" ColorComponent="Component2"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -450,11 +443,11 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsVisible="{TemplateBinding IsComponentTextInputVisible}" IsVisible="{TemplateBinding IsComponentTextInputVisible}"
Maximum="{Binding Maximum, ElementName=Component3Slider}" Maximum="{Binding #Component3Slider.Maximum}"
Minimum="{Binding Minimum, ElementName=Component3Slider}" Minimum="{Binding #Component3Slider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=Component3Slider}" /> Value="{Binding #Component3Slider.Value,Converter={StaticResource DoNothingForNullConverter}}" />
<ColorSlider <ColorSlider
Name="Component3Slider" Name="Component3Slider"
Grid.Row="4" Grid.Row="4"
@@ -463,7 +456,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Component3" ColorComponent="Component3"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
IsVisible="{TemplateBinding IsComponentSliderVisible}" IsVisible="{TemplateBinding IsComponentSliderVisible}"
@@ -480,15 +473,15 @@
AllowSpin="True" AllowSpin="True"
Classes="Small" Classes="Small"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Maximum="{Binding Maximum, ElementName=AlphaComponentSlider}" Maximum="{Binding #AlphaComponentSlider.Maximum}"
Minimum="{Binding Minimum, ElementName=AlphaComponentSlider}" Minimum="{Binding #AlphaComponentSlider.Minimum}"
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" NumberFormat="{StaticResource ColorViewComponentNumberFormat}"
ShowButtonSpinner="False" ShowButtonSpinner="False"
Value="{Binding Value, ElementName=AlphaComponentSlider}"> Value="{Binding #AlphaComponentSlider.Value,Converter={StaticResource DoNothingForNullConverter}}">
<NumericUpDown.IsVisible> <NumericUpDown.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}"> <MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsAlphaVisible" />
<Binding Path="IsComponentTextInputVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsComponentTextInputVisible" />
</MultiBinding> </MultiBinding>
</NumericUpDown.IsVisible> </NumericUpDown.IsVisible>
</NumericUpDown> </NumericUpDown>
@@ -500,7 +493,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ColorComponent="Alpha" ColorComponent="Alpha"
ColorModel="{TemplateBinding ColorModel,Mode=OneWay}" ColorModel="{TemplateBinding ColorModel,Mode=OneWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
IsRoundingEnabled="True" IsRoundingEnabled="True"
IsSnapToTickEnabled="True" IsSnapToTickEnabled="True"
@@ -508,8 +501,8 @@
TickFrequency="1"> TickFrequency="1">
<ColorSlider.IsVisible> <ColorSlider.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}"> <MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsAlphaVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsAlphaVisible" />
<Binding Path="IsComponentSliderVisible" RelativeSource="{RelativeSource TemplatedParent}" /> <TemplateBinding Property="IsComponentSliderVisible" />
</MultiBinding> </MultiBinding>
</ColorSlider.IsVisible> </ColorSlider.IsVisible>
</ColorSlider> </ColorSlider>
@@ -517,11 +510,11 @@
</TabItem> </TabItem>
</TabControl> </TabControl>
<!-- Previewer --> <!-- Previewer -->
<!-- Note that top/bottom margins have -5 to remove for drop shadow padding --> <!-- Note that the drop shadow is allowed to extend past the control bounds -->
<ColorPreviewer <ColorPreviewer
Grid.Row="1" Grid.Row="1"
Margin="12,-5,12,7" Margin="12,0,12,12"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}" IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}"
IsVisible="{TemplateBinding IsColorPreviewVisible}" /> IsVisible="{TemplateBinding IsColorPreviewVisible}" />
</Grid> </Grid>
@@ -558,11 +551,12 @@
</ControlTheme> </ControlTheme>
<ControlTheme x:Key="SimpleColorView" TargetType="ColorView"> <ControlTheme x:Key="SimpleColorView" TargetType="ColorView">
<Setter Property="HexInputAlphaPosition" Value="Trailing" />
<Setter Property="Width" Value="280" /> <Setter Property="Width" Value="280" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="ColorSpectrumComponents" Value="SaturationValue" /> <Setter Property="ColorSpectrumComponents" Value="SaturationValue" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="{x:Type ColorView}"> <ControlTemplate TargetType="ColorView">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="280" /> <RowDefinition Height="*" MinHeight="280" />
@@ -579,6 +573,7 @@
Name="ColorSpectrum" Name="ColorSpectrum"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
CornerRadius="8 8 0 0"
Components="{TemplateBinding ColorSpectrumComponents}" Components="{TemplateBinding ColorSpectrumComponents}"
HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}" HsvColor="{TemplateBinding HsvColor, Mode=TwoWay}"
MaxHue="{TemplateBinding MaxHue}" MaxHue="{TemplateBinding MaxHue}"
@@ -602,7 +597,7 @@
Orientation="Horizontal" /> Orientation="Horizontal" />
<ColorSlider <ColorSlider
x:Name="ColorSpectrumAlphaSlider" Name="ColorSpectrumAlphaSlider"
Grid.Row="2" Grid.Row="2"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -629,35 +624,43 @@
CornerRadius="4" /> CornerRadius="4" />
<Panel <Panel
Name="PART_TextBoxPanel" Name="PART_TextBoxPanel"
Width="106" Width="116"
Margin="4 0 0 0" Margin="4 0 0 0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center"> VerticalAlignment="Center">
<TextBox <TextBox
Name="PART_HexTextBox" Name="PART_HexTextBox"
AutomationProperties.Name="Hexadecimal Color"
Classes="Small" Classes="Small"
CornerRadius="3 0 0 3"
InnerLeftContent="#" InnerLeftContent="#"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Hex}" IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter=Hex}"
Text="{TemplateBinding Color, Converter={StaticResource ColorToHexConverter}, Mode=TwoWay}" MaxLength="8">
MaxLength="8" /> <TextBox.Resources>
<Thickness x:Key="TextBoxInnerLeftContentPadding">0 0 4 0</Thickness>
</TextBox.Resources>
</TextBox>
<TextBox <TextBox
Name="PART_RgbaTextBox" Name="PART_RgbaTextBox"
Classes="Small" Classes="Small"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Rgba}" CornerRadius="3 0 0 3"
Text="{TemplateBinding Color, Converter={StaticResource ColorToTextConverter}, Mode=TwoWay}" /> IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static ColorModel.Rgba}}"
Text="{TemplateBinding Color, Converter={semi:ColorToTextConverter}, Mode=TwoWay}" />
<TextBox <TextBox
Name="PART_HsvaTextBox" Name="PART_HsvaTextBox"
Classes="Small" Classes="Small"
IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={StaticResource ToColorModel}, ConverterParameter=Hsva}" CornerRadius="3 0 0 3"
Text="{TemplateBinding HsvColor, Converter={StaticResource HsvColorToTextConverter}, Mode=TwoWay}" /> IsVisible="{Binding #ColorModelComboBox.SelectedValue, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static ColorModel.Hsva}}"
Text="{TemplateBinding HsvColor, Converter={semi:HsvColorToTextConverter}, Mode=TwoWay}" />
</Panel> </Panel>
<NumericUpDown <NumericUpDown
Name="AlphaComponentNumericUpDown" Name="AlphaComponentNumericUpDown"
Width="70" Width="60"
HorizontalAlignment="Right" HorizontalAlignment="Right"
VerticalAlignment="Center" VerticalAlignment="Center"
AllowSpin="True" AllowSpin="True"
CornerRadius="0"
Classes="Small" Classes="Small"
IsEnabled="{TemplateBinding IsAlphaEnabled}" IsEnabled="{TemplateBinding IsAlphaEnabled}"
Maximum="{Binding #ColorSpectrumAlphaSlider.Maximum}" Maximum="{Binding #ColorSpectrumAlphaSlider.Maximum}"
@@ -666,14 +669,21 @@
ShowButtonSpinner="False" ShowButtonSpinner="False"
InnerRightContent="%" InnerRightContent="%"
IsVisible="{TemplateBinding IsAlphaVisible}" IsVisible="{TemplateBinding IsAlphaVisible}"
Value="{Binding #ColorSpectrumAlphaSlider.Value}" /> Value="{Binding #ColorSpectrumAlphaSlider.Value,Converter={StaticResource DoNothingForNullConverter}}">
<NumericUpDown.Resources>
<Thickness x:Key="TextBoxContentPadding">12 0 4 0</Thickness>
<Thickness x:Key="TextBoxInnerRightContentPadding">4 0 0 0</Thickness>
</NumericUpDown.Resources>
</NumericUpDown>
<ComboBox <ComboBox
Name="ColorModelComboBox" Name="ColorModelComboBox"
Width="80" Width="80"
CornerRadius="0 3 3 0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Small" Classes="Small"
SelectedValue="Hex"> SelectedValue="Hex">
Hex<ColorModel>Rgba</ColorModel> <x:String>Hex</x:String>
<ColorModel>Rgba</ColorModel>
<ColorModel>Hsva</ColorModel> <ColorModel>Hsva</ColorModel>
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
@@ -0,0 +1,17 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Avalonia.Controls.Converters"
xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
xmlns:globalization="using:System.Globalization">
<pc:ContrastBrushConverter x:Key="ContrastBrushConverter" />
<pc:AccentColorConverter x:Key="AccentColorConverter" />
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
<converters:DoNothingForNullConverter x:Key="DoNothingForNullConverter" />
<converters:ToBrushConverter x:Key="ToBrushConverter" />
<converters:ColorToHexConverter x:Key="ColorToHexConverter" AlphaPosition="Trailing" IsAlphaVisible="True" />
<converters:EnumToBoolConverter x:Key="EnumToBoolConverter" />
<globalization:NumberFormatInfo x:Key="ColorViewComponentNumberFormat" NumberDecimalDigits="0" />
</ResourceDictionary>
@@ -2,6 +2,7 @@
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="Converters.axaml" />
<ResourceInclude Source="ColorPicker.axaml" /> <ResourceInclude Source="ColorPicker.axaml" />
<ResourceInclude Source="ColorPreviewer.axaml" /> <ResourceInclude Source="ColorPreviewer.axaml" />
<ResourceInclude Source="ColorSlider.axaml" /> <ResourceInclude Source="ColorSlider.axaml" />
@@ -3,19 +3,19 @@ using System.Globalization;
using System.Linq; using System.Linq;
using Avalonia; using Avalonia;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Media; using Avalonia.Media;
using Irihi.Avalonia.Shared.Converters;
namespace Semi.Avalonia.ColorPicker.Converters; namespace Semi.Avalonia.ColorPicker.Converters;
public class ColorToTextConverter : IValueConverter public class ColorToTextConverter : MarkupValueConverter
{ {
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public override object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
return value is Color color ? $"{color.R},{color.G},{color.B},{color.A}" : AvaloniaProperty.UnsetValue; return value is Color color ? $"{color.R},{color.G},{color.B},{color.A}" : AvaloniaProperty.UnsetValue;
} }
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) public override object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
if (value is not string str) return BindingOperations.DoNothing; if (value is not string str) return BindingOperations.DoNothing;
var parts = str.Split(','); var parts = str.Split(',');
@@ -3,21 +3,21 @@ using System.Globalization;
using System.Linq; using System.Linq;
using Avalonia; using Avalonia;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Media; using Avalonia.Media;
using Irihi.Avalonia.Shared.Converters;
namespace Semi.Avalonia.ColorPicker.Converters; namespace Semi.Avalonia.ColorPicker.Converters;
public class HsvColorToTextConverter : IValueConverter public class HsvColorToTextConverter : MarkupValueConverter
{ {
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public override object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
return value is HsvColor hsvColor return value is HsvColor hsvColor
? $"{Math.Round(hsvColor.H)},{Math.Round(hsvColor.S * 100)},{Math.Round(hsvColor.V * 100)},{Math.Round(hsvColor.A * 100)}" ? $"{Math.Round(hsvColor.H)},{Math.Round(hsvColor.S * 100)},{Math.Round(hsvColor.V * 100)},{Math.Round(hsvColor.A * 100)}"
: AvaloniaProperty.UnsetValue; : AvaloniaProperty.UnsetValue;
} }
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) public override object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
if (value is not string str) return BindingOperations.DoNothing; if (value is not string str) return BindingOperations.DoNothing;
var parts = str.Split(','); var parts = str.Split(',');
@@ -1,21 +0,0 @@
using System;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Data.Converters;
namespace Semi.Avalonia.ColorPicker.Converters;
public class ToColorModel : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return parameter is "Hex" && value is "Hex" ||
parameter is "Rgba" && value is ColorModel.Rgba ||
parameter is "Hsva" && value is ColorModel.Hsva;
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
@@ -3,6 +3,7 @@
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.ThemeDictionaries> <ResourceDictionary.ThemeDictionaries>
<ResourceInclude x:Key="Default" Source="Light.axaml" /> <ResourceInclude x:Key="Default" Source="Light.axaml" />
<ResourceInclude x:Key="Light" Source="Light.axaml" />
<ResourceInclude x:Key="Dark" Source="Dark.axaml" /> <ResourceInclude x:Key="Dark" Source="Dark.axaml" />
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@@ -1,3 +1,5 @@
using Avalonia.Metadata; using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://irihi.tech/semi", "Semi.Avalonia.ColorPicker")] [assembly: XmlnsPrefix("https://irihi.tech/semi", "semi")]
[assembly: XmlnsDefinition("https://irihi.tech/semi", "Semi.Avalonia.ColorPicker")]
[assembly: XmlnsDefinition("https://irihi.tech/semi", "Semi.Avalonia.ColorPicker.Converters")]
@@ -1,14 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks> <TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<Version>11.3.7.2</Version> <Version>12.0.1</Version>
<PackageReleaseNotes>Update to Semi.Avalonia.ColorPicker 11.3.7.2</PackageReleaseNotes> <PackageReleaseNotes>Update to Semi.Avalonia.ColorPicker 12.0.1</PackageReleaseNotes>
<Title>Semi.Avalonia.ColorPicker</Title> <Title>Semi.Avalonia.ColorPicker</Title>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Controls.ColorPicker"/> <PackageReference Include="Avalonia.Controls.ColorPicker"/>
<PackageReference Include="Irihi.Avalonia.Shared"/>
<None Include="README.md" Pack="true" PackagePath="\"/> <None Include="README.md" Pack="true" PackagePath="\"/>
</ItemGroup> </ItemGroup>
@@ -1,12 +1,12 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Utilities; using Irihi.Avalonia.Shared.Helpers;
namespace Semi.Avalonia.ColorPicker; namespace Semi.Avalonia.ColorPicker;
public class SemiColorDarkPalette: IColorPalette public class SemiColorDarkPalette : IColorPalette
{ {
private static readonly Color[,] Colors = new Color[,] private static readonly Color[,] Colors = new[,]
{ {
{ {
//Red //Red
@@ -216,16 +216,30 @@ public class SemiColorDarkPalette: IColorPalette
Color.FromUInt32(0xFFE6E8EA), Color.FromUInt32(0xFFE6E8EA),
Color.FromUInt32(0xFFF9F9F9), Color.FromUInt32(0xFFF9F9F9),
}, },
{
//AIPurple
Color.FromUInt32(0xFF3A1770),
Color.FromUInt32(0xFF532394),
Color.FromUInt32(0xFF6F31B8),
Color.FromUInt32(0xFF8D41DB),
Color.FromUInt32(0xFFA744FF),
Color.FromUInt32(0xFFC375FF),
Color.FromUInt32(0xFFD598FF),
Color.FromUInt32(0xFFE5BAFF),
Color.FromUInt32(0xFFF3DDFF),
Color.FromUInt32(0xFFFBF3FF),
},
}; };
public Color GetColor(int colorIndex, int shadeIndex) public Color GetColor(int colorIndex, int shadeIndex)
{ {
return Colors[ return Colors[
MathUtilities.Clamp(colorIndex, 0, ColorCount - 1), MathHelpers.SafeClamp(colorIndex, 0, ColorCount - 1),
MathUtilities.Clamp(shadeIndex, 0, ShadeCount - 1) MathHelpers.SafeClamp(shadeIndex, 0, ShadeCount - 1)
]; ];
} }
public int ColorCount => Colors.GetLength(0); public int ColorCount => Colors.GetLength(0);
public int ShadeCount => Colors.GetLength(1); public int ShadeCount => Colors.GetLength(1);
} }
@@ -1,12 +1,12 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Utilities; using Irihi.Avalonia.Shared.Helpers;
namespace Semi.Avalonia.ColorPicker; namespace Semi.Avalonia.ColorPicker;
public class SemiColorLightPalette: IColorPalette public class SemiColorLightPalette : IColorPalette
{ {
private static readonly Color[,] Colors = new Color[,] private static readonly Color[,] Colors = new[,]
{ {
{ {
//Red //Red
@@ -216,12 +216,26 @@ public class SemiColorLightPalette: IColorPalette
Color.FromUInt32(0xFF2E3238), Color.FromUInt32(0xFF2E3238),
Color.FromUInt32(0xFF1C1F23), Color.FromUInt32(0xFF1C1F23),
}, },
{
//AIPurple
Color.FromUInt32(0xFFF8EDFF),
Color.FromUInt32(0xFFF2DAFF),
Color.FromUInt32(0xFFE3B5FF),
Color.FromUInt32(0xFFD191FF),
Color.FromUInt32(0xFFBD6CFF),
Color.FromUInt32(0xFFA647FF),
Color.FromUInt32(0xFF8636DB),
Color.FromUInt32(0xFF6928B8),
Color.FromUInt32(0xFF4E1C94),
Color.FromUInt32(0xFF361270),
},
}; };
public Color GetColor(int colorIndex, int shadeIndex) public Color GetColor(int colorIndex, int shadeIndex)
{ {
return Colors[ return Colors[
MathUtilities.Clamp(colorIndex, 0, ColorCount - 1), MathHelpers.SafeClamp(colorIndex, 0, ColorCount - 1),
MathUtilities.Clamp(shadeIndex, 0, ShadeCount - 1) MathHelpers.SafeClamp(shadeIndex, 0, ShadeCount - 1)
]; ];
} }

Some files were not shown because too many files have changed in this diff Show More