From 8abda28597faef06e03a2f2eb58538cb589fbc49 Mon Sep 17 00:00:00 2001 From: Bill Henning Date: Wed, 24 Apr 2024 09:25:24 -0400 Subject: [PATCH] Updates for v24.1.2. --- Documentation/topics/bars/controls/button.md | 6 +- .../topics/bars/controls/control-basics.md | 15 +- Documentation/topics/bars/controls/gallery.md | 4 + .../topics/bars/controls/popup-button.md | 5 +- .../topics/bars/controls/split-button.md | 5 +- .../bars/controls/using-custom-controls.md | 3 + Documentation/topics/bars/mvvm-support.md | 3 +- .../topics/bars/ribbon-features/backstage.md | 4 + .../topics/bars/ribbon-features/footer.md | 79 ++- .../topics/editors/editboxes/enumeditbox.md | 4 +- .../topics/editors/pickers/enumpicker.md | 4 +- Documentation/topics/licensing.md | 2 +- Documentation/topics/recent-updates.md | 11 + .../topics/shared/images/card-padding.png | Bin 0 -> 4506 bytes Documentation/topics/shared/images/card.png | Bin 0 -> 10770 bytes .../topics/shared/images/info-bar-action.png | Bin 0 -> 1744 bytes .../topics/shared/images/info-bar-content.png | Bin 0 -> 1322 bytes .../shared/images/info-bar-severity.png | Bin 0 -> 5163 bytes .../shared/images/info-bar-wrapping.png | Bin 0 -> 2757 bytes .../topics/shared/images/info-bar.png | Bin 0 -> 1076 bytes Documentation/topics/shared/index.md | 2 + .../windows-controls/advancedtextblock.md | 2 +- .../windows-controls/animatedexpander.md | 2 +- .../windows-controls/animatedprogressbar.md | 2 +- .../shared/windows-controls/avatar-group.md | 2 +- .../topics/shared/windows-controls/avatar.md | 2 +- .../topics/shared/windows-controls/badge.md | 2 +- .../topics/shared/windows-controls/card.md | 387 +++++++++++++ .../windows-controls/circular-progressbar.md | 2 +- .../windows-controls/customdrawelement.md | 2 +- .../windows-controls/dropshadowchrome.md | 2 +- .../shared/windows-controls/dynamicimage.md | 2 +- .../editablecontentcontrol.md | 2 +- .../windows-controls/horizontallistbox.md | 2 +- .../shared/windows-controls/imagetextinfo.md | 2 +- .../topics/shared/windows-controls/index.md | 8 + .../shared/windows-controls/info-bar.md | 262 +++++++++ .../shared/windows-controls/pixelsnapper.md | 2 +- .../shared/windows-controls/popupbutton.md | 2 +- .../windows-controls/progress-spinners.md | 2 +- .../shared/windows-controls/radialslider.md | 2 +- .../windows-controls/radiobuttonlist.md | 2 +- .../reflectioncontentcontrol.md | 2 +- .../resizablecontentcontrol.md | 2 +- .../shared/windows-controls/ringslice.md | 2 +- .../shared/windows-controls/shadowchrome.md | 2 +- .../windows-controls/template-selectors.md | 92 +++ .../shared/windows-controls/toggle-switch.md | 2 +- .../user-prompt/.toc-generator.yml | 2 +- .../user-prompt/appearance.md | 6 +- .../user-prompt/builder-pattern.md | 16 + .../user-prompt/extension-methods.md | 6 +- .../user-prompt/localization.md | 2 +- .../user-prompt/user-prompt-content.md | 10 +- .../zerosizecontentcontrol.md | 2 +- Documentation/topics/toc.yml | 12 + Documentation/topics/views/controls/index.md | 6 + .../topics/views/controls/settings-card.md | 403 +++++++++++++ .../views/controls/settings-expander.md | 390 +++++++++++++ .../topics/views/controls/settings-group.md | 248 ++++++++ .../views/images/settings-card-wrapping.png | Bin 0 -> 3956 bytes .../topics/views/images/settings-card.png | Bin 0 -> 2219 bytes .../topics/views/images/settings-examples.png | Bin 0 -> 12021 bytes .../settings-expander-header-footer.png | Bin 0 -> 5835 bytes .../images/settings-expander-wrapping.png | Bin 0 -> 4039 bytes .../topics/views/images/settings-expander.png | Bin 0 -> 4822 bytes .../images/settings-group-header-footer.png | Bin 0 -> 5513 bytes .../topics/views/images/settings-group.png | Bin 0 -> 2555 bytes Documentation/topics/views/index.md | 7 +- .../PrismIntegration/PrismIntegration.csproj | 2 +- .../ActiproSoftware.References.props | 2 +- .../BarsSamples/Common/BarManager.cs | 1 + .../QuickStart/Backstage/MainWindow.xaml | 35 +- .../QuickStart/Backstage/MainWindow.xaml.cs | 15 + .../QuickStart/Footer/MainControl.xaml | 5 +- .../QuickStart/Footer/OptionsViewModel.cs | 2 +- .../QuickStart/Footer/SampleControlBase.cs | 10 +- .../Footer/SampleMvvmControl.xaml.cs | 2 +- .../QuickStart/FooterInfoBar/MainControl.xaml | 78 +++ .../FooterInfoBar/OptionsViewModel.cs | 93 +++ .../FooterInfoBar/SampleControlBase.cs | 115 ++++ .../FooterInfoBar/SampleMvvmControl.xaml | 28 + .../FooterInfoBar/SampleMvvmControl.xaml.cs | 108 ++++ .../FooterInfoBar/SampleXamlControl.xaml | 74 +++ .../FooterInfoBar/SampleXamlControl.xaml.cs | 61 ++ .../EditorsSamples/Common/EnumWithoutFlags.cs | 15 +- .../QuickStart/CardIntro/MainControl.xaml | 540 ++++++++++++++++++ .../QuickStart/CardIntro/MainControl.xaml.cs | 34 ++ .../QuickStart/InfoBarIntro/MainControl.xaml | 297 ++++++++++ .../InfoBarIntro/MainControl.xaml.cs | 79 +++ .../Demo/ApplicationSettings/MainControl.xaml | 380 ++++++++++++ .../ApplicationSettings/MainControl.xaml.cs | 35 ++ .../QuickStart/SettingsIntro/MainControl.xaml | 286 ++++++++++ .../SettingsIntro/MainControl.xaml.cs | 44 ++ .../SampleBrowser/Properties/AssemblyInfo.cs | 4 +- .../SampleBrowser/Properties/Licenses.licx | 2 +- Samples/SampleBrowser/SampleBrowser.csproj | 2 +- .../Controls/SampleGalleryControl.cs | 1 - .../Documents/ReleaseHistories/v24.1.xaml | 72 +++ .../SampleBrowser/Models/ProductData.xaml | 13 + .../ViewModels/ApplicationViewModel.cs | 12 +- .../Views/ApplicationStyles.xaml | 118 ++-- .../WindowsWorkflowIntegration.csproj | 6 +- Source/Bars.Mvvm/Bars.Mvvm.csproj | 6 +- .../Products/Bars.Mvvm/AssemblyInfo.cs | 4 +- .../RibbonFooterContentTemplateSelector.cs | 8 + .../BarControls/BarGalleryViewModel.cs | 18 + .../RibbonControlGroupViewModel.cs | 4 +- .../RibbonFooterInfoBarContentViewModel.cs | 166 ++++++ .../ViewModels/BarControls/RibbonViewModel.cs | 27 +- .../FontSizeBarGalleryItemViewModel.cs | 2 - .../UI/Themes/BarsMvvmResourceDictionary.xaml | 29 +- .../UI/Themes/BarsMvvmResourceKeys.cs | 18 +- .../DataGrid.Contrib/DataGrid.Contrib.csproj | 4 +- .../Products/DataGrid/Contrib/AssemblyInfo.cs | 4 +- .../Editors.Interop.DataGrid.csproj | 4 +- .../Editors.Interop.DataGrid/AssemblyInfo.cs | 4 +- 117 files changed, 4748 insertions(+), 173 deletions(-) create mode 100644 Documentation/topics/shared/images/card-padding.png create mode 100644 Documentation/topics/shared/images/card.png create mode 100644 Documentation/topics/shared/images/info-bar-action.png create mode 100644 Documentation/topics/shared/images/info-bar-content.png create mode 100644 Documentation/topics/shared/images/info-bar-severity.png create mode 100644 Documentation/topics/shared/images/info-bar-wrapping.png create mode 100644 Documentation/topics/shared/images/info-bar.png create mode 100644 Documentation/topics/shared/windows-controls/card.md create mode 100644 Documentation/topics/shared/windows-controls/info-bar.md create mode 100644 Documentation/topics/shared/windows-controls/template-selectors.md create mode 100644 Documentation/topics/views/controls/settings-card.md create mode 100644 Documentation/topics/views/controls/settings-expander.md create mode 100644 Documentation/topics/views/controls/settings-group.md create mode 100644 Documentation/topics/views/images/settings-card-wrapping.png create mode 100644 Documentation/topics/views/images/settings-card.png create mode 100644 Documentation/topics/views/images/settings-examples.png create mode 100644 Documentation/topics/views/images/settings-expander-header-footer.png create mode 100644 Documentation/topics/views/images/settings-expander-wrapping.png create mode 100644 Documentation/topics/views/images/settings-expander.png create mode 100644 Documentation/topics/views/images/settings-group-header-footer.png create mode 100644 Documentation/topics/views/images/settings-group.png create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/MainControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/OptionsViewModel.cs create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleControlBase.cs create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml.cs create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml.cs create mode 100644 Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/CardIntro/MainControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/CardIntro/MainControl.xaml.cs create mode 100644 Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/InfoBarIntro/MainControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/InfoBarIntro/MainControl.xaml.cs create mode 100644 Samples/SampleBrowser/ProductSamples/ViewsSamples/Demo/ApplicationSettings/MainControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/ViewsSamples/Demo/ApplicationSettings/MainControl.xaml.cs create mode 100644 Samples/SampleBrowser/ProductSamples/ViewsSamples/QuickStart/SettingsIntro/MainControl.xaml create mode 100644 Samples/SampleBrowser/ProductSamples/ViewsSamples/QuickStart/SettingsIntro/MainControl.xaml.cs create mode 100644 Source/Bars.Mvvm/UI/Controls.Bars.Mvvm/ViewModels/BarControls/RibbonFooterInfoBarContentViewModel.cs diff --git a/Documentation/topics/bars/controls/button.md b/Documentation/topics/bars/controls/button.md index 555b25ce..a5960e56 100644 --- a/Documentation/topics/bars/controls/button.md +++ b/Documentation/topics/bars/controls/button.md @@ -118,10 +118,12 @@ The [BarMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem).[Label](xref:@A The controls can display images that help identify their function. -All [BarButton](xref:@ActiproUIRoot.Controls.Bars.BarButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.MediumImageSource), falling back to [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.SmallImageSource) if a medium image is not available. +All [BarButton](xref:@ActiproUIRoot.Controls.Bars.BarButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarButton.MediumImageSource). -[BarMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem) instances can optionally define a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.SmallImageSource) that appears in the menu's icon column. When [UseLargeSize](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.UseLargeSize) is set to create a large menu item, the [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.LargeImageSource) property is used instead. When the menu item is checked, a highlight box will appear around the image. If no image is specified, a standard check glyph will be used in place of the image. +> [!TIP] +> See the [Control Basics](control-basics.md) topic for more detail on the fallback logic for button images. +[BarMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem) instances can optionally define a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.SmallImageSource) that appears in the menu's icon column. When [UseLargeSize](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.UseLargeSize) is set to create a large menu item, the [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.LargeImageSource) property is used instead. When the menu item is checked, a highlight box will appear around the image. If no image is specified, a standard check glyph will be used in place of the image. ### Description (BarMenuItem only) diff --git a/Documentation/topics/bars/controls/control-basics.md b/Documentation/topics/bars/controls/control-basics.md index 3583a042..6306c871 100644 --- a/Documentation/topics/bars/controls/control-basics.md +++ b/Documentation/topics/bars/controls/control-basics.md @@ -89,20 +89,29 @@ Some controls support a single image size, while other controls with variant siz | Medium | 24x24 | Medium images are only used in [Simplified layout mode](../ribbon-features/layout-and-density.md) for some controls. | | Large | 32x32 | Large images are used in certain controls when in large variant sizes. | -When a button is in a ribbon with [Simplified layout mode](../ribbon-features/layout-and-density.md) active, it will fall back to using its small image if a medium image is not available. - #### Fallback Label and Images If an image is not defined and is vital to the normal appearance of the control, a fallback display mechanism can occur, primarily in buttons. In many cases, a missing image for small and medium variant size buttons will result in the label being displayed instead. -In other cases, such as when the control is within the ribbon's [quick access toolbar](../ribbon-features/quick-access-toolbar.md) or when the control is a collapsed ribbon group, then a default fallback image will be used. +In other cases, such as when the control is within the ribbon's [quick access toolbar](../ribbon-features/quick-access-toolbar.md) or when the control is a collapsed ribbon group, then a default missing fallback image will be used. ![Screenshot](../images/fallback-image.png) *The fallback image* +The following table describes the priority order of properties (e.g., `SmallImageSource`, `LargeImageSource`) used to resolve an image for a desired image size. + +| Desired Image Size | Resolution Priority | +|-----|-----| +| Small (16x16) | Small, Large (downscaled), Medium (downscaled), Missing (if no label visible) | +| Medium (24x24) | Medium, Small (centered), Large (downscaled), Missing (if no label visible) | +| Large (32x32) | Large, Medium (centered), Small (centered), Missing | + +> [!TIP] +> When using a vector image for a button with the intention of using a single image for all image sizes, it is best to make a single 32x32 size vector image and assign it to the button's `LargeImageSource` property. Per the table above, a `Large` image can scale down as a fallback for other image sizes. When using raster images, it is much better to use a distinct image design for the `Large` and `Small` image sizes at a minimum. + ### Title An optional string `Title` can be specified, which is intended to override the control's `Label` when displayed in screen tips and customization UI. diff --git a/Documentation/topics/bars/controls/gallery.md b/Documentation/topics/bars/controls/gallery.md index dfb10e5e..2f8a618d 100644 --- a/Documentation/topics/bars/controls/gallery.md +++ b/Documentation/topics/bars/controls/gallery.md @@ -324,6 +324,10 @@ The gallery's `SelectedItem` property may be set at any time to alter the select The [IsSelectionSupported](xref:@ActiproUIRoot.Controls.Bars.Primitives.BarGalleryBase.IsSelectionSupported) property, which defaults to `true`, can be set to `false` to prevent a selection from being retained when an item is clicked. It does this by automatically clearing the `SelectedItem` after a selection is made. This feature is handy for galleries that should take an action when an item is clicked, such as a gallery that inserts a symbol into a document based on the item that was clicked. +### Automatically Scrolling to the Selected Item (RibbonGallery only) + +The [RibbonGallery](xref:@ActiproUIRoot.Controls.Bars.RibbonGallery).[CanAutoScrollToSelectedItem](xref:@ActiproUIRoot.Controls.Bars.RibbonGallery.CanAutoScrollToSelectedItem) property, which defaults to `false`, can be set to `true` to automatically scroll to the in-ribbon gallery's selected item when the selection changes. This ensures that external changes to the selection keep the newly-selected item visible in the user interface. + ### Item Templates Gallery controls generate a [BarGalleryItem](xref:@ActiproUIRoot.Controls.Bars.BarGalleryItem) container for each gallery item in the gallery's `ItemsSource`. diff --git a/Documentation/topics/bars/controls/popup-button.md b/Documentation/topics/bars/controls/popup-button.md index 8a193055..c870ba5a 100644 --- a/Documentation/topics/bars/controls/popup-button.md +++ b/Documentation/topics/bars/controls/popup-button.md @@ -124,7 +124,10 @@ The [BarMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem).[Label](xref:@A The controls can display images that help identify their function. -All [BarPopupButton](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.MediumImageSource), falling back to [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) if a medium image is not available. +All [BarPopupButton](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.MediumImageSource). + +> [!TIP] +> See the [Control Basics](control-basics.md) topic for more detail on the fallback logic for button images. [BarMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem) instances can optionally define a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.SmallImageSource) that appears in the menu's icon column. When [UseLargeSize](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.UseLargeSize) is set to create a large menu item, the [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.LargeImageSource) property is used instead. diff --git a/Documentation/topics/bars/controls/split-button.md b/Documentation/topics/bars/controls/split-button.md index 848f6352..0ebc3cc4 100644 --- a/Documentation/topics/bars/controls/split-button.md +++ b/Documentation/topics/bars/controls/split-button.md @@ -130,7 +130,10 @@ The [BarSplitMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarSplitMenuItem).[Labe The controls can display images that help identify their function. -All [BarSplitButton](xref:@ActiproUIRoot.Controls.Bars.BarSplitButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.MediumImageSource), falling back to [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) if a medium image is not available. +All [BarSplitButton](xref:@ActiproUIRoot.Controls.Bars.BarSplitButton) instances should set a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.SmallImageSource) at a minimum, which is generally used for `Small` and `Medium` variants, as well as in the [Ribbon Quick Access Toolbar](../ribbon-features/quick-access-toolbar.md) and if the control overflows to a menu. If the button supports a `Large` variant size, it should also define a [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.LargeImageSource). When the button has a `Spacious` UI density, it will try to use [MediumImageSource](xref:@ActiproUIRoot.Controls.Bars.BarPopupButton.MediumImageSource). + +> [!TIP] +> See the [Control Basics](control-basics.md) topic for more detail on the fallback logic for button images. [BarSplitMenuItem](xref:@ActiproUIRoot.Controls.Bars.BarSplitMenuItem) instances can optionally define a [SmallImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.SmallImageSource) that appears in the menu's icon column. When [UseLargeSize](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.UseLargeSize) is set to create a large menu item, the [LargeImageSource](xref:@ActiproUIRoot.Controls.Bars.BarMenuItem.LargeImageSource) property is used instead. When the menu item is checked, a highlight box will appear around the image. If no image is specified, a standard check glyph will be used in place of the image. diff --git a/Documentation/topics/bars/controls/using-custom-controls.md b/Documentation/topics/bars/controls/using-custom-controls.md index 9fae7fab..46fdafc1 100644 --- a/Documentation/topics/bars/controls/using-custom-controls.md +++ b/Documentation/topics/bars/controls/using-custom-controls.md @@ -111,6 +111,7 @@ xmlns:editors="http://schemas.actiprosoftware.com/winfx/xaml/editors" bars:BarControlService.Key="Minimum" bars:BarControlService.Label="Minimum" bars:BarControlService.PanelSpacingSuggestion="Both" + bars:BarControlService.SmallImageSource="/Images/Minimum16.png" Width="60" MinHeight="24" MaxHeight="30" UsageContext="ToolBar" themes:ThemeProperties.CornerRadius="3" @@ -120,6 +121,8 @@ xmlns:editors="http://schemas.actiprosoftware.com/winfx/xaml/editors" ``` +When a label and/or small image are applied to a custom control with the attached [LabelProperty](xref:@ActiproUIRoot.Controls.Bars.BarControlService.LabelProperty) and [SmallImageSourceProperty](xref:@ActiproUIRoot.Controls.Bars.BarControlService.SmallImageSourceProperty) properties, they will be displayed in the [BarMenuControlWrapper](xref:@ActiproUIRoot.Controls.Bars.BarMenuControlWrapper) alongside the custom control itself. The small image will align in the icon column with other menu items. + ## Screen Tips The [ScreenTip](xref:@ActiproUIRoot.Controls.Bars.ScreenTip) class inherits the native `ToolTip` control and therefore can be used anywhere a normal tooltip can, including on custom controls. diff --git a/Documentation/topics/bars/mvvm-support.md b/Documentation/topics/bars/mvvm-support.md index ed51aab4..1743ae7f 100644 --- a/Documentation/topics/bars/mvvm-support.md +++ b/Documentation/topics/bars/mvvm-support.md @@ -187,7 +187,8 @@ The following table shows the ribbon footer content view model types defined in | Name | Description | |-----|-----| -| [RibbonFooterSimpleContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterSimpleContentViewModel) | Specifies an `ImageSource` and text message to render in the ribbon [footer](ribbon-features/footer.md). | +| [RibbonFooterInfoBarContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterInfoBarContentViewModel) | Configures an [InfoBar](../shared/windows-controls/info-bar.md) to render in the ribbon [footer](ribbon-features/footer.md) | +| [RibbonFooterSimpleContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterSimpleContentViewModel) | Specifies an `ImageSource` and text message to render in the ribbon [footer](ribbon-features/footer.md). | #### Gallery Item View Models diff --git a/Documentation/topics/bars/ribbon-features/backstage.md b/Documentation/topics/bars/ribbon-features/backstage.md index 5e04f567..c2335966 100644 --- a/Documentation/topics/bars/ribbon-features/backstage.md +++ b/Documentation/topics/bars/ribbon-features/backstage.md @@ -115,10 +115,14 @@ When there are not many tabs or buttons to display in the backstage, the backsta ## Auto-Selecting a Tab When Backstage Opens +The first tab is auto-selected if no tab is currently selected when the backstage opens or when the [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).[CanSelectFirstTabOnOpen](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage.CanSelectFirstTabOnOpen) property is `true`, which is that property's default value. + The [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).[IsOpen](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage.IsOpen) property gets or sets whether the backstage is currently open. A related [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).[IsOpenChanged](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage.IsOpenChanged) event is raised whenever that property changes. This is an ideal place to initialize the backstage so that a certain tab is always selected when it opens. The event handler for the [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).[IsOpenChanged](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage.IsOpenChanged) event can check to see if the backstage is being opened and, if so, ensure the [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).`SelectedItem` property is set to the desired tab. +Set the [RibbonBackstage](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage).[CanSelectFirstTabOnOpen](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstage.CanSelectFirstTabOnOpen) property to `false` if the selected tab will be set programmatically. + ## TaskTabControl The [TaskTabControl](xref:@ActiproUIRoot.Controls.Bars.TaskTabControl) is a styled version of a native WPF `TabControl` that renders its tabs on the left side. The selected tab's content appears on the right side. This tab control is ideal for use on a [RibbonBackstageTabItem](xref:@ActiproUIRoot.Controls.Bars.RibbonBackstageTabItem) since it provides a secondary level of tabs. It can be used externally to backstage as well. diff --git a/Documentation/topics/bars/ribbon-features/footer.md b/Documentation/topics/bars/ribbon-features/footer.md index dee414ef..c593eca4 100644 --- a/Documentation/topics/bars/ribbon-features/footer.md +++ b/Documentation/topics/bars/ribbon-features/footer.md @@ -48,14 +48,23 @@ The footer may also be defined by setting the [Ribbon](xref:@ActiproUIRoot.Contr The optional companion [MVVM Library](../mvvm-support.md) defines a [RibbonFooterViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel) class that is intended to be used as a view model for a [RibbonFooterControl](xref:@ActiproUIRoot.Controls.Bars.RibbonFooterControl) control, and the [BarControlTemplateSelector](xref:@ActiproUIRoot.Controls.Bars.Mvvm.BarControlTemplateSelector) class in the library generates a [RibbonFooterControl](xref:@ActiproUIRoot.Controls.Bars.RibbonFooterControl) for that view model. +### Simple Content + A [RibbonFooterSimpleContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterSimpleContentViewModel) instance may be assigned to the [RibbonFooterViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel).[Content](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel.Content) property. This simple content view model supports easy definition of an image and text message for the footer. +### InfoBar Content + +A [RibbonFooterInfoBarContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterInfoBarContentViewModel) instance may be assigned to the [RibbonFooterViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel).[Content](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel.Content) property. This view model supports configuring an [InfoBar](../../shared/windows-controls/info-bar.md) for the footer. + +> [!IMPORTANT] +> The [RibbonFooterViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel).[Padding](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterViewModel.Padding) property should be set to `0` when using [RibbonFooterInfoBarContentViewModel](xref:@ActiproUIRoot.Controls.Bars.Mvvm.RibbonFooterInfoBarContentViewModel) as the content so the [InfoBar](../../shared/windows-controls/info-bar.md) can render edge-to-edge. + > [!TIP] > See the [MVVM Support](../mvvm-support.md) topic for more information on how to use the library's view models and view templates to create and manage your application's bars controls with MVVM techniques. ## Showing / Hiding the Footer -The ribbon will display the footer as long as the [Ribbon](xref:@ActiproUIRoot.Controls.Bars.Ribbon).[FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property is defined. To show the footer, set the [FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property to the desired content. To hide the footer, set the [FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property to `null`. +The ribbon will display the footer as long as the [Ribbon](xref:@ActiproUIRoot.Controls.Bars.Ribbon).[FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property is defined. To show the footer, set the [FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property to the desired content. To hide the footer, set the [FooterContent](xref:@ActiproUIRoot.Controls.Bars.Ribbon.FooterContent) property to `null` or invoke the command defined by the [ClearFooterCommand](xref:@ActiproUIRoot.Controls.Bars.Ribbon.ClearFooterCommand) property. > [!IMPORTANT] > The ribbon has an altered appearance based on the presence of the footer, so changing the `Visibility` property of a footer control is not sufficient to properly hide the footer. @@ -70,4 +79,70 @@ Instead of setting the `Background` property directly, the [RibbonFooterControl] See the [Reusable Assets](../../themes/reusable-assets.md) topic for details on customizing the pre-defined brush assets used by a footer kind. > [!TIP] -> See the "Footer" Bars Ribbon QuickStart of the Sample Browser application for a full demonstration of working with the ribbon footer. \ No newline at end of file +> See the "Footer" Bars Ribbon QuickStart of the Sample Browser application for a full demonstration of working with the ribbon footer. + +## Using InfoBar in the Footer + +The [InfoBar](../../shared/windows-controls/info-bar.md) is specifically designed to display non-intrusive user messages and is a natural fit for use in the footer, but some properties should be changed to optimally display the control. + +- **BorderThickness** - Set [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).`BorderThickness` to `0` since the footer already defines a border. +- **IsAnimationEnabled** - The ribbon already animates when a footer is opened/closed, so set [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).[IsAnimationEnabled](xref:@ActiproUIRoot.Controls.InfoBar.IsAnimationEnabled) to `false`. + +### Padding + +Since the [InfoBar](../../shared/windows-controls/info-bar.md) should fill the entire area of the footer, it is important to set the [RibbonFooterControl](xref:@ActiproUIRoot.Controls.Bars.RibbonFooterControl).`Padding` to `0`. Any changes to padding should be assigned to [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).`Padding`. + +### Background Color + +The default background color for [InfoBar](../../shared/windows-controls/info-bar.md) (at the default [InfoBarSeverity](xref:@ActiproUIRoot.Controls.InfoBarSeverity)) is different than the default footer background color. It is recommended to apply a `Style` to [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar) that changes the `Background` property to `Transparent` when the default [InfoBarSeverity](xref:@ActiproUIRoot.Controls.InfoBarSeverity) is used as this will allow the footer's own `Background` to be shown. + +> [!IMPORTANT] +> Setting the `Background` property directly will prevent the background color from changing to match the current [InfoBarSeverity](xref:@ActiproUIRoot.Controls.InfoBarSeverity). + +### Closing + +When [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).[CanClose](xref:@ActiproUIRoot.Controls.InfoBar.CanClose) is set to `true`, a **Close Button** is displayed. By default, clicking this button will hide the [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar) (i.e., set `Visibility` to `Collapsed`), but hiding the control does not effectively hide the ribbon's footer. As noted in the "Showing / Hiding the Footer" section above, the footer must be set to `null` to properly hide the footer. + +The easiest solution is to bind the [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).[CloseButtonCommand](xref:@ActiproUIRoot.Controls.InfoBar.CloseButtonCommand) to the ancestor [Ribbon](xref:@ActiproUIRoot.Controls.Bars.Ribbon).[ClearFooterCommand](xref:@ActiproUIRoot.Controls.Bars.Ribbon.ClearFooterCommand) so clicking the **Close Button** will clear the footer. Otherwise, use a custom command or listen to the [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar).[CloseButtonClick](xref:@ActiproUIRoot.Controls.InfoBar.CloseButtonClick) event and clear the footer as noted in the "Showing / Hiding the Footer" section above. + +### Example + +The following example fully demonstrates one way to use an [InfoBar](../../shared/windows-controls/info-bar.md) on a footer: + +```xaml +xmlns:bars="http://schemas.actiprosoftware.com/winfx/xaml/bars" +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Documentation/topics/editors/editboxes/enumeditbox.md b/Documentation/topics/editors/editboxes/enumeditbox.md index 3fc6cb08..fb12443e 100644 --- a/Documentation/topics/editors/editboxes/enumeditbox.md +++ b/Documentation/topics/editors/editboxes/enumeditbox.md @@ -93,7 +93,7 @@ Sometimes it is helpful to display an alternate text version of an enumeration v This scenario is fully supported by [EnumEditBox](xref:@ActiproUIRoot.Controls.Editors.EnumEditBox). A `System.ComponentModel.DataAnnotations.DisplayAttribute` can be applied to a value to give it an alternate textual description. Then as long as the [UseDisplayAttributes](xref:@ActiproUIRoot.Controls.Editors.EnumEditBox.UseDisplayAttributes) property is set to `true`, that alternate text will be used. -If the `DisplayAttribute.ResourceType` property is left blank, it will use the direct value specified by the `Name` property. Otherwise, it will look in the specified resource `Type` for a localized resource value within the property indicated by `Name`. +If the `DisplayAttribute.ResourceType` property is left blank, it will use the direct value specified by the `Name` property. Otherwise, it will look in the specified resource `Type` for a localized resource value within the property indicated by `Name`. If the `Name` property is undefined, the `ShortName` property will be used instead. In this example, the `DisplayAttribute` will look for a property named `MyFirstValue` in the string resources type `MyResources` and use that property's value: @@ -120,6 +120,8 @@ By default, values are listed in the order they are defined. The exception is t Sorting can be altered by implementing a custom `IComparer` class and assigning it to the [EnumSortComparer](xref:@ActiproUIRoot.Controls.Editors.EnumEditBox.EnumSortComparer) property. The [EnumValueNameSortComparer](xref:@ActiproUIRoot.Controls.Editors.Primitives.EnumValueNameSortComparer).[Instance](xref:@ActiproUIRoot.Controls.Editors.Primitives.EnumValueNameSortComparer.Instance) static property provides access to a pre-built comparer for listing enumeration values alphabetically by name. +Alternatively, the `DisplayAttribute.Order` property can be used to define the sort order if the [UseDisplayAttributes](xref:@ActiproUIRoot.Controls.Editors.EnumEditBox.UseDisplayAttributes) property is set to `true` and a custom [EnumSortComparer](xref:@ActiproUIRoot.Controls.Editors.EnumEditBox.EnumSortComparer) is undefined. Values that define a `DisplayAttribute.Order` will always be sorted before values that do not define the attribute. + ## Hiding Enumeration Values By default, all values are listed in the control's popup and when cycling through values using arrow keys. If you wish to hide a specific value from the end user, use `EditorBrowsableAttribute` on the value with `EditorBrowsableState.Never`. diff --git a/Documentation/topics/editors/pickers/enumpicker.md b/Documentation/topics/editors/pickers/enumpicker.md index 7e14b8d8..eedec520 100644 --- a/Documentation/topics/editors/pickers/enumpicker.md +++ b/Documentation/topics/editors/pickers/enumpicker.md @@ -23,7 +23,7 @@ Sometimes it is helpful to display an alternate text version of an enumeration v This scenario is fully supported by [EnumPicker](xref:@ActiproUIRoot.Controls.Editors.EnumPicker). A `System.ComponentModel.DataAnnotations.DisplayAttribute` can be applied to a value to give it an alternate textual description. Then as long as the [UseDisplayAttributes](xref:@ActiproUIRoot.Controls.Editors.EnumPicker.UseDisplayAttributes) property is set to `true`, that alternate text will be used. -If the `DisplayAttribute.ResourceType` property is left blank, it will use the direct value specified by the `Name` property. Otherwise, it will look in the specified resource `Type` for a localized resource value within the property indicated by `Name`. +If the `DisplayAttribute.ResourceType` property is left blank, it will use the direct value specified by the `Name` property. Otherwise, it will look in the specified resource `Type` for a localized resource value within the property indicated by `Name`. If the `Name` property is undefined, the `ShortName` property will be used instead. In this example, the `DisplayAttribute` will look for a property named `MyFirstValue` in the string resources type `MyResources` and use that property's value: @@ -50,6 +50,8 @@ By default, values are listed in the order they are defined. The exception is t Sorting can be altered by implementing a custom `IComparer` class and assigning it to the [EnumSortComparer](xref:@ActiproUIRoot.Controls.Editors.EnumPicker.EnumSortComparer) property. The [EnumValueNameSortComparer](xref:@ActiproUIRoot.Controls.Editors.Primitives.EnumValueNameSortComparer).[Instance](xref:@ActiproUIRoot.Controls.Editors.Primitives.EnumValueNameSortComparer.Instance) static property provides access to a pre-built comparer for listing enumeration values alphabetically by name. +Alternatively, the `DisplayAttribute.Order` property can be used to define the sort order if the [UseDisplayAttributes](xref:@ActiproUIRoot.Controls.Editors.EnumPicker.UseDisplayAttributes) property is set to `true` and a custom [EnumSortComparer](xref:@ActiproUIRoot.Controls.Editors.EnumPicker.EnumSortComparer) is undefined. Values that define a `DisplayAttribute.Order` will always be sorted before values that do not define the attribute. + ## Hiding Enumeration Values By default, all values are listed in the control. If you wish to hide a specific value from the end user, use `EditorBrowsableAttribute` on the value with `EditorBrowsableState.Never`. diff --git a/Documentation/topics/licensing.md b/Documentation/topics/licensing.md index ae787295..7086cecd 100644 --- a/Documentation/topics/licensing.md +++ b/Documentation/topics/licensing.md @@ -152,7 +152,7 @@ The contents of a *licenses.licx* file are pretty simple. It needs a single lin This single line (update the version to match the one you use) should be added to the *licenses.licx* file in any project that uses Actipro @@PlatformName control or SyntaxEditor add-on products: ``` -ActiproSoftware.Products.ActiproLicenseToken, ActiproSoftware.Shared.Wpf, Version=24.1.1.0, Culture=neutral, PublicKeyToken=36ff2196ab5654b9 +ActiproSoftware.Products.ActiproLicenseToken, ActiproSoftware.Shared.Wpf, Version=24.1.2.0, Culture=neutral, PublicKeyToken=36ff2196ab5654b9 ``` > [!IMPORTANT] diff --git a/Documentation/topics/recent-updates.md b/Documentation/topics/recent-updates.md index 14fe9d31..f477a44f 100644 --- a/Documentation/topics/recent-updates.md +++ b/Documentation/topics/recent-updates.md @@ -9,9 +9,20 @@ WPF Studio's documentation has frequent updates, so this topic is the best place If you are looking for a list of recently added major new features to WPF Studio products, please see the Sample Browser's Recent Updates page instead. +## Updates for v24.1.2 + +- **Bars:** Updated [Footer](bars/ribbon-features/footer.md) documentation with details on using [InfoBar](shared/windows-controls/info-bar.md) in the ribbon footer. + +- **Views:** Added documentation for the new [SettingsCard](views/controls/settings-card.md), [SettingsExpander](xref:@ActiproUIRoot.Controls.Views.SettingsExpander), and [SettingsGroup](xref:@ActiproUIRoot.Controls.Views.SettingsGroup) controls. + +- **Shared:** Added documentation for the new [Card](shared/windows-controls/card.md) and [InfoBar](shared/windows-controls/info-bar.md) controls. + +- **Shared:** Added documentation for [Template Selectors](shared/windows-controls/template-selectors.md) which includes the new [ImageTemplateSelector](xref:@ActiproUIRoot.Controls.ImageTemplateSelector). + ## Updates for v24.1.0 - **Shared:** Restructured [User Prompt](shared/windows-controls/user-prompt/index.md) documentation across multiple topics. +- **Shared:** Added documentation for the new [Avatar](shared/windows-controls/avatar.md), [AvatarGroup](shared/windows-controls/avatar-group.md), [Badge](shared/windows-controls/badge.md), and [CircularProgressBar](shared/windows-controls/circular-progressbar.md) controls. - **All:** Updated [Sample Code and QuickStarts](quick-starts.md) topic. diff --git a/Documentation/topics/shared/images/card-padding.png b/Documentation/topics/shared/images/card-padding.png new file mode 100644 index 0000000000000000000000000000000000000000..f0131f9e2550ce01d95d0764c7c4b6610b33a5d5 GIT binary patch literal 4506 zcmZ9Qc{o(>`^RSnF$p6Xq#=AzA0wiylPycaWGRj%X6(D{yBQ2Z2pJ?1DP@L1_H7~| zyX;w$J$oowzSHOT`Tl;__50_(?&p2q@7H;*=RD6j*EzBJXf2l0=TCz`AQtUg>V_Z? zm_*CNm`>4RfVMCS1Y*Z(tE=7(82|p1q3nywIr=KEng@wI_L}b_9{;X(r=G$+)L()SntnXt|c@odEI&Pv2jtPoS|NC-qziX zs!7gdqaxnm-^;GE71X;aJ>RTK+`g}8kOrZfSrUEO*^?^zs|$6W{Nn1L>#`f>^7(6B zYF1^XYnpk(--x7&*Ynu=>ScqPenBStYk!3qGBWr7*l_XBF&9f`WxdG~o{8DGI4alS z9V^;9sq;HVb(`VNWUOfUkv2c_gRRsE?!fEUBd>`Bt%WA{43_PvGP%yI{UMxnXjc^y zWLcZP+U+Cg13e)Wx7O9RS07cCUJ$H6sdd5iZ}Jk;+Jm>dy3%rCwL92AST%Y zhheAOf&%o&PZCgY{13BB;CQ^oA8fLj0fcBViI-eyMeJ5(`Bg{L+wQOa6!m>FEy~U# z<$A7RE)nzMC-1XCv34}eSIewfhij2uX=09Wn{Ds3qN0bRiWzJW`22nf0e_Ff`(YHS znmk|1apPESpf&YW7RNbb4yNBMyc!;LA0JPkz8;;7Y6LYW)sdrf`ozwuvjTrGiZ? zGT)!JW)mtNZH>vUp4)4FfBI=fMu=+GZIuTrVNl@7bUYN?X%UDS+J*!TqV{fRd^d%B z?)}Q`XtIX71?TnG&JK_h!I)KKhQv(`pSXs(*^JwfvVRMxbJjWLnuD_#@1FsNt+%O9 zVKDEduo7ts6CfjjnmR6DsoY`EyQ2DFCF(0TOIgl9eBYo+J4jzy%@iWqR+GEXxmA{z zlzwWLLB0`e|5lmJyS3d**SK%|JGbfE88!se@Sj`d#}@QE#9?Tt1FRFJ+w~$6Q_^qZ ziH_;|z&Q9W+XxzUQ)$>zB=^@!P-#(;QCR5Oqj~PTj}`@3Wr#LXmFjB0p`+pGH6z zIP3$z`Cp5v1GI%!;%J@>dhpxt`aj1slTR-OWoQqR* zxOWK6L~L<;>Xn6U6KT#ncd9#f-Q&-ICgj87;O z{W|UZovC-UhC%dfMsEo9)5|0}V>3EqrsbO)7}JD~Zr>t#uqt(2Qa(k#*}SB7=Aaaq zx7lLQs|qw{kQllb0H~IqPt6en$8QJQsZl>=UZ_diti5xeOQ|b9gj7!5p1od<{ku_B zf{tjayHk@Q!$MifVehZ}V#$=(m3hproPQCl0*$ceP~W4EK2-Osj@%LMS+Z&CVm%H_ zNn5mBztpa#`)B*Ujl%ERAh6;|d>^*YI{d!Tlz3;{-HG>Vw+P-R^T<+F0W%j8nmO2Z zKh?Z2`ylzrBHwypuUeNqBfO%5f3f+X=IZKM>DneUbP{gmr`!uJvEf}#ey`?vzn#XH zEGQ>wvpmMTb@YOCv;)>M!CRe{K|6{YL(CNw8+K|ze5PEv{gWeJLG}I-{&NbC028ah z=>)zJx~UN?>rJv|XWg9&4%nV=o+#|AA3(G|OIcDxzR75AU)Bg_Tn`k2P09MWcW@%h zJe*x4A1)^9-w-8Q+`k#3vemMF({f!!VRl^(+4dLh5m92fq)3YFmZ!hNd)c-6i){3$ z^G%1TlKWld94zpgt$tK^hi0v_be+xZn#7tWX;Tk6dl0nW@YT zn#-aho|`OdPN%}gWvd42k==ez%yKl| z?q3}WK!`jPyfCqyrH^Je0I z{ONSe5#2eTu0|bYsQSZrs7*oLaWfx4BRRdEdJsQ z-De&+$h19UM)@h09q6IBo+5V3Ab_shr$#7wt~zQxB!Vf=@Iwd_0Wr7fA&7r@vV0x+ zFDg7u)nMv{*4z~oBu;Td?T56a(mwirz2Ssk^3}^YP}w^j$=^q9)G{7GCac8$DQ>Sb z&t_+0_NFL5N-KdaQ0#pAd7`X)ia9fIim1_+lU1_&^$SGY`4rK2nEKQej=;G$3Nv_X zQ9n|jdeEkoXM^DZM#<*)KidZm&L76h1Q@7TesOntR{AkvTKUW6$;Y=-LV}x_w{rd8Y@Yo&tHc%GL%Pbt8w=(2L$?yfAk;Fln8GiA)N7IAI_qp7 zddTj@i)KDQ>6u>`dG1zN2GQy9MZyF_VrQ*thl`Yo_a8EVgJ0JOsq0J$ww$y%1Tjzq zl?ds+VKCj8uVeB$W~bo2abT@R_n#TVyyE}I7k-&&FqIe;Iv2E=Y*Ohqdi`r;Tw~fojiQT?`^%zw==kkP^fOLN5Shh$}T)ow`N-7+& zSBkOs-ZyVMvaPLFADER~5KV_-peLy=fEbv0jMV6>=~0i}ikut&O zMktq*6x`>{B-}4g`K4iHvM2FAW02poLDQBVmY3$0!}7!&ry)QvpI#Eu>!; z(3R7{;7CLU0!g5JTv@Im`xOK0{as0=la;_f91Y_tiO_v$k;6)_&YFc7#Ro(4rk4aR zS{!B@4;|~BES8KSxkw{6%hd1nmdb*Pwrd>27B@l*?o~vrcyt>+Qj318dm0aPQR?tZiLuIW0GE?-ftA9XTC3;GOyDx;cjNq52*KzmC@w39F&G zk?);j(>4pSCmwlxd=GF78@O~*y%%|ZU)I)QNU-88adT_2<4D!jl1(sGcv)ZMB=#9D z#YZw-{&9`|1_=hgs}BekHMPCdFK)z|JPCOBK;6*H`G8PhCwzT(n*Z8crM$N}l-%KG zZcWm{{QgbS%QECF-?yc&U+p^lXqq0*-MPtQQjx2We&rbcC{V3KTSu4hH6?6 zF!K^@Xo@PJzeT%D_* znBpIQI?Y@yyrks$#&a=NXY$nG^?T1V)M*76A&QdQco7*v0sYw-^t1pWXfV+N15^A( zWOV=x{@>#5fft8mNMpiZ_Jx~N23iN_hgbE;cus*ZTVqtAY?)3a2q)CrG8;9tk1m>Q z*o=y!ea*Wlvvqg!4f2i&<92st;VS1N4oXe;Cgg(W#F6&ocuNvfrd9iwoRF|NKDL#F z? zlF(gf|2nJZztuEuz22Wlc%+vU+;_n?-Qr1+GT?|b4clo;{cf25@}!_({_Co7kxkuX zxp^*A@}kc3^45aGtj(YkX1;4lJ{X^BQE}#OAqf*VtCP_gr)R^FqxF31B02*vbloqU z^?Is3@ZRFNL}1Tg6}V5`HXWs)^f|?!$KpewtW=X!Z@!JRxZfL)zP8dK& z3Mfr_s0ze@^!~;7-tVsUu66U{9sYLI$~D!nA5n&DLbAxYe}sb-lFM&g>?%2G02Q-;F1{%bhA_&%jUb z;?KjWF$=s55f`&CQ?(hY9t)4`WOctl zGl;4pgMV%z4EHvSpZwDy*{=uY0--u5qx6nLzs;!Yua;O;37&hRMc4MK$%^6wZw(gZ zx_hucR<$Slj#m(OGjB@L`FsyVmC}5E#yB;lsznzwcMx~UJo?JEhQTT5V0QCN$gFZv z>QhkFtPyXQU$_9VJnX&8{r7)WZhAvz(vWtbtGmPUp7kG7_k-(QI2XFdPzK)%6tG7a z5XY}?y z+uGp!f8Cw|XpARyDQrOW{NSpr73aX*)vvghVtt!3Lf^?S8Z=_@ZG_|F#SG3k%f1fuvX%6U-BT)x-pAH%hjfRV z;uXJjTN3?Ko`PtdMs=@s%(5)PwDoGU{1x1$s*B72ChrLIQ0YbXy|CcA~J=1>Slg%0=+ z03fAoU~C%RT_#Xj!%O0{t0@e|RJpyqRYeZ|5qn4#{NTB(Ars|jOA;4hT*>v>-FT+L z;uli)wm@ckf7)}L?kZh3$id&Z5+JACanvBgsJ3zM)%Itm&H_eShG!45LAXLj26{#Q zN2XzJ;R_k@GJ!1~(bo;0Y-=N@vvvu`#w_1EIAA+B}I)>|hp_kZmuD`jW8; zYwaVMhGO%8YRpEcx7+r+>9h?B7e{&t;#t9bvXv8ODBSm!!>`|S`b4pq#TR;dA#P(c zR`b_;C9|zU5tS&sW17=1f_RQ2#)*@x7GO&i+uibhz0aMT8Ne9sJrv)2l#cxfZj-S| zb*V({5Xiw1dgYqi6YHGE{}}C0QpNWi*~mZb-ZdMGrtY}bo1cnu3-^+2EZ+OKP*pxA z;}kAc^kv(f_UTUU1o3$c`6N|Cfp%acBOOEHIxU%RK%UO@?U5{;Ezteu7jFr(Wb7eC z{pg<8ZAo^>fQfgco{2!n`Z{N*nhDA=4jU7@B*RQ*D5$t+i=NLI7?$6|21nlBn4r>W zxI=^CLBt|&mF+XO@@kUL5t5mL;OjD^`yJe%sR4pj{@tqp#n`qlRfe8jo__E7Cxe(Gi;Rf&SuY@xE^GCK9q<^#(z4xbH^*)9t;5Y z0J}P@q-a`EQJwZLoTBP-29lR1slLg8qyZxH7*HpLHpL3p;=st1Rd~197x|Fwb79q^ zgPIA?zA$>oBOY)>afWiy5w0Z?C9gR_S68ST^9KTl8TnFa3rhn88jE8L!uP|#?MG{7 z5)lm(-bqjZdL7tR3@sj%bN#nXT1x3%OH2CWBPx@WIG=o(;z4e?eNbPh0t?LpM1@3PxV6PqAh6bl5@y@p)>W%1Obn0YyO-NS5&ec?<|zy( z)bqR$ay3al4nw`A)pmw>LvF>iMmB0RYMbyElponzLTzv{poWUYGh$B8bbSo{q{^}6 z(MwmDsrs6giW`eJ9)nSc6(9LDFCRU`FWY(k6ov`qBJD_MQz5ss=GPWk6={I@J+m<~ z>L`P$^idp9-#(FCxI@Bi8iPlV%o=! z#sh2L>o<=1M~{kBPfYm8(@v7;&RCHzivoa=9Nh!~@MvM|K7AQ#>mAkO8EvMgDAb!b z=m9;q`{1i@aDw)YZZBQmrBC|xni0Qktn!|2l>U78GyjD{|N7Iz#=+>Oi!3G~OLdF10bS@?6 zfZuv5kz-gd*td9|Sh13_v)kd5P>8`R112MBuWA4(4+hJ<(e zAGwiv-Ig`spr|ka=oPXT)6hovmfGJ2PFsEFjg7*(2}J31CS>m9J+Xf=m2{x$R7U7Q zr%jv*F%D)(B{BVZ$h@2wIGua)k9IXqgdA zj&66aInGsL;IZO?@PnC5YJKM)l}&o=+j^{S=rVHjWxw$(7FAr4)a#HbR_l8a?FUmX zc15^*$=@W4B~gHdW;GBS1?Q3uoGCCuwCo`Kl`Yu`kL&Q+0i*`L>#*^LU>(!Y&aI<2 zJ=Q$p53M21+jTwBdXxs-%eMo!@#a;H4aL3uYT}hwVWN*h<@*fVKdrJ~?-NgyQEh45 zeV}l4rE7O25lAb?s0#bcLfrqs-+fj#@tUG*aYv-VJtYdy12DL$2(i!@!%|ha{O%9U z?1bMi2>wyNf!u^LV%RclxpfVX1b6)|_|5kuw% zHqP=R&JZ%RMdz)A!y!IPA;catgc4Im1=O7S@FO2#f$rhX$lw7K)bo7R4-1jasPUC4 z|nAFa~~ z0;^2$-$T6Boaz)rv|iWmtbKUQ_gJ}eDu$3?b7OVgbFcH%#4^ieyXOH{k$ z>>jXJLE5z3Du{X^d+D*YW05fR!i}^~0=F$@Ob~Hj8`BhzG^IO3e%wYdk)qZb$pn+N zU5ueCNxa*GwwCNFiryDMfEOxo>wYim^brmc`J&{R^;X$49i{|pK^t&b!a=q5q9Ivf z`tD=0OG_1tiy^s2>Gqdph~!CUqv3qMoRk|q8P)=U5K1t)!R5cN??|wP0tnyy`WgV^ z?w*D>>13h|vo*!_ov(z_L6S$3%b!;z;52?;-`KR7`shCqboEfJFY&efzmeSn5RqBo zVr7XopO$SQoB7RmQf=`Y+TB~)FH_nrnN;T&h5u_x%|31VX2nnUAd0qwxLo{ ze*Nk5MgMW2-*f=C#?igKF%?p~zSzPCNpT!o&2Pe)ddf0KrA*g8yoA<#n@DYW+1nc` z?ja|F=pRO=%TJVLrt!l_W7SDJavof9rOD2}B7J<`Dum2mPUZ^CKp@ldgXdd&Z-$<7 zcvaebl|fVSN`u{+%Vr`aCgI?f+G-xomGE>+INk8et6UcuZjN_kv9q3Esxr2|{^keH zb-jLrX&eDb1+s|_8fgs(*S(^uH2dSQl++q8uWD@wxiY(4j@jwEl2$$wRnNiWZ6JP! z&6k{VcFp=k?hv-dTKV;T+tFjXLIv0(w>ov6C~uo!WIn(E{0BLrK}tP4NnrtgDYAd= z8cBp_?lFohRq5c8D|K{RFi*y9+AL;=bmK5fOZ>KkZEPdN*0y!;_3FJ*HlP*b=X3S8@mw0*t!rBdjI2+ z@mVFIendC#{JONj&!)SWMnpa%=4-PjjIHz65XVYG&VW4~#DboDIfo1}J4FW(Q>E^` z`>IoAQU+GA1_4I-EeOJL&X@jFr|u@ih|~Hk46$(uyWCGS+l2K>)^y%%8avtSkI4Bf z8Zs)qSkX@Z1JJt*grQ}KJ8((t(M9=l;={<;T!~dV`;W}`mYEmG6T4$B2g438TRnJ{ zB0OryFzfUPbq;JZDFh?5VCLrn5KhAwoyImQ*q>(z^-(OmgFsMj--K`2M3Mb5@l#|# z7ouZam=U0k`|LdP7a50ku$%k*hCG?O;g}m@U9!{OO_NK zEyed|YNy>|gV*2T6yRABAKAVmTGYtcdu|RZ_zdf84oE{dkXWQ6co(QKE&z-+MU;Hl zlVP9m)4H@212V%!OJPfGqzk^sGO{b|;yXXJa5)`$Z(T&E%7q-HNgpO_LB5;_>h-1t zdWD}NFga<{bTDlJmq6*B0ts?Mau#iXIGn9PF?s1ciPFU)>qQnLF!zNsVwN;?tL^0Ih7UIsHpYZ^AsC&7&IB8QYvfblh9I5ORJ z^@NTj`Hmg$9;?!UMfX;@k$VJVs-;#^Bu)@Td*lghJr8)~|fvUFn3-kde!o zdojpM{VyG2t8&ESS5}eB*+iES_&}wCLe`Qyh|wk0GR@j?TP2a`bVToi(j9P`-X$6x zYgw4UI>~fHElj2ka$1t)Yj(b#LL#NpZO~B$ov9YuLU{=I_69Dc(CE_nepgsG1G;1N zE754DE0zWw$=|(juvXZRvX(rN6#>@D*w9^8*?17;Da>z3Zp~in zQy@CkE_l#hg-$3cb!PtJFaK1}NaVQZy{d+jfAg7!w+@sRmKi7lc(<;w(Zi#}X{|Zy zD#f}jgD!FHR#InK=>){e_neN^s#rY9!4}9xQQE>$4!5aWI@0j=Gho!R88r(au@jeA z@Zs}oF2iGbA0OR;1?+a_fi>*R5sa!2nqbzgNr84-)gHgI0ls^!D$Q-vV2Mi&X(iJ> zi`Cb*v}UJ=cYYBc*~(ZJ|AfK|@a-9Tp7UXj5w7XbDCildo_qM|KR5qYfRlkW*F4q# zj;o9rZI{Qm;B7f0c~=kR&d^Pl0$>J%YpoHmxK#~geb5Rs4*i@cQOD*J`9reHAhr`L z5RdBnJC`D++X{A449S>y^#Rn>6&s03mFQ|M%`sgKm18xbFIkv}I#_FKPRZ&)+7rlpP zaLEcVG%Ln^WsfaZSb(J1R2!;J-1CBs4d+PShJPA~OWXFkLyOk3YqfmP zigGa7bMjn1Rh1LPYIhgZ# zI5`V9N1hK^IbGpTLZ4;iC2nE+K&JWL;v&&8(C<#07yZ7(Q{{+4 z93bAQ$cA(F2$a`K4!tIr%+d*<_o2qzCPQmUD0S=*QYQbx6XkZQY7{04brwPDvxgp> zY!tO{2gj8UIZTE>m+N!p4@gWe>7UyX6?- zH+DdZ10E|)$S%)9c1m%`?o5pWo8rAK0}5Pf)OMz}uQ)^RQV(a)AE9YKNx-toAK8}0 zZ?aN}$-~v|aJNi$F{v0JJ@PAHJD(DcdY*t46cQ@$L@+Urf`G9J2@tT5kTWbHA>p6> zpW*+3|NdpUgE+5yv3MQ6%A1%zNo>5mu*&N%dtHo~ncfn1ak>`x=>_A8<2Q|EMRjq~ zBi&FP!C(J9ZSh)xrF9A&JyqgTKABJf7e8iJ%?p8j@%T{JRX(SVe$30?FP*3~M$h@*bm+G&cF|*#`5CFTyhrVf3k^tjj)L$> zYT=}aqsYxUCC+Po8wcIPF=*{fIy{`aQe0qwMonFiyIrCdIr)(>g7csgS#Nf_hJhm?o~77 z9tgdf=Nhqf6w--JS`Y%%J%q2R`ZG}2A{@SN_xP=hh`_y5S3lpGSLW*!}(7Dge+K7XlJYu%WB_t&#n z$S-Shy6*LdS}&bzPndYQm^HM~G`B z`ZJ22?qBCSj(FVURV}&7r8oCH^{_55J-&Aj+b{fD!RQX9yxX^@v2^GJXKUzW@VAC7s{QgzD5OE*0g0a=|$FaHF3Md`QLIkxeG znu5Hpsxih@BUbzw^Ji6XgxEWzD_Q;8RZ$)tUZI3thGp8K`IXosN@EtN@698LgoOJ+ zuxr()9K|x5m%69K)4E=b$2`@XaJDD4qVLQ~KPp0kU_qRL(Kn(sf;dCyKeGyZg^Xjx z*^`)5RXtsF6wZO&-=<%_ln?3cmTpkWWKH_EJdk+A7?pZu6} zMMZ|&_xYh(BOH4^^*t)&CkYi;XtwG&gK7X1?f8l z)@Mi2XFvO?NO!}EJF(2PJlm|ClYI1@XNRPr9dP0FaLU-u;O$I{h}P^BS%C**u{!$Q zh{~Yk8(J3^Cy|w{)k5Gx9umL#=EH?xBKWAo;4-&ux8L7Yx!{*W&~*j1k!zlGS*EwY zt_Xgl<>Mz%2*07~p9CrvGoTuEoNmm;p7n3I)-9aA&%P(U*UqnpgYQ66ean&q?T)BZR-JZUg?vo%NSVQ|d5{w^k<_DcQq zPQ`~^f-VG#VKM*-$E7BQ1?xi2r{{fa8j`(*?vz)o`d4`I3ZDPn!-sD6T)Vpoxp`Z` z&ukimRA>CG;V7HSpgpbC7~SE1dsE=Ft^SY@Pj+!ZRDNgqv$hGV?DTt%u5EQ`q}Qxtdo*l)`;`)cFL* z-}g&PJMZVJD^87_zl3OL>O$hClu&kP|qBwEkB|Nmf&@@4;#=fz-KY_7Tv60o?|5j*aS1&{CGLhCpZICJgvF|35~bk z*uS{?(D04sC>!NgTy)2b(r)h0ug}b!RaY4AL^Ow?J4VbwdRwj!U)y6^e2mBa;$*14 z7`OHa+<0i$k(euzQIF(@V%87ZK7y7f4zY33!{ounkS;#%m3(@)KW)4GE05I(Rm^D4 zIy*5iNGg0O4k~}+B9G6tLk9PvnIHr{p{RH<%CY;Z`}>Js9I1GfXuZ7wX=-N_1xs5} zHAd)jZQ5HIK$@^IYUWTdm|wQ0tc4N&&~%6uXpHnQ^^AtS5U7YlUI^1Xj4Y+;avnHC zeuD*Tewn<2gD<@F$K?&3$620I*f;mVSknF@mHXBn-s}l5iX|3CF=m#uz38QiuP-xPP7hYhZ1jiSK~r)FDc+z&65O z{C&!2+6Tw|1cx7Vfok*JslO|4EF)yVV^Y}sbpO9T4A*WjSF_S|(RC?#UIg5GPi!S#5G;1do79n0xXudna=41r`(MQ};}!uPlbRwR`mM~8d5J=A%By;D-T7mm5(eR2cq)5{ zaQ7phH@6PIK$J5swz4A!HJ8>mG;2J?HbOG(ePmmdPqHGC>zEgetL4^-Zm*JtAE`Pr zh+^g!g>M!F@@Kux&-GAiQsHPA3d}zie3KQ)v4S2dCi$Gug+#Bf!bR;Q74T zAdLVDaq9M*`r85Qr}1a5^H4DvMmOH1R$OKYGmv#!)U8#PD0u}E&@1@L-z%c1^!#X{ z9?W+Wa9SXJAguYmZ8cW+7s3x>8-KG=hd3dnc2{2@_(2;qXn0o&eE7`AcxOLSpw4HC z{P@0@Sd8;`%b&Y((DqjjS_-IC)0$6LY);eTjBhcVWC@fENz7CJh}@%yF)%mbA5a0h zf^&@^0la+Tz+_gG4#0P8Cl3EbU9RgDbFiL}*Hf5llr%H&WP#a-;WUU*r+HwARTgsb_T&eFum1sxgRwon&-SC!xLOD^%g42R}r^Id)Rj9R$I@ zd>N21nqOe~5iuU_FKz*CB1PsO=%2>BhHTec80g%ORsS_zP1vl4*;Q;kJ+qQap%6Gg zvSb|AX(bh_FZg6G-+_#@1VS;6nx2yfaWdp{8E5|`7)pQR)gku>;>VEb=y{y$=1uC516z`9ypnwWSBVo>a3--*e` z#w-lN(Y*9AJ|8HtE-_)t*kx8=Q;RNS@E84HuV6@bI#qiEtGXnzf8ybP6yJ}J{il9X zav%x%f0YmINE(SZe!`S=xvg>W7_Y>Td|6(o#YFJl{i-_Ew^R4b)j@XXg{SL5dJSp4!-(pMl6C&J64;C8&53!jWp!;#*DT3H6AMCs_iD6SQ0!N;@U0-k^~e1FlpwB^K1PC!Jp z9bS#+^|M`ORhdKNG!{}na|b#N(NE~-F+Sl{3rPFI7-~NG2VTzkac^j(kKSc(e)yU} z^Zx2<0T*sP9nkXrx6EMNV%>;)N9`3G0XqZ7xjU1?Co4*$It=&JUce?cC8jKY2j#u( z8F2ffW$lN23Jp}MubD{FEJ`-2ieEk4^ZOm-oqum=Z?+aS3qJS-@$+{U+jY6=(u`q3 z=gOh_;_$CzX9O%D1zpE+(49|GIE31)j2tuiCfj$;v%4o0DoLWgSck?hiMMB zxb10va|nOeIS5&qD|dNfZx!aHdjxpB@N!xQGJ@1XcBat9)xj;WO+~;k&ZZ*u_j>#c z5pqoEZl@C*<^H9;)i0lSFpkC|j*T88UAEzXX+i@gJNjsv(DChT+7xncri-S_c%L;(&z;BRgo5+Sdu z7Tj>+jm7mf8&Ja2x>p3|%2^Im^3#U#Q2DV~N+6eJwS2y5uYvYGHdT zo!Wamf{PHZ^L7+?`p*`1U0X!78|%NaCj5&KdEVP{yo+VGs7)r7u79B&&j|eg7Pj7J z4eWPTXRcdb2%;P__fPmQ29HSvZZ{&u7F>SlW(zh#>_TUR;q9hl0zV2u<$gwH#-O3+8yd zlSsPQZHC3S{y}g4K4%Nm)jn}kXYRYprQ>@kg?TF6AuloLN_+j3Vbsf!rYmWy{vPij z=Gped{SbObPEc3Cp=N0zD|(#7^P`~$53+Vn1nC=7atYxah8{(I{+u&EJOWf0Nf}>$ zoyknO3qr!5Gmxqf^v9ZA=JQ*c!bnUY@RkoCD*4a^QXiHDYu=wY@nQw82$(}MG8s)t zTco!^P0GiAuDd8WFW438fnsOqw{p*sFYivh%o=H`b{UaXVd2S39`Tqmf0-rbZ`M?F z$Fl%@>z(PRf9X9A9~!Fl@s-A^G!t-(Hl{@kTqaN(_H>lHF}~HOW)vTXeY|78tZzL& zxLqYJhB1za5EAj^JB~UjbDVh}Kc-&i_4&N%9xK&wYu?q99(}F)%;uY{|5obA)gsqO zBiVzCbO7quV~7j5)A>cAgq>PvTkBwJ3KRv3DnMM0&;Qm2GR4llaq5cAj?ppYhPJMp}y5M<{>SU4bYyzDzyDFmR?{-80*CV}*Z2>UMPuf)BSKr?^k9nW) zp8Bk)U$y1slA@9-oIh4}3NqOBAH4n;^X9?)mvcX+cfG#KL;vusglB6|~FZzV`M~cbqD}UH==U0kDV2 zVd0N!9Svso9U77ZRr}V2m*G22&)LnA%ulA*&4zzd#cGZu zNsFD;|HkDy@00-2X?+~B%YfC+$F)(>zI|IlMX{@?fwcBJ;dl$LuUNmbzI@D2O()#P zG{a$7Wuy7*l>S|l=r=ksjAlk;E2YAQ#aMZHhY8+gFO0e|Iu&O^NqiEt|_BxXbc2Qm4O0##?elvZ}r?C=jvUC zoi3$4Rp)k@mw`x&IGUO?nLD4yBepgE+EW#7A?Fjv_3D*B7tA<>8g98jCNt;5q)p%_M_zM-F{6F{5taVbPTLN&=yq#? z)X`b2;z395^90@wCm5y<0pU<}!F-~lLsNA@T%;i!V3&W!f0r|lVcBZW=lKBIlE%Xq zl75HRUa-KDE<)$FI*~EA0b4#*8Urf)RzXq#z?t?T?Q(cC&+}e#K&P!iVJcjp8ne4o zG((^P0GxgYv@E?{xW>pBStnjWO$Jz`dt#|+$8*WE8UgodQi~v2p5Lj^@RgO$ZgS3W zQfCAK049fVuM@BCvJ3pUlVkg&WG3Qxg)~hYf%0!{7CdWWCnflZsbJ07xU@NS tJ2`#*z0)5`PLq*y6c42@vKey#3YxFS(+)yBNbh1~2)EP)!R&I{feA<>u)6`ud}0 z4xeBI?byEl@~Lth92^`R97c)T^5(j292^`(meJh=j7$8W*He785w4%=j5no85w7%<>x#)INH$0>E6@MsB_JybC!_DNE~UF zvF2tOL5RlZ%}mPQ=g@~M`PX-JTXma&QBmtvW~rxU8FG+`avW)LMu|v9iDnsRWKS0Wf?(- z#O1?>K|qJb;>3tR8E2;BxwG;p64u)YVsv(^M3|b1MvG3`FhPCTWtkZZ2+Y0y@E=%>>QEFAUlrft z8&LRfIp^HFw6`Q}7bxk+?(h4Ob92wR3EwZ}+;!6wF~bz`q5Q{-@*gkCf4nIF@uK|4 zi}KG&bOqKL<=-c9R~Lxpf7|xH9XtBA-_5oXiF>+06#qN>cMTA``ggLeL(ll{8}Qk^ zhiw@W_jZ8@{`<-N-n|t1*_NS4{BOIj(f|DqH0F|nsdR=hJ!P1zJ=v5cVk%{`&TybI zJeSJl1Lg}4nk)jzAyf80%z0?Ub=`-DJ7m;#$M%J%Z}2}pf#-?wN5cH?AMpJn2W0`-Trau?hcE;}fWVig9lA ze?<0wME3tA_;HM<>i+e1{tHEqwWj^82q&Eh$=rJXcyz?*^wStR_D?TB(%<+AHma0ZUj*E~iMx``z9COQMOoaQN7{?YQ2<|^bVE+NJZx$_Z>ZAZ6S&T`e7~?eAqXHgKHJ59P zAc|qc>i*?Q)&NXf$+z;!w==>hYzdO#!aErZLNn9ppJw>kBK;4+CsJYf=YQew5`Mzr zJuED)`2I17gD0sR3M-{|mrC!=Q;rsg`={OyEhyao0onilCjYPn)rUKQqal7?Xc726NOdMAt|j z1hH5v`)^!`cF4b6$$a2p*l!A-pE2tl-In|}_8*&pYKOWIZW<0vXKhG8*(6)Z=5J zQOxUN|K)q6zpKjrMKJ}NZsjyrHa;902SgoC!Z*!Xb^ox)-+#Y>3_knYGceJ0ajgp|{}Sr&zY68Qw^07$ mMfr~xwx literal 0 HcmV?d00001 diff --git a/Documentation/topics/shared/images/info-bar-content.png b/Documentation/topics/shared/images/info-bar-content.png new file mode 100644 index 0000000000000000000000000000000000000000..83877fe086f3eddbb5cc048f388eb034c645458b GIT binary patch literal 1322 zcmZ{kdr(q&6vs)cQOhWGY%zRPEjQM7Olz}Euw1X$x|yX`zS=M~ zy-FIUX;_=NQ$*f$Ei)e_QVLW=Xuhx%r3ek$U@!Ggvorgf^E>DK&V0V-{B?c>;bDQM zCRQdW6v`9`3W!9Z7Eq9Uqmd!vo#RHkk)RGIlD3bIP3UwwnNnTDdy~c;BG!tAXFpD> zG*FMsuWHbN!Hc~n{^zq+qtWPK5UW2Rj0kiR2*7@ESS$cZbUNT`&_jS{*%Rk;{o<)P zgoQy6z=9C0E9sgj?Vdnn2%daPipY?55t1Z@`@!fgRT}?Ed~aL6q{FF-kdcaNfb_g7Ew`9xWPuN zvmI^Y_KKUD4_m)Z_n9Z;qge#O(KUJ&+J|F9~Qot65)z4fdm zDRADUNbwTa9RB!r`6f%DG~*oklOkf~wF))-E}yz8wA(cPSSydLxOneSwt1MtmN3_6 zhspA2eD|jPMzLklkAz26&eUouty;|$&ItOhCLCFO`|6s!>hhsOK4~mr%44M{hH|~` zW#3gYy_D%?PcL>%>{z#06Z_2cV+m$2#9C22CX=t!6hB{)H#6lucf68l-|+YG4DO6` zR2Jh3yDX;SSdmTmB+u>q>U~a9T6-Hm8+Rs|3Zt)A(H(tednRR72~_lZD%vijhv6UD zfF+riI7KH4zzbe9!}Z?ynv)B5J@sJb-|3wlXtV2z%XU$Z7h$ThaG`tqAH5aB!O^Fi zKD{#XpGjb*oJp!M$jVUuVO=lVGtF}Y{!Gm;tqn4{ynY$2Pf)V^c{wIH;L1&a=j9L) z0uu1_oJ6y|g=pitXzm;GwI%NXn?_gG=}|MkAeKd3y(mjhw>@{*HgL!Qh` zPQ)UP#bsVR4j!}3NhGmrNOKOyc&sebSN>z)bjQeC>Ib0a zU_Xq)k$wvOY>|<=G;knAvHiX)2WZMR%(mHKTR-UL^;c%T_{I=OHG{80VE&K!N=lN3@GH6iEc&1t|zRN?gsg#EdON2 z(-Zsw^w7w*x=p)AcOOWP81R44us;L$OPD-84l}SaRJirrK{O-C$75sc#iPGh)?x== z`ktghmbA>{+8hH7KEhb4u6wP@4eY{2ea}e|a@@Sjv|G$$H02L>C3a%o75h#fp17-c zPHmZwT`$g|jLoYbj*mZ7V~osK>rA-0Y|j5#*LTz#ry}pUHi)-!I|V1sd?9xva5~EB oZ$>)?3Z%y0?%;p&s2oqN0o?w=b2$5!{wG8M+rt8y{Nr=}1#%{&&j0`b literal 0 HcmV?d00001 diff --git a/Documentation/topics/shared/images/info-bar-severity.png b/Documentation/topics/shared/images/info-bar-severity.png new file mode 100644 index 0000000000000000000000000000000000000000..560477ccb9c30650b8d55324de63b42179f58148 GIT binary patch literal 5163 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 O^MmM_>XvFdMf?LosRD5T literal 0 HcmV?d00001 diff --git a/Documentation/topics/shared/images/info-bar-wrapping.png b/Documentation/topics/shared/images/info-bar-wrapping.png new file mode 100644 index 0000000000000000000000000000000000000000..0e77f2fee8a5574ffc244eb277d1f31be0aa3c52 GIT binary patch literal 2757 zcmZ`*XH=6(7mg@hL|K+EgrF#9QJ1Pz2~woJpg|N}SP;}Kfruc48hSH;Nni;jw15-^ z1OzrHy@+cRl(6)YAYzmf0!VL4z8ClGSI*h}b7$_I=XvJN%)RGK!X=c2gcwW=0)a>X zmZp~>5CH}_zbdj9v|+5?^AO0M1D7t?nQ=Z&f)PHSKefF1plimzcKkxY;QNIQ-s%?h z^^|c=pHgDi^|H|~Uw5{)w)p%892^b@sBDnHXHx;t!8QEPY4Esc{SPD*$L_b0Q_#vJ8)#PsSO|fr4L-ZU9MaK6_UY6akqy@CfYP0l;w`uD=4WL%{Dc>Ixt7saD+z0ulWMFg3Od z8s+5>16Za92{EIokLD3Aw-E#8lfC<%YO5fQsz}2Gq}|0II=$oDX2@0qYW;>Pv<{Hx zZrYTmVQOX#B3dkeRLYc3whp^dqlkNK^zniq>7`qo6p3b~zNYwmxO5-d@Nb+#F;b<| zSaX2qIyWw=gf0dpb{}|3SX^zEGw3BZ&qkFL{uT1-o}R2Q>c99+_7u8l==@mA#jeBF zVS)QytyzDE`5x2ikqEQAZ2995}OdaRR!H*?51jHcmKC_;{j^XWsd= zJhP>fufF_yr)V zpnc3CD_3uwhs5M_*B3tNiT!Sc&}vItN(CS`=Y%LQo{+g8i`F;@^rSi?%~tMcHO-;l^u+sD0Mt> zD`t}E6_?Rnp@9;(r3>VR4e`VEy7J5-v3`2zLoUWx{ox)yD}E*j@vyA=dGH!Mp1c^^ zOr2WMu~R9|$aH(@wKkgAcPYzj9<Yk1am3FkmoWV0l!1jdXAgAkt?m^QCPw=ck8cvIF?3hWr8)d7_Y={m-{D&mQ4F&KPi@lif7h4)*Rh52 z$yY=f&il-XO_u5bC!P;e_o2bg4g>ztDb;3Fo6tV;OL`y9+cvgLj{De8)08S(D;6k6 zqpQ^h7#S_I^R3Hiw9N3R6q3w&zh`pj#jomu=Jdi=}D=3&xE89OLv;K zbo#!#rrohZR)qPjZPOYfNJ>G^!uH?kzE&Vy8XjzS)VS*AW9KY6%sTdDjGWrjHWbExgqmpehj zFQ!h7O{0QiBjZ-}Rf_}Qb{AyzkH{4=2%GK@E%@+Bep#`ogM*z@@aCq9^PK*fo+%Dp zT@5UZ4oQaAk4mD9f&g5SPfRBeU0p(BqnloStC^k3<}@#5+N{ZcAXzYC-* zc(uvfL)KeG2ADSCV#3m=s%P3Fv`DXH;N@%y}HSGSnU*x;CPJ{G(6&sct6%+4pTZtW{uBz6!{$U)mqzQDgG0x zNKLQ)xAM7XDbb$gR?W!xn;%95L#jL{Pz2*f)Fs_WRu3elD7_xpT30i!UKsN) zrJ;3ILXSTq8b@6Y$opBhK!!qVgEfou{-isB^rb5A8EY?i*8%0vGU;qyn=MJgkxOe~ zZa9uZVsc+QwalaPx`(4wMlRMq={x4{0*~4FY9oowF-u|C=sSI$d4nZaYg|KnL>hOi z`eOTdBOp{_us3M7#{F%6s%lsV86JgQ<+sG@9&Z&h&sqyyKAN(+Xd&pEHYN|P$A^XJ za33g-2NZghBP%oxzs2VEZUkkPR!bU z07p6TJZIJX#vqKts&7x@Y*82vUz!-RiEXir(2eE_d1c`>1ev~pCr4=X>WX9G@tRB% znD8+&-Tq_=z@00bJggI^$vk#?Lgo;RCH)tqz@WrIb?Km0L=~o3!#Bwq^@x3{SC_c< z02Ai*NZ+2`_?FF~q@1k1ugNSxz+!_i{$7)&^@%5x^)hi~mK^0Q&BGKSq)uO&;q4~% z+$sRfT?MxME0CK#(;35P+M3!KR3g*eC2yx&BXv?>^b2JCRTxoZ#j$C(4tsSEVsq|k o9x#Qu9VP#_JpUogH&s}8+-uq&pKMnF{=Oi98OrpD$&KiL1JDR%4FCWD literal 0 HcmV?d00001 diff --git a/Documentation/topics/shared/images/info-bar.png b/Documentation/topics/shared/images/info-bar.png new file mode 100644 index 0000000000000000000000000000000000000000..f1473c2a345a160f88357077f535c400e3ccd14b GIT binary patch literal 1076 zcmV-41k3x0P)+?Pol92^`RNtfKZ za!Hrm|GILzavU6Ty8qmlNgPR+-2eaox^f&z-2eYImC!1X&f4qt+?Ppmy8lT@a&k#Y zavU5yJUrXm+v@7-lE&tf$L7k)%5SvZNgN!PNl8gbmzS4v92|1G|Nob|mr0kGa&k#a zq1GH6Nl6@X|GJmm?e{K{&&=fW97%EB^B-7Z#V6mzNfwizr9^`K}CBhosfP ziimR5m+#WB(b~F*vecjNfXHraP%~&-MwqR1IoMP)L%f%n5*e+FPyi+>H#zM1P z$Nox_tzBP2@ep$PF1&2>ef3&csuD?D;i^0M7H{@`|J`^U_wn^V>96smc0>Pt`27RC zAMC$XLznO2(9)61my~t#tz;$tC%#so-h8J381PQ@(B*qPe>O_uwi&!!#k7xwQb8><7$vJ$x^1zL$Q!YX2gj9Ma{21#khe zKttNRS}IeV12;3)cHS!*A&UBwt=(c*g(EvL%6L>)r7{|F zCW_RPC`=QA`C1E*T|1cZ_U4-=sN5_MDi0u4pGMAlLJL2JDqjqRT@rB@La|>`qwHHf7ulm4zY0RSY25N6iMFm}Jx~Z|Y zGp5mr=F9!jX003M%l7;Ex`|EkVq-U7XBJ-e0{nQVP$Ihd9@%^kJNQY`KgsD zg<_0Ec*V^@swCZD?C?!Z6;Kh>S;b}Rrl}8X=lTG4FW>pZkhu-3IBbAyp1wR({fIaQ(!J`YP!+5v1iala>>^{&DZoV@J~t8 zl!^lk$Zi}V7^e5~olmSCp?_|S+MyK%q(gHEU6j7w|_dCJ(;z!uiN8G;5m-X}J_U`WX=2}GcRQ!HD uxFX-MihRQ=@(ruVH>@JxuzD61R=)u5pu62Njv5*O0000 [!TIP] +> In some scenarios, content may not be automatically detected. For instance, if a `DataTemplate` is used to define content without setting the corresponding content property, the card will not know that content is available. Use the [IsCoverVisible](xref:@ActiproUIRoot.Controls.Card.IsCoverVisible), [IsHeaderVisible](xref:@ActiproUIRoot.Controls.Card.IsHeaderVisible), [IsThumbnailVisible](xref:@ActiproUIRoot.Controls.Card.IsThumbnailVisible), and [IsFooterVisible](xref:@ActiproUIRoot.Controls.Card.IsFooterVisible) properties to manually control the visibility of each content area. + +### Content (Body) + +[Card](xref:@ActiproUIRoot.Controls.Card) is a `ContentControl`, and the default content of the control will be displayed in the body area of the card. The content can be set to any value supported by `ContentPresenter`. + +The following example demonstrates defining the content of a [Card](xref:@ActiproUIRoot.Controls.Card): + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + +``` +} + +### Cover + +The [Cover](xref:@ActiproUIRoot.Controls.Card.Cover) can be docked to any side of the card using the [CoverDock](xref:@ActiproUIRoot.Controls.Card.CoverDock) property. While a high-quality image is typically used for the [Cover](xref:@ActiproUIRoot.Controls.Card.Cover), it can be set to any value supported by `ContentPresenter`. + +@if (wpf) { +> [!TIP] +> The [CoverTemplateSelector](xref:@ActiproUIRoot.Controls.Card.CoverTemplateSelector) is pre-configured with a default [ImageTemplateSelector](xref:@ActiproUIRoot.Controls.ImageTemplateSelector), so it supports `ImageSource` and `Geometry` data values. See the [Template Selectors](template-selectors.md) topic for more details. +} + +The following example demonstrates creating a [Card](xref:@ActiproUIRoot.Controls.Card) with a cover image docked to the left: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + + + + + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + + + + + + + +``` +} + +### Header + +The [Title](xref:@ActiproUIRoot.Controls.Card.Title) and [Description](xref:@ActiproUIRoot.Controls.Card.Description) properties can be used to define a header with a default template where the [Title](xref:@ActiproUIRoot.Controls.Card.Title) is displayed with typography consistent with a heading, and the [Description](xref:@ActiproUIRoot.Controls.Card.Description), if defined, is displayed immediately below it. + +@if (avalonia) { +Use the [TitleTheme](xref:@ActiproUIRoot.Controls.Card.TitleTheme) and [DescriptionTheme](xref:@ActiproUIRoot.Controls.Card.DescriptionTheme) properties to customize the appearance of each element. +} +@if (wpf) { +Use the [TitleStyle](xref:@ActiproUIRoot.Controls.Card.TitleStyle) and [DescriptionStyle](xref:@ActiproUIRoot.Controls.Card.DescriptionStyle) properties to customize the appearance of each element. +} + +The following example demonstrates creating a [Card](xref:@ActiproUIRoot.Controls.Card) with both [Title](xref:@ActiproUIRoot.Controls.Card.Title) and [Description](xref:@ActiproUIRoot.Controls.Card.Description) defined: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + +``` +} + +Alternatively, the [Header](xref:@ActiproUIRoot.Controls.Card.Header) can be set to any value supported by `ContentPresenter`. In this case, the explicit content will be used instead of the default template based on the [Title](xref:@ActiproUIRoot.Controls.Card.Title) and [Description](xref:@ActiproUIRoot.Controls.Card.Description) properties. + +The following example demonstrates creating a [Card](xref:@ActiproUIRoot.Controls.Card) with an explicit [Header](xref:@ActiproUIRoot.Controls.Card.Header) defined: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + + Title Here + + + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + + Title Here + + + + + +``` +} + +### Thumbnail + +The [Thumbnail](xref:@ActiproUIRoot.Controls.Card.Thumbnail) is displayed in the header area, but is separate from the [Header](xref:@ActiproUIRoot.Controls.Card.Header) content. [Thumbnail](xref:@ActiproUIRoot.Controls.Card.Thumbnail) can be set to any value supported by `ContentPresenter` but is typically used to display a small image. + +@if (wpf) { +> [!TIP] +> The [ThumbnailTemplateSelector](xref:@ActiproUIRoot.Controls.Card.ThumbnailTemplateSelector) is pre-configured with a default [ImageTemplateSelector](xref:@ActiproUIRoot.Controls.ImageTemplateSelector), so it supports `ImageSource` and `Geometry` data values. See the [Template Selectors](template-selectors.md) topic for more details. +} + +By default, the [Thumbnail](xref:@ActiproUIRoot.Controls.Card.Thumbnail) is vertically centered with a right margin to separate it from the [Header](xref:@ActiproUIRoot.Controls.Card.Header). Use the @if (avalonia) {[ThumbnailTheme](xref:@ActiproUIRoot.Controls.Card.ThumbnailTheme)}@if (wpf) {[ThumbnailStyle](xref:@ActiproUIRoot.Controls.Card.ThumbnailStyle)} property to customize the appearance. + +The following example demonstrates creating a [Card](xref:@ActiproUIRoot.Controls.Card) with top-aligned image and a custom margin: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + + + + + + + + + + + + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + + + + + + + + + + + +``` +} + +### Footer + +The [Footer](xref:@ActiproUIRoot.Controls.Card.Footer) can be set to any value supported by `ContentPresenter`. + +The following example demonstrates creating a [Card](xref:@ActiproUIRoot.Controls.Card) with italicized text in the footer: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + + + + + + + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + + + + + + + + + +``` +} + +## Appearance + +The appearance of the control can be fully customized. + +### Brushes + +The following brush properties are available: + +| Property | Description | +| ----- | ----- | +| `Foreground` | The default foreground for all areas. | +| `Background` | The default background for all areas. | +| `BorderBrush` | The brush for the outer border. | +| [HeaderForeground](xref:@ActiproUIRoot.Controls.Card.HeaderForeground) | The foreground for the header area, overriding the default foreground. | +| [HeaderBackground](xref:@ActiproUIRoot.Controls.Card.HeaderBackground) | The background for the header area, overriding the default background. | +| [HeaderBorderBrush](xref:@ActiproUIRoot.Controls.Card.HeaderBorderBrush) | The brush for the bottom border of the header. +| [FooterForeground](xref:@ActiproUIRoot.Controls.Card.FooterForeground) | The foreground for the footer area, overriding the default foreground. | +| [FooterBackground](xref:@ActiproUIRoot.Controls.Card.FooterBackground) | The background for the footer area, overriding the default background. | +| [FooterBorderBrush](xref:@ActiproUIRoot.Controls.Card.FooterBorderBrush) | The brush for the top border of the footer. | + +### Header and Footer Borders + +Use the [HeaderBorderThickness](xref:@ActiproUIRoot.Controls.Card.HeaderBorderThickness) and [FooterBorderThickness](xref:@ActiproUIRoot.Controls.Card.FooterBorderThickness) properties to insert a border below the header or above the footer. In the event header and footer both define a border when no content is defined between them, only the header border will be displayed. + +> [!IMPORTANT] +> When setting the border thickness, only `Thickness.Bottom` is used by the header and `Thickness.Top` is used by the footer. + +### Padding + +![Screenshot](../images/card-padding.png) + +*Card controls with the same padding shown with and without separation between then content and the header/footer* + +By default, the `Padding` is consistently applied around the header, content, and footer areas instead of having separate values for each area. When there is visual separation between the content and the header/footer (either by a border or an explicit background color), the padding will be consistently applied to both sides of the separation. + +> [!NOTE] +> The [Cover](xref:@ActiproUIRoot.Controls.Card.Cover) area does not have any default padding applied so the content can be displayed edge-to-edge. + +## Using Card as a Button + +[Card](xref:@ActiproUIRoot.Controls.Card) derives from `Button`, so it supports the same `Command` model and `Click` event as `Button`. Unlike a `Button`, though, not all instances of [Card](xref:@ActiproUIRoot.Controls.Card) will be interactive and the control has been configured to appear non-interactive by default. + +Set the [IsClickEnabled](xref:@ActiproUIRoot.Controls.Card.IsClickEnabled) property to `true` to enable clicking the card. The `Click` event will not be raised if this property is `false`. + +> [!TIP] +> If the `Command` property is assigned a non-`null` value, the [IsClickEnabled](xref:@ActiproUIRoot.Controls.Card.IsClickEnabled) property is automatically coerced to `true`, so no additional configuration is necessary. + +> [!NOTE] +> Setting the [IsClickEnabled](xref:@ActiproUIRoot.Controls.Card.IsClickEnabled) property to `true` will also trigger hover effects to emphasize the control is actionable. + +@if (wpf) { +## Badge Adornment + +[Card](xref:@ActiproUIRoot.Controls.Card) includes built-in support for adding a [Badge](badge.md) adornment. Refer to the [Badge](badge.md) documentation for details on working with a badge. + +The following properties are available for configuring the badge, which correspond to attached properties on [BadgeService](xref:@ActiproUIRoot.Controls.BadgeService): + +| Property | Description | +| ----- | ----- | +| [Badge](xref:@ActiproUIRoot.Controls.Card.Badge) | Set to an instance of a [Badge](badge.md). | +| [BadgeHorizontalAlignment](xref:@ActiproUIRoot.Controls.Card.BadgeHorizontalAlignment) | Set to one of the [AdornmentHorizontalAlignment](xref:@ActiproUIRoot.Controls.AdornmentHorizontalAlignment) values to alter the horizontal alignment. (Default = [CenterOnTargetRightEdge](xref:@ActiproUIRoot.Controls.AdornmentHorizontalAlignment.CenterOnTargetRightEdge) ) | +| [BadgeHorizontalOffset](xref:@ActiproUIRoot.Controls.Card.BadgeHorizontalOffset) | An explicit offset to be applied after alignment. Positive values shift to the right while negative values shift to the left. | +| [BadgeVerticalAlignment](xref:@ActiproUIRoot.Controls.Card.BadgeVerticalAlignment) | Set to one of the [AdornmentVerticalAlignment](xref:@ActiproUIRoot.Controls.AdornmentVerticalAlignment) values to alter the vertical alignment. (Default = [CenterOnTargetTopEdge](xref:@ActiproUIRoot.Controls.AdornmentVerticalAlignment.CenterOnTargetTopEdge) ) | +| [BadgeVerticalOffset](xref:@ActiproUIRoot.Controls.Card.BadgeVerticalOffset) | An explicit offset to be applied after alignment. Positive values shift down while negative values shift up. | + +} + + +@if (avalonia) { +## Themes + +![Screenshot](../images/card-themes.png) + +*Card control in the outline, solid, soft, and elevated themes* + +The following control themes are supported: +- [CardBase](xref:@ActiproUIRoot.Themes.ControlThemeKind.CardBase) - Base control theme used by several others. +- [CardElevated](xref:@ActiproUIRoot.Themes.ControlThemeKind.CardElevated) (`theme-elevated`) - Has an elevated appearance with a shadow. +- [CardOutline](xref:@ActiproUIRoot.Themes.ControlThemeKind.CardOutline) (`theme-outline`) - Has an outline appearance. +- [CardSoft](xref:@ActiproUIRoot.Themes.ControlThemeKind.CardSoft) (`theme-soft`) - Has a soft fill appearance. +- [CardSolid](xref:@ActiproUIRoot.Themes.ControlThemeKind.CardSolid) (`theme-solid`) - Has a solid appearance. + + +The following example demonstrates how to define a card using the elevated theme: + +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + +``` + +### Elevated Button Animation + +When used as a `Button` and the elevated theme is applied (`theme-elevated` style class name), an animation is applied when the pointer is over the [Card](xref:@ActiproUIRoot.Controls.Card) that slides the control up while raising the elevation of the shadow. + +Animations are automatically enabled. To turn off animations, set the [IsAnimationEnabled](xref:@ActiproUIRoot.Controls.Card.IsAnimationEnabled) property to `false`. +} +@if (wpf) { +## Elevated Appearance + +By default, the [IsShadowEnabled](xref:@ActiproUIRoot.Controls.Card.IsShadowEnabled) property is set to `true` and gives the [Card](xref:@ActiproUIRoot.Controls.Card) an elevated appearance. + +When also used as a `Button`, an animation is applied when the mouse is over the [Card](xref:@ActiproUIRoot.Controls.Card) that slides the control up while raising the elevation of the shadow. + +Animations are automatically disabled, as appropriate, based on system settings. To manually turn off animations, set the [IsAnimationEnabled](xref:@ActiproUIRoot.Controls.Card.IsAnimationEnabled) property to `false`. +} + +@if (avalonia) { + +## Theme Resources + +The following theme resources are available for customizing the appearance of the control: + +| Theme Resource | Description | +| ----- | ----- | +| [CardBorderThickness](xref:@ActiproUIRoot.Themes.ThemeResourceKind.CardBorderThickness) | The default `BorderThickness`. | +| [CardCornerRadius](xref:@ActiproUIRoot.Themes.ThemeResourceKind.CardCornerRadius) | The default `CornerRadius`. | +| [CardPadding](xref:@ActiproUIRoot.Themes.ThemeResourceKind.CardPadding) | The default `Padding`. | + +} +@if (wpf) { +## Theme Assets + +See the [Theme Reusable Assets](../../themes/reusable-assets.md) topic for more details on using and customizing theme assets. The following reusable assets are used by [SettingsCard](xref:@ActiproUIRoot.Controls.Views.SettingsCard): + +| Asset Resource Key | Description | +|-----|-----| +| [CardBorderNormalThicknessKey](xref:@ActiproUIRoot.Themes.AssetResourceKeys.CardBorderNormalThicknessKey) | The default `BorderThickness`. | +| [CardBorderNormalCornerRadiusKey](xref:@ActiproUIRoot.Themes.AssetResourceKeys.CardBorderNormalCornerRadiusKey) | The default [CornerRadius](xref:@ActiproUIRoot.Controls.Card.CornerRadius). | +| [CardBorderNormalThicknessKey](xref:@ActiproUIRoot.Themes.AssetResourceKeys.CardPaddingNormalThicknessKey) | The default `Padding`. | +} \ No newline at end of file diff --git a/Documentation/topics/shared/windows-controls/circular-progressbar.md b/Documentation/topics/shared/windows-controls/circular-progressbar.md index 61b6f646..cdf75aba 100644 --- a/Documentation/topics/shared/windows-controls/circular-progressbar.md +++ b/Documentation/topics/shared/windows-controls/circular-progressbar.md @@ -1,7 +1,7 @@ --- title: "CircularProgressBar" page-title: "CircularProgressBar- Shared Library Controls" -order: 11 +order: 35 --- # CircularProgressBar diff --git a/Documentation/topics/shared/windows-controls/customdrawelement.md b/Documentation/topics/shared/windows-controls/customdrawelement.md index 8cbf299c..d7d72b7f 100644 --- a/Documentation/topics/shared/windows-controls/customdrawelement.md +++ b/Documentation/topics/shared/windows-controls/customdrawelement.md @@ -1,7 +1,7 @@ --- title: "CustomDrawElement" page-title: "CustomDrawElement - Shared Library Controls" -order: 12 +order: 40 --- # CustomDrawElement diff --git a/Documentation/topics/shared/windows-controls/dropshadowchrome.md b/Documentation/topics/shared/windows-controls/dropshadowchrome.md index 63b16909..a38f814a 100644 --- a/Documentation/topics/shared/windows-controls/dropshadowchrome.md +++ b/Documentation/topics/shared/windows-controls/dropshadowchrome.md @@ -1,7 +1,7 @@ --- title: "DropShadowChrome" page-title: "DropShadowChrome - Shared Library Controls" -order: 13 +order: 45 --- # DropShadowChrome diff --git a/Documentation/topics/shared/windows-controls/dynamicimage.md b/Documentation/topics/shared/windows-controls/dynamicimage.md index c18c85e7..720c2ded 100644 --- a/Documentation/topics/shared/windows-controls/dynamicimage.md +++ b/Documentation/topics/shared/windows-controls/dynamicimage.md @@ -1,7 +1,7 @@ --- title: "DynamicImage" page-title: "DynamicImage - Shared Library Controls" -order: 14 +order: 50 --- # DynamicImage diff --git a/Documentation/topics/shared/windows-controls/editablecontentcontrol.md b/Documentation/topics/shared/windows-controls/editablecontentcontrol.md index 97f823c3..173fea1c 100644 --- a/Documentation/topics/shared/windows-controls/editablecontentcontrol.md +++ b/Documentation/topics/shared/windows-controls/editablecontentcontrol.md @@ -1,7 +1,7 @@ --- title: "EditableContentControl" page-title: "EditableContentControl - Shared Library Controls" -order: 16 +order: 55 --- # EditableContentControl diff --git a/Documentation/topics/shared/windows-controls/horizontallistbox.md b/Documentation/topics/shared/windows-controls/horizontallistbox.md index 6f2dc755..733b76b5 100644 --- a/Documentation/topics/shared/windows-controls/horizontallistbox.md +++ b/Documentation/topics/shared/windows-controls/horizontallistbox.md @@ -1,7 +1,7 @@ --- title: "HorizontalListBox" page-title: "HorizontalListBox - Shared Library Controls" -order: 19 +order: 60 --- # HorizontalListBox diff --git a/Documentation/topics/shared/windows-controls/imagetextinfo.md b/Documentation/topics/shared/windows-controls/imagetextinfo.md index b82e49f8..ace8ffef 100644 --- a/Documentation/topics/shared/windows-controls/imagetextinfo.md +++ b/Documentation/topics/shared/windows-controls/imagetextinfo.md @@ -1,7 +1,7 @@ --- title: "ImageTextInfo" page-title: "ImageTextInfo - Shared Library Controls" -order: 21 +order: 65 --- # ImageTextInfo diff --git a/Documentation/topics/shared/windows-controls/index.md b/Documentation/topics/shared/windows-controls/index.md index dbf4394e..6caac15b 100644 --- a/Documentation/topics/shared/windows-controls/index.md +++ b/Documentation/topics/shared/windows-controls/index.md @@ -31,6 +31,10 @@ The [AvatarGroup](avatar-group.md) control renders multiple [Avatar](avatar.md) The [Badge](badge.md) control is used to provide contextual information for other elements or can be used stand-alone. +## The Card Control + +The [Card](card.md) control is typically used to present visually grouped information for a single subject. + ## The CircularProgressBar Control [CircularProgressBar](circular-progressbar.md) displays a ranged progress value using fluent animations. It is similar to a native linear `ProgressBar`, except that it renders the progress in a ring shape. @@ -65,6 +69,10 @@ The [HorizontalListBox](horizontallistbox.md) control is a restyled native `List The [ImageTextInfo](imagetextinfo.md) class is a simple helper class that can be used to store image and text data for databinding. +## The InfoBar Control + +The [InfoBar](info-bar.md) control can be used to display essential information to a user without disrupting the user flow. + ## The PixelSnapper Decorator The [PixelSnapper](pixelsnapper.md) decorator snaps the measurement of its child content to integer values, thereby helping to prevent blurry images and borders that may appear after it. diff --git a/Documentation/topics/shared/windows-controls/info-bar.md b/Documentation/topics/shared/windows-controls/info-bar.md new file mode 100644 index 00000000..277d8d45 --- /dev/null +++ b/Documentation/topics/shared/windows-controls/info-bar.md @@ -0,0 +1,262 @@ +--- +title: "InfoBar" +page-title: "InfoBar - Shared Library Controls" +order: 67 +--- +# InfoBar + +An [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar) can be used to display essential information to a user without disrupting the user flow. + +![Screenshot](../images/info-bar.png) + +*InfoBar with default severity showing a title and message* + +## Title and Message + +The [Title](xref:@ActiproUIRoot.Controls.InfoBar.Title) property is typically set to short text that categorizes the message being displayed while the [Message](xref:@ActiproUIRoot.Controls.InfoBar.Message) property is set to text that provides additional detail. + +The following demonstrates how to create an info bar with a title and message: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + +``` +} +@if (wpf) { +```xaml +xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared" +... + +``` +} + +## Severity + +![Screenshot](../images/info-bar-severity.png) + +*InfoBar with Information, Success, Warning, and Error severities* + +By default, an [InfoBar](xref:@ActiproUIRoot.Controls.InfoBar) is displayed with [Information](xref:@ActiproUIRoot.Controls.InfoBarSeverity.Information) severity, but the [Severity](xref:@ActiproUIRoot.Controls.InfoBar.Severity) property can be set to any one of the [InfoBarSeverity](xref:@ActiproUIRoot.Controls.InfoBarSeverity) values. Each severity automatically applies a default[Icon](xref:@ActiproUIRoot.Controls.InfoBar.Icon) and `Background` brush to visually distinguish one severity from another. + +## Action + +![Screenshot](../images/info-bar-action.png) + +*InfoBar with action button* + +The [Action](xref:@ActiproUIRoot.Controls.InfoBar.Action) can be set to any value supported by `ContentPresenter`, but is typically used to show a button or hyperlink the user can act upon to respond to the message. + +The following demonstrates how to create an info bar with a button for an action: + +@if (avalonia) { +```xaml +xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui" +... + + + + + + + + + + Actipro Ribbon includes a built-in footer for displaying additional content below the Ribbon. The footer + can be set to any content and is great for tips or notifications. + + This sample has been configured with an InfoBar that allows for the configuration of multiple severity + levels, pre-defined or custom images, optional actions/content, and a close button. + + Click the 'Close' button on the InfoBar to hide the MVVM or XAML sample footer. Use the corresponding + 'Show Footer' button to re-display the footer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/OptionsViewModel.cs b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/OptionsViewModel.cs new file mode 100644 index 00000000..f3061bb7 --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/OptionsViewModel.cs @@ -0,0 +1,93 @@ +using ActiproSoftware.Windows; +using ActiproSoftware.Windows.Controls; +using ActiproSoftware.Windows.Controls.Bars; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; + +namespace ActiproSoftware.ProductSamples.BarsSamples.QuickStart.FooterInfoBar { + + /// + /// Defines configurable options for this sample. + /// + public class OptionsViewModel : ObservableObjectBase { + + private bool canClose = true; + private bool isIconVisible = true; + private Thickness padding = new Thickness(10, 5, 10, 5); + private RibbonQuickAccessToolBarLocation qatLocation = RibbonQuickAccessToolBarLocation.Below; + private InfoBarSeverity severity = InfoBarSeverity.Success; + private ICommand showFooterMvvmCommand; + private ICommand showFooterXamlCommand; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Gets or sets if the info bar can be closed. + /// + /// true if the info bar can be closed; otherwise false. + public bool CanClose { + get => canClose; + set => SetProperty(ref canClose, value); + } + + /// + /// Gets or sets if the info bar icon is visible. + /// + /// true if the info bar icon is visible; otherwise false. + public bool IsIconVisible { + get => isIconVisible; + set => SetProperty(ref isIconVisible, value); + } + + /// + /// Gets or sets the padding for the info bar. + /// + /// A value. + public Thickness Padding { + get => padding; + set => SetProperty(ref padding, value); + } + + /// + /// Gets or sets the location of the Quick Access Toolbar. + /// + /// One of the values. + [DisplayName("QAT location")] + public RibbonQuickAccessToolBarLocation QuickAccessToolBarLocation { + get => qatLocation; + set => SetProperty(ref qatLocation, value); + } + + /// + /// Gets of sets the severity of the info bar. + /// + /// One of the values. + public InfoBarSeverity Severity { + get => severity; + set => SetProperty(ref severity, value); + } + + /// + /// Gets or sets the command that will be executed to show the MVVM-based footer. + /// + /// An . + public ICommand ShowFooterMvvmCommand { + get => showFooterMvvmCommand; + set => SetProperty(ref showFooterMvvmCommand, value); + } + + /// + /// Gets or sets the command that will be executed to show the XAML-based footer. + /// + /// An . + public ICommand ShowFooterXamlCommand { + get => showFooterXamlCommand; + set => SetProperty(ref showFooterXamlCommand, value); + } + + } + +} diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleControlBase.cs b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleControlBase.cs new file mode 100644 index 00000000..0f4275cf --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleControlBase.cs @@ -0,0 +1,115 @@ +using ActiproSoftware.ProductSamples.BarsSamples.Common; +using ActiproSoftware.Windows.Controls.Bars.Mvvm; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; + +namespace ActiproSoftware.ProductSamples.BarsSamples.QuickStart.FooterInfoBar { + + /// + /// Provides the base user control of shared logic for this sample that is extended for MVVM- and XAML-based samples. + /// + public abstract class SampleControlBase : UserControl { + + #region Dependency Properties + + public static readonly DependencyProperty OptionsProperty = DependencyProperty.Register(nameof(Options), typeof(OptionsViewModel), typeof(SampleControlBase), new PropertyMetadata(null, OnOptionsPropertyValueChanged)); + + #endregion Dependency Properties + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // OBJECT + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Initializes a new instance of the class. + /// + public SampleControlBase() { + // Initialize the Ribbon view models (used by both XAML and MVVM samples for the Ribbon configuration not related to the footer) + this.Ribbon = InitializeRibbonViewModels(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // NON-PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Occurs when the dependency property value has changed. + /// + /// The sender of the event. + /// The containing data related to this event. + private static void OnOptionsPropertyValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + => ((SampleControlBase)obj).OnOptionsPropertyValueChanged(e.OldValue as OptionsViewModel, e.NewValue as OptionsViewModel); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Initializes the view models for ribbon. + /// + /// A new . + protected virtual RibbonViewModel InitializeRibbonViewModels() { + // The focus of this sample is the Ribbon Footer, so base the MVVM- and XAML-based samples + // will reuse the same core Ribbon MVVM configuration for non-footer configuration to keep + // sample focused only on the footer configuration + var ribbonViewModel = SampleViewModelFactory.CreateDefaultRichTextEditorRibbonWindowViewModel().Ribbon; + ribbonViewModel.IsApplicationButtonVisible = false; + ribbonViewModel.IsCollapsible = false; + return ribbonViewModel; + } + + /// + /// Handles a change in one of the individual property values on . + /// + /// The sender of the event. + /// The event data. + protected virtual void OnOptionsPropertyChanged(object sender, PropertyChangedEventArgs args) { + if (Ribbon == null) + return; + + // Synchronize the footer with current options + UpdateFooter(); + } + + /// + /// Handles a change in the dependency property value. + /// + /// The old value. + /// The new value. + protected virtual void OnOptionsPropertyValueChanged(OptionsViewModel oldValue, OptionsViewModel newValue) { + // Stop listening for changes + if (oldValue != null) + oldValue.PropertyChanged -= OnOptionsPropertyChanged; + + // Listen for changes + if (newValue != null) + newValue.PropertyChanged += OnOptionsPropertyChanged; + + // Synchronize the footer with current options + UpdateFooter(); + + } + + /// + /// Gets or sets the options associated with this control. + /// + public OptionsViewModel Options { + get => (OptionsViewModel)GetValue(OptionsProperty); + set => SetValue(OptionsProperty, value); + } + + /// + /// Gets the view model for the Ribbon control. + /// + /// A . + public RibbonViewModel Ribbon { get; private set; } + + /// + /// Updates the footer based on the current sample options. + /// + protected virtual void UpdateFooter() { /* no op */ } + + } + +} diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml new file mode 100644 index 00000000..2a37be44 --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml.cs b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml.cs new file mode 100644 index 00000000..9920d953 --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleMvvmControl.xaml.cs @@ -0,0 +1,108 @@ +using ActiproSoftware.Windows.Controls.Bars.Mvvm; +using ActiproSoftware.Windows.Input; +using System.Windows; + +namespace ActiproSoftware.ProductSamples.BarsSamples.QuickStart.FooterInfoBar { + + /// + /// Provides the user control for this sample that uses an MVVM-based ribbon configuration. + /// + public partial class SampleMvvmControl : SampleControlBase { + + private RibbonFooterViewModel footerViewModel; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // OBJECT + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Initializes a new instance of the class. + /// + public SampleMvvmControl() { + InitializeComponent(); + + // Configure this code-behind to be the view model for this sample + this.DataContext = this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // NON-PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Gets the view model for the footer. + /// + /// A value. + private RibbonFooterViewModel FooterViewModel { + get { + if (footerViewModel is null) { + footerViewModel = new RibbonFooterViewModel() { + + // The RibbonFooterInfoBarContentViewModel can be used to define a footer + // with features supported by the InfoBar control + Content = new RibbonFooterInfoBarContentViewModel() { + CanClose = Options?.CanClose ?? true, + IsIconVisible = Options?.CanClose ?? true, + Message = "Use an info bar for essential app messages", + Padding = Options?.Padding ?? new Thickness(), + Title = "InfoBar", + Severity = Options?.Severity ?? Windows.Controls.InfoBarSeverity.Information, + }, + + // Footer must not have padding so InfoBar can display edge-to-edge + Padding = new Thickness(), + }; + } + return footerViewModel; + } + } + + /// + /// Shows the footer. + /// + private void ShowFooter() { + // When the footer is closed the view model is cleared. Show the footer again + // by re-assigning the view model that defines the footer + Ribbon.Footer = this.FooterViewModel; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + protected override RibbonViewModel InitializeRibbonViewModels() { + var ribbonViewModel = base.InitializeRibbonViewModels(); + + // Initialize the ribbon with a footer already displayed + ribbonViewModel.Footer = this.FooterViewModel; + + return ribbonViewModel; + } + + /// + protected override void OnOptionsPropertyValueChanged(OptionsViewModel oldValue, OptionsViewModel newValue) { + // Configure the command to show the MVVM-based footer + if (newValue is not null) + newValue.ShowFooterMvvmCommand = new DelegateCommand(_ => ShowFooter()); + + base.OnOptionsPropertyValueChanged(oldValue, newValue); + } + + /// + protected override void UpdateFooter() { + if (Options == null) + return; + + // Update properties to match the sample options + if (FooterViewModel?.Content is RibbonFooterInfoBarContentViewModel infoBarViewModel) { + infoBarViewModel.CanClose = Options.CanClose; + infoBarViewModel.IsIconVisible = Options.IsIconVisible; + infoBarViewModel.Padding = Options.Padding; + infoBarViewModel.Severity = Options.Severity; + } + } + + } + +} diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml new file mode 100644 index 00000000..836a0966 --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml.cs b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml.cs new file mode 100644 index 00000000..5b41066c --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/BarsSamples/QuickStart/FooterInfoBar/SampleXamlControl.xaml.cs @@ -0,0 +1,61 @@ +using ActiproSoftware.Windows.Input; +using System; + +namespace ActiproSoftware.ProductSamples.BarsSamples.QuickStart.FooterInfoBar { + + /// + /// Provides the user control for this sample that uses a XAML-based ribbon configuration. + /// + public partial class SampleXamlControl : SampleControlBase { + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // OBJECT + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Initializes a new instance of the class. + /// + public SampleXamlControl() { + InitializeComponent(); + + // Configure this code-behind to be the view model for this sample + this.DataContext = this; + + // IMPORTANT: This sample uses a RibbonViewModel to help pre-populate the ribbon controls, + // and this will, by default, bind Ribbon.ClearFooterCommand to the RibbonViewModel.ClearFooterCommand. + // Since this sample is not using MVVM footers, restore the default XAML-friendly command logic by setting + // Ribbon.ClearFooterCommand to null. + // + // This step is ONLY necessary if RibbonViewModel is used and the the Ribbon.Footer is defined in XAML. + this.Dispatcher.BeginInvoke((Action)(() => ribbon.ClearFooterCommand = null), System.Windows.Threading.DispatcherPriority.Input); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // NON-PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Shows the footer. + /// + private void ShowFooter() { + // When the footer is closed the FooterContent is cleared. Show the footer again + // by re-assigning the original RibbonFooterControl to the FooterContent + ribbon.FooterContent = footer; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // PUBLIC PROCEDURES + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + protected override void OnOptionsPropertyValueChanged(OptionsViewModel oldValue, OptionsViewModel newValue) { + // Configure the command to show the MVVM-based footer + if (newValue is not null) + newValue.ShowFooterXamlCommand = new DelegateCommand(_ => ShowFooter()); + + base.OnOptionsPropertyValueChanged(oldValue, newValue); + } + + } + +} diff --git a/Samples/SampleBrowser/ProductSamples/EditorsSamples/Common/EnumWithoutFlags.cs b/Samples/SampleBrowser/ProductSamples/EditorsSamples/Common/EnumWithoutFlags.cs index 5f62225b..f32d134c 100644 --- a/Samples/SampleBrowser/ProductSamples/EditorsSamples/Common/EnumWithoutFlags.cs +++ b/Samples/SampleBrowser/ProductSamples/EditorsSamples/Common/EnumWithoutFlags.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.ComponentModel.DataAnnotations; namespace ActiproSoftware.ProductSamples.EditorsSamples.Common { @@ -11,43 +12,43 @@ public enum EnumWithoutFlags { /// /// Indicates no value. /// - [Description("Nada")] + [Display(Order = 0, Name = "Nada")] None = 0, /// /// Indicates the value 1. /// - [Description("Uno")] + [Display(Order = 1, Name = "Uno")] One = 0x01, /// /// Indicates the value 2. /// - [Description("One and One")] + [Display(Order = 2, Name = "One and One")] Two = 0x02, /// /// Indicates the value 4. /// - [Description("Square root of 16")] + [Display(Order = 4, Name = "Square root of 16")] Four = 0x04, /// /// Indicates the value 8. /// - [Description("2 to the power of 3")] + [Display(Order = 8, Name = "2 to the power of 3")] Eight = 0x08, /// /// Indicates the union of One and Two. /// - [Description("An odd number")] + [Display(Order = 3, Name = "An odd number")] Three = One | Two, /// /// Indicates the union of One, Two, Four, and Eight. /// - [Description("Everything")] + [Display(Name = "Everything")] All = One | Two | Four | Eight } diff --git a/Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/CardIntro/MainControl.xaml b/Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/CardIntro/MainControl.xaml new file mode 100644 index 00000000..b8b62cb3 --- /dev/null +++ b/Samples/SampleBrowser/ProductSamples/SharedSamples/QuickStart/CardIntro/MainControl.xaml @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The Card control is used to group related information for a single subject. + + + Cards can be display-only or actionable like a button. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +