From cdef4fcef62d3aca1a7f2afb89d4799ce83c1dc3 Mon Sep 17 00:00:00 2001 From: Yimeng Wu Date: Mon, 2 Nov 2020 01:35:12 +0800 Subject: [PATCH 01/10] * Rename FindElementOfTypeInSubtree -> FindVisualChildByType (microsoft/microsoft-ui-xaml#3438) --- .../ModernWpfTestApp/CommonStylesPage.xaml.cs | 2 +- .../ItemsViewWithDataPage.xaml.cs | 2 +- .../Utilities/VisualTreeUtils.cs | 32 +++++++++---------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/test/ModernWpfTestApp/CommonStylesPage.xaml.cs b/test/ModernWpfTestApp/CommonStylesPage.xaml.cs index a8216697..7d0083a1 100644 --- a/test/ModernWpfTestApp/CommonStylesPage.xaml.cs +++ b/test/ModernWpfTestApp/CommonStylesPage.xaml.cs @@ -222,7 +222,7 @@ private void TimePickerDensityTest_Click(object sender, RoutedEventArgs e) private void ListViewItemDensityTest_Click(object sender, RoutedEventArgs e) { - var item = ListView1.FindElementOfTypeInSubtree(); + var item = ListView1.FindVisualChildByType(); SimpleVerify simpleVerify = new SimpleVerify(); if (item != null) { diff --git a/test/ModernWpfTestApp/Samples/LayoutSamples/NestedLayoutSamples/ItemsViewWithDataPage.xaml.cs b/test/ModernWpfTestApp/Samples/LayoutSamples/NestedLayoutSamples/ItemsViewWithDataPage.xaml.cs index 1e00c9b0..c30c6d25 100644 --- a/test/ModernWpfTestApp/Samples/LayoutSamples/NestedLayoutSamples/ItemsViewWithDataPage.xaml.cs +++ b/test/ModernWpfTestApp/Samples/LayoutSamples/NestedLayoutSamples/ItemsViewWithDataPage.xaml.cs @@ -240,7 +240,7 @@ private void OnScrollButtonClicked(object sender, RoutedEventArgs e) if (i < indexPath.Length - 1) { - repeater = container.FindElementOfTypeInSubtree(); + repeater = container.FindVisualChildByType(); } else { diff --git a/test/ModernWpfTestApp/Utilities/VisualTreeUtils.cs b/test/ModernWpfTestApp/Utilities/VisualTreeUtils.cs index 0de679fd..c74ca649 100644 --- a/test/ModernWpfTestApp/Utilities/VisualTreeUtils.cs +++ b/test/ModernWpfTestApp/Utilities/VisualTreeUtils.cs @@ -8,7 +8,7 @@ namespace MUXControlsTestApp.Utilities { public static class VisualTreeUtils { - public static T FindElementOfTypeInSubtree(this DependencyObject element) + public static T FindVisualChildByType(this DependencyObject element) where T : DependencyObject { if (element == null) @@ -16,15 +16,15 @@ public static T FindElementOfTypeInSubtree(this DependencyObject element) return null; } - if (element is T) + if (element is T elementAsT) { - return (T)element; + return elementAsT; } int childrenCount = VisualTreeHelper.GetChildrenCount(element); for (int i = 0; i < childrenCount; i++) { - var result = FindElementOfTypeInSubtree(VisualTreeHelper.GetChild(element, i)); + var result = VisualTreeHelper.GetChild(element, i).FindVisualChildByType(); if (result != null) { return result; @@ -34,27 +34,25 @@ public static T FindElementOfTypeInSubtree(this DependencyObject element) return null; } - public static DependencyObject FindVisualChildByName(FrameworkElement parent, string name) + public static FrameworkElement FindVisualChildByName(this DependencyObject element, string name) { - if (parent.Name == name) + if (element == null || string.IsNullOrWhiteSpace(name)) { - return parent; + return null; } - int childrenCount = VisualTreeHelper.GetChildrenCount(parent); + if (element is FrameworkElement elementAsFE && elementAsFE.Name == name) + { + return elementAsFE; + } + int childrenCount = VisualTreeHelper.GetChildrenCount(element); for (int i = 0; i < childrenCount; i++) { - FrameworkElement childAsFE = VisualTreeHelper.GetChild(parent, i) as FrameworkElement; - - if (childAsFE != null) + var result = VisualTreeHelper.GetChild(element, i).FindVisualChildByName(name); + if (result != null) { - DependencyObject result = FindVisualChildByName(childAsFE, name); - - if (result != null) - { - return result; - } + return result; } } From 3ef3861736f324395cfed3652583e62367ba1199 Mon Sep 17 00:00:00 2001 From: Shankar Date: Fri, 6 Nov 2020 15:07:25 +0530 Subject: [PATCH 02/10] Added localization string resources of TeachingTip --- ModernWpf/Resources/Strings.Designer.cs | 45 ++++++++++++++++++++++++ ModernWpf/Resources/Strings.cs.resx | 20 +++++++++++ ModernWpf/Resources/Strings.de.resx | 20 +++++++++++ ModernWpf/Resources/Strings.es.resx | 20 +++++++++++ ModernWpf/Resources/Strings.fa.resx | 20 +++++++++++ ModernWpf/Resources/Strings.fr.resx | 20 +++++++++++ ModernWpf/Resources/Strings.it.resx | 20 +++++++++++ ModernWpf/Resources/Strings.ja.resx | 20 +++++++++++ ModernWpf/Resources/Strings.ko.resx | 20 +++++++++++ ModernWpf/Resources/Strings.pl.resx | 20 +++++++++++ ModernWpf/Resources/Strings.pt-BR.resx | 20 +++++++++++ ModernWpf/Resources/Strings.resx | 20 +++++++++++ ModernWpf/Resources/Strings.ru.resx | 20 +++++++++++ ModernWpf/Resources/Strings.tr.resx | 20 +++++++++++ ModernWpf/Resources/Strings.zh-Hans.resx | 20 +++++++++++ ModernWpf/Resources/Strings.zh-Hant.resx | 20 +++++++++++ 16 files changed, 345 insertions(+) diff --git a/ModernWpf/Resources/Strings.Designer.cs b/ModernWpf/Resources/Strings.Designer.cs index c0c13c54..26d834db 100644 --- a/ModernWpf/Resources/Strings.Designer.cs +++ b/ModernWpf/Resources/Strings.Designer.cs @@ -438,6 +438,51 @@ internal static string SplitButtonSecondaryButtonName { } } + /// + /// Looks up a localized string similar to Close. + /// + internal static string TeachingTipAlternateCloseButtonName { + get { + return ResourceManager.GetString("TeachingTipAlternateCloseButtonName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close. + /// + internal static string TeachingTipAlternateCloseButtonTooltip { + get { + return ResourceManager.GetString("TeachingTipAlternateCloseButtonTooltip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tip. + /// + internal static string TeachingTipCustomLandmarkName { + get { + return ResourceManager.GetString("TeachingTipCustomLandmarkName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press F6 to go to new notification from {0}, {1}.. + /// + internal static string TeachingTipNotification { + get { + return ResourceManager.GetString("TeachingTipNotification", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Press F6 to go to new notification, {0}.. + /// + internal static string TeachingTipNotificationWithoutAppName { + get { + return ResourceManager.GetString("TeachingTipNotificationWithoutAppName", resourceCulture); + } + } + /// /// Looks up a localized string similar to Copy. /// diff --git a/ModernWpf/Resources/Strings.cs.resx b/ModernWpf/Resources/Strings.cs.resx index 76bbcacc..eab00bfc 100644 --- a/ModernWpf/Resources/Strings.cs.resx +++ b/ModernWpf/Resources/Strings.cs.resx @@ -268,4 +268,24 @@ Nastavení Automation name for the settings button + + Zavřít + This is the automation name of the alternate close button. + + + Zavřít + This is the string used for the alternate close button's tooltip + + + Tip + This is the custom landmark used to denote a tip to narrator. + + + Stisknutím klávesy F6 přejdete na nové oznámení z aplikace {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Stisknutím klávesy F6 přejdete na nové oznámení, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.de.resx b/ModernWpf/Resources/Strings.de.resx index cd6b60c8..56c645f4 100644 --- a/ModernWpf/Resources/Strings.de.resx +++ b/ModernWpf/Resources/Strings.de.resx @@ -268,4 +268,24 @@ Einstellungen Automation name for the settings button + + Schließen + This is the automation name of the alternate close button. + + + Schließen + This is the string used for the alternate close button's tooltip + + + Tipp + This is the custom landmark used to denote a tip to narrator. + + + Drücken Sie F6, um auf die neue Benachrichtigung zu {0}, {1} zuzugreifen. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Drücken Sie F6, um auf die neue Benachrichtigung zu {0} zuzugreifen. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.es.resx b/ModernWpf/Resources/Strings.es.resx index 20e0b569..2c1af593 100644 --- a/ModernWpf/Resources/Strings.es.resx +++ b/ModernWpf/Resources/Strings.es.resx @@ -268,4 +268,24 @@ Configuración Automation name for the settings button + + Cerrar + This is the automation name of the alternate close button. + + + Cerrar + This is the string used for the alternate close button's tooltip + + + Sugerencia + This is the custom landmark used to denote a tip to narrator. + + + Presiona F6 para ir a la nueva notificación de {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Presiona F6 para ir a la nueva notificación, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.fa.resx b/ModernWpf/Resources/Strings.fa.resx index 421c8598..40dcf744 100644 --- a/ModernWpf/Resources/Strings.fa.resx +++ b/ModernWpf/Resources/Strings.fa.resx @@ -313,4 +313,24 @@ تنظیمات Automation name for the settings button + + بستن + This is the automation name of the alternate close button. + + + بستن + This is the string used for the alternate close button's tooltip + + + ترفند + This is the custom landmark used to denote a tip to narrator. + + + برای رفتن به اعلان جدید از {0}، {1}، F6 را فشار دهید. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + برای رفتن به اعلان جدید از {0}، F6 را فشار دهید. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.fr.resx b/ModernWpf/Resources/Strings.fr.resx index a496cd1e..dfc090c2 100644 --- a/ModernWpf/Resources/Strings.fr.resx +++ b/ModernWpf/Resources/Strings.fr.resx @@ -268,4 +268,24 @@ Paramètres Automation name for the settings button + + Fermer + This is the automation name of the alternate close button. + + + Fermer + This is the string used for the alternate close button's tooltip + + + Astuce + This is the custom landmark used to denote a tip to narrator. + + + Appuyez sur F6 pour accéder à la nouvelle notification de {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Appuyez sur F6 pour accéder à la nouvelle notification, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.it.resx b/ModernWpf/Resources/Strings.it.resx index 8ec3d029..4795b531 100644 --- a/ModernWpf/Resources/Strings.it.resx +++ b/ModernWpf/Resources/Strings.it.resx @@ -268,4 +268,24 @@ Impostazioni Automation name for the settings button + + Chiudi + This is the automation name of the alternate close button. + + + Chiudi + This is the string used for the alternate close button's tooltip + + + Suggerimento + This is the custom landmark used to denote a tip to narrator. + + + Premi F6 per passare alla nuova notifica da {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Premi F6 per passare alla nuova notifica, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.ja.resx b/ModernWpf/Resources/Strings.ja.resx index 68d0de58..cf9f0669 100644 --- a/ModernWpf/Resources/Strings.ja.resx +++ b/ModernWpf/Resources/Strings.ja.resx @@ -268,4 +268,24 @@ 設定 Automation name for the settings button + + 閉じる + This is the automation name of the alternate close button. + + + 閉じる + This is the string used for the alternate close button's tooltip + + + ヒント + This is the custom landmark used to denote a tip to narrator. + + + {0} からの新しい通知 ({1}) にアクセスするには、F6 キーを押してください。 + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + 新しい通知 {0} にアクセスするには、F6 キーを押してください。 + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.ko.resx b/ModernWpf/Resources/Strings.ko.resx index 17b7bf2f..ef9c201c 100644 --- a/ModernWpf/Resources/Strings.ko.resx +++ b/ModernWpf/Resources/Strings.ko.resx @@ -268,4 +268,24 @@ 설정 Automation name for the settings button + + 닫기 + This is the automation name of the alternate close button. + + + 닫기 + This is the string used for the alternate close button's tooltip + + + + This is the custom landmark used to denote a tip to narrator. + + + F6 키를 눌러 {0}, {1}의 새 알림으로 이동하세요. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + F6 키를 눌러 새 알림, {0}(으)로 이동하세요. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.pl.resx b/ModernWpf/Resources/Strings.pl.resx index 046df708..e4fb8b27 100644 --- a/ModernWpf/Resources/Strings.pl.resx +++ b/ModernWpf/Resources/Strings.pl.resx @@ -268,4 +268,24 @@ Ustawienia Automation name for the settings button + + Zamknij + This is the automation name of the alternate close button. + + + Zamknij + This is the string used for the alternate close button's tooltip + + + Wskazówka + This is the custom landmark used to denote a tip to narrator. + + + Naciśnij klawisz F6, aby przejść do nowego powiadomienia z aplikacji {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Naciśnij klawisz F6, aby przejść do nowego powiadomienia {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.pt-BR.resx b/ModernWpf/Resources/Strings.pt-BR.resx index 109b7eb4..4e22c074 100644 --- a/ModernWpf/Resources/Strings.pt-BR.resx +++ b/ModernWpf/Resources/Strings.pt-BR.resx @@ -268,4 +268,24 @@ Configurações Automation name for the settings button + + Fechar + This is the automation name of the alternate close button. + + + Fechar + This is the string used for the alternate close button's tooltip + + + Dica + This is the custom landmark used to denote a tip to narrator. + + + Pressione F6 para ir para a nova notificação de {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Pressione F6 para ir para a nova notificação, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.resx b/ModernWpf/Resources/Strings.resx index 470f248a..12657c6f 100644 --- a/ModernWpf/Resources/Strings.resx +++ b/ModernWpf/Resources/Strings.resx @@ -317,4 +317,24 @@ More ToolTip caption for the nav view more button when panel is on top + + Close + This is the automation name of the alternate close button. + + + Close + This is the string used for the alternate close button's tooltip + + + Tip + This is the custom landmark used to denote a tip to narrator. + + + Press F6 to go to new notification from {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Press F6 to go to new notification, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.ru.resx b/ModernWpf/Resources/Strings.ru.resx index 5c3f268f..125059ed 100644 --- a/ModernWpf/Resources/Strings.ru.resx +++ b/ModernWpf/Resources/Strings.ru.resx @@ -268,4 +268,24 @@ Параметры Automation name for the settings button + + Закрыть + This is the automation name of the alternate close button. + + + Закрыть + This is the string used for the alternate close button's tooltip + + + Совет + This is the custom landmark used to denote a tip to narrator. + + + Нажмите клавишу F6, чтобы перейти к новому уведомлению от {0}, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Нажмите клавишу F6, чтобы перейти к новому уведомлению, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.tr.resx b/ModernWpf/Resources/Strings.tr.resx index ef610a56..ddfc3be3 100644 --- a/ModernWpf/Resources/Strings.tr.resx +++ b/ModernWpf/Resources/Strings.tr.resx @@ -268,4 +268,24 @@ Ayarlar Automation name for the settings button + + Kapat + This is the automation name of the alternate close button. + + + Kapat + This is the string used for the alternate close button's tooltip + + + İpucu + This is the custom landmark used to denote a tip to narrator. + + + {0} tarafından gelen yeni bildirime gitmek için F6 tuşuna basın, {1}. + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + Yeni bildirime gitmek için F6 tuşuna basın, {0}. + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.zh-Hans.resx b/ModernWpf/Resources/Strings.zh-Hans.resx index 502d5c7c..6cb13443 100644 --- a/ModernWpf/Resources/Strings.zh-Hans.resx +++ b/ModernWpf/Resources/Strings.zh-Hans.resx @@ -268,4 +268,24 @@ 设置 Automation name for the settings button + + 关闭 + This is the automation name of the alternate close button. + + + 关闭 + This is the string used for the alternate close button's tooltip + + + 提示 + This is the custom landmark used to denote a tip to narrator. + + + 按 F6 转到来自 {0}、{1} 新的通知。 + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + 按 F6 转到新的通知 {0}。 + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file diff --git a/ModernWpf/Resources/Strings.zh-Hant.resx b/ModernWpf/Resources/Strings.zh-Hant.resx index d51f4155..87384667 100644 --- a/ModernWpf/Resources/Strings.zh-Hant.resx +++ b/ModernWpf/Resources/Strings.zh-Hant.resx @@ -268,4 +268,24 @@ 設定 Automation name for the settings button + + 關閉 + This is the automation name of the alternate close button. + + + 關閉 + This is the string used for the alternate close button's tooltip + + + 提示 + This is the custom landmark used to denote a tip to narrator. + + + 按一下 F6,前往來自 {0},{1} 的新通知。 + This is the formarted string read by narrator when a new tip is opened. It is "Press F6 to go to new notification from 'AppName', 'TipTitle'. + + + 按一下 F6 前往新通知,{0}。 + This is the formatted string read by narrator when a new tip is opened and the app name is not available. it is "Press F6 to go to new notification, 'TipTitle'. + \ No newline at end of file From 35bfa14fcd91619dfcf851415187f29b05047b1f Mon Sep 17 00:00:00 2001 From: Shankar Date: Fri, 6 Nov 2020 15:09:03 +0530 Subject: [PATCH 03/10] Initial porting --- ModernWpf.Controls/TeachingTip/Enums.cs | 45 ++++++ ModernWpf.Controls/TeachingTip/TeachingTip.cs | 8 ++ .../TeachingTip/TeachingTipAutomationPeer.cs | 131 ++++++++++++++++++ .../TeachingTip/TeachingTipClosedEventArgs.cs | 14 ++ .../TeachingTipClosingEventArgs.cs | 50 +++++++ .../TeachingTipTemplateSettings.cs | 59 ++++++++ ModernWpf/Common/Deferral.cs | 38 +++++ 7 files changed, 345 insertions(+) create mode 100644 ModernWpf.Controls/TeachingTip/Enums.cs create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTip.cs create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTipClosedEventArgs.cs create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTipClosingEventArgs.cs create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTipTemplateSettings.cs create mode 100644 ModernWpf/Common/Deferral.cs diff --git a/ModernWpf.Controls/TeachingTip/Enums.cs b/ModernWpf.Controls/TeachingTip/Enums.cs new file mode 100644 index 00000000..7253852f --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/Enums.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + + +namespace ModernWpf.Controls +{ + public enum TeachingTipTailVisibility + { + Auto, + Visible, + Collapsed, + }; + + public enum TeachingTipCloseReason + { + CloseButton, + LightDismiss, + Programmatic, + }; + + public enum TeachingTipPlacementMode + { + Auto, + Top, + Bottom, + Left, + Right, + TopRight, + TopLeft, + BottomRight, + BottomLeft, + LeftTop, + LeftBottom, + RightTop, + RightBottom, + Center + }; + + public enum TeachingTipHeroContentPlacementMode + { + Auto, + Top, + Bottom, + }; +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTip.cs b/ModernWpf.Controls/TeachingTip/TeachingTip.cs new file mode 100644 index 00000000..6385f7c1 --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTip.cs @@ -0,0 +1,8 @@ +using System.Windows.Controls; + +namespace ModernWpf.Controls +{ + public class TeachingTip : ContentControl + { + } +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs b/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs new file mode 100644 index 00000000..c830dfdc --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs @@ -0,0 +1,131 @@ +using System.Windows.Automation; +using System.Windows.Automation.Peers; +using ModernWpf.Controls; + +namespace ModernWpf.Automation.Peers +{ + public class TeachingTipAutomationPeer : FrameworkElementAutomationPeer + { + public TeachingTipAutomationPeer(TeachingTip owner) : base(owner) + { + } + + protected override AutomationControlType GetAutomationControlTypeCore() + { + if (GetTeachingTip() != null/*.IsLightDismissEnabled*/) + { + return AutomationControlType.Window; + } + else + { + return AutomationControlType.Pane; + } + } + + protected override string GetClassNameCore() + { + return nameof(TeachingTip); + } + + private WindowInteractionState InteractionState() + { + //var teachingTip = GetTeachingTip(); + //if (teachingTip.m_isIdle && teachingTip.IsOpen) + //{ + // return WindowInteractionState.ReadyForUserInteraction; + //} + //else if (teachingTip.m_isIdle && !teachingTip.IsOpen) + //{ + // return WindowInteractionState.BlockedByModalWindow; + //} + //else if (!teachingTip.m_isIdle && !teachingTip.IsOpen) + //{ + // return WindowInteractionState.Closing; + //} + //else + //{ + // return WindowInteractionState.Running; + //} + + return WindowInteractionState.Running; + } + + private bool IsModal() + { + return GetTeachingTip() != null/*.IsLightDismissEnabled*/; + } + + private bool IsTopMost() + { + return GetTeachingTip() != null/*.IsOpen*/; + } + + private bool Maximizable() + { + return false; + } + + private bool Minimizable() + { + return false; + } + + private WindowVisualState VisualState() + { + return WindowVisualState.Normal; + } + + private void Close() + { + GetTeachingTip()/*.IsOpen = false*/; + } + + private void SetVisualState(WindowVisualState state) + { + + } + + private bool WaitForInputIdle(int milliseconds) + { + return true; + } + + // Didn't implement these as AutomationEvents.WindowOpened & AutomationEvents.WindowClosed are not present in WPF + + //internal void RaiseWindowClosedEvent() + //{ + // We only report as a window when light dismiss is enabled. + // if (GetTeachingTip().IsLightDismissEnabled && + // ListenerExists(AutomationEvents.WindowClosed)) + // { + // RaiseAutomationEvent(AutomationEvents.WindowClosed); + // } + //} + + //internal void RaiseWindowOpenedEvent(string displayString) + //{ + // AutomationPeer automationPeer7 = this; + // if (automationPeer7 != null) + // { + // //automationPeer7.RaiseNotificationEvent( + // // Automation.Peers.AutomationNotificationKind.Other, + // // Peers.AutomationNotificationProcessing.CurrentThenMostRecent, + // // displayString, + // // L"TeachingTipOpenedActivityId"); + // } + + // // We only report as a window when light dismiss is enabled. + // if (GetTeachingTip().IsLightDismissEnabled && + // AutomationPeer.ListenerExists(AutomationEvents.WindowOpened)) + // { + // RaiseAutomationEvent(AutomationEvents.WindowOpened); + // } + //} + + TeachingTip GetTeachingTip() + { + var owner = Owner; + return (TeachingTip)owner; + } + } +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTipClosedEventArgs.cs b/ModernWpf.Controls/TeachingTip/TeachingTipClosedEventArgs.cs new file mode 100644 index 00000000..3951854d --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTipClosedEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace ModernWpf.Controls +{ + public sealed class TeachingTipClosedEventArgs : EventArgs + { + internal TeachingTipClosedEventArgs(TeachingTipCloseReason reason) + { + Reason = reason; + } + + public TeachingTipCloseReason Reason { get; } + } +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTipClosingEventArgs.cs b/ModernWpf.Controls/TeachingTip/TeachingTipClosingEventArgs.cs new file mode 100644 index 00000000..3d855163 --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTipClosingEventArgs.cs @@ -0,0 +1,50 @@ +using System; +using System.Diagnostics; + +namespace ModernWpf.Controls +{ + public sealed class TeachingTipClosingEventArgs : EventArgs + { + private Deferral m_deferral; + private int m_deferralCount; + + internal TeachingTipClosingEventArgs(TeachingTipCloseReason reason) + { + Reason = reason; + } + + public bool Cancel { get; set; } + + public TeachingTipCloseReason Reason { get; } + + public Deferral GetDeferral() + { + m_deferralCount++; + + return new Deferral(() => + { + DecrementDeferralCount(); + }); + } + + internal void SetDeferral(Deferral deferral) + { + m_deferral = deferral; + } + + internal void DecrementDeferralCount() + { + Debug.Assert(m_deferralCount > 0); + m_deferralCount--; + if (m_deferralCount == 0) + { + m_deferral.Complete(); + } + } + + internal void IncrementDeferralCount() + { + m_deferralCount++; + } + } +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTipTemplateSettings.cs b/ModernWpf.Controls/TeachingTip/TeachingTipTemplateSettings.cs new file mode 100644 index 00000000..672e2c94 --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTipTemplateSettings.cs @@ -0,0 +1,59 @@ +using System.Windows; + +namespace ModernWpf.Controls +{ + public class TeachingTipTemplateSettings : DependencyObject + { + public TeachingTipTemplateSettings() + { + } + + #region IconElement + + public static readonly DependencyProperty IconElementProperty = + DependencyProperty.Register( + nameof(IconElement), + typeof(IconElement), + typeof(TeachingTipTemplateSettings)); + + public IconElement IconElement + { + get => (IconElement)GetValue(IconElementProperty); + set => SetValue(IconElementProperty, value); + } + + #endregion + + #region TopLeftHighlightMargin + + public static readonly DependencyProperty TopLeftHighlightMarginProperty = + DependencyProperty.Register( + nameof(TopLeftHighlightMargin), + typeof(Thickness), + typeof(TeachingTipTemplateSettings)); + + public Thickness TopLeftHighlightMargin + { + get => (Thickness)GetValue(TopLeftHighlightMarginProperty); + set => SetValue(TopLeftHighlightMarginProperty, value); + } + + #endregion + + #region TopRightHighlightMargin + + public static readonly DependencyProperty TopRightHighlightMarginProperty = + DependencyProperty.Register( + nameof(TopRightHighlightMargin), + typeof(Thickness), + typeof(TeachingTipTemplateSettings)); + + public Thickness TopRightHighlightMargin + { + get => (Thickness)GetValue(TopRightHighlightMarginProperty); + set => SetValue(TopRightHighlightMarginProperty, value); + } + + #endregion + } +} diff --git a/ModernWpf/Common/Deferral.cs b/ModernWpf/Common/Deferral.cs new file mode 100644 index 00000000..d7affdcb --- /dev/null +++ b/ModernWpf/Common/Deferral.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +namespace ModernWpf +{ + /// + /// Represents a method that handles the completed event of a deferred action. + /// + public delegate void DeferralCompletedHandler(); + + /// + /// Stores a to be invoked upon completion of the deferral + /// and manipulates the state of the deferral. + /// + public class Deferral : IDisposable + { + private readonly DeferralCompletedHandler _handler; + + /// + /// Initializes a new object and specifies a + /// to be called upon completion of the deferral. + /// + /// A to be called upon completion of the deferral. + public Deferral([In] DeferralCompletedHandler handler) + { + _handler = handler; + } + + /// + /// If the has not yet been invoked, this will call it + /// and drop the reference to the delegate. + /// + public void Complete() => _handler?.Invoke(); + + /// + public void Dispose() { } + } +} From ed116b7a3b610757ca8d5f0ff9615957c39178ed Mon Sep 17 00:00:00 2001 From: Shankar Date: Fri, 6 Nov 2020 21:51:17 +0530 Subject: [PATCH 04/10] Added basic support for IconSource and its subclasses (#192) * Ported IconSource and its sub classes from WinUI * Resolved suggestions * Added headers with copyright & license notices to avoid potential licensing issues * Removed an unnecessary duplicate class and moved code into an existing file to resolved CS0436 warning --- ModernWpf.Controls/Common/SharedHelpers.cs | 72 +++++++++++ ModernWpf/IconSource/BitmapIconSource.cs | 63 ++++++++++ ModernWpf/IconSource/FontIconSource.cs | 135 +++++++++++++++++++++ ModernWpf/IconSource/IconSource.cs | 36 ++++++ ModernWpf/IconSource/PathIconSource.cs | 42 +++++++ ModernWpf/IconSource/SymbolIconSource.cs | 42 +++++++ 6 files changed, 390 insertions(+) create mode 100644 ModernWpf/IconSource/BitmapIconSource.cs create mode 100644 ModernWpf/IconSource/FontIconSource.cs create mode 100644 ModernWpf/IconSource/IconSource.cs create mode 100644 ModernWpf/IconSource/PathIconSource.cs create mode 100644 ModernWpf/IconSource/SymbolIconSource.cs diff --git a/ModernWpf.Controls/Common/SharedHelpers.cs b/ModernWpf.Controls/Common/SharedHelpers.cs index 49266990..c88dcdad 100644 --- a/ModernWpf.Controls/Common/SharedHelpers.cs +++ b/ModernWpf.Controls/Common/SharedHelpers.cs @@ -158,6 +158,78 @@ public static void RaiseAutomationPropertyChangedEvent(UIElement element, object } } + public static IconElement MakeIconElementFrom(IconSource iconSource) + { + if (iconSource is FontIconSource fontIconSource) + { + FontIcon fontIcon = new FontIcon(); + + fontIcon.Glyph = fontIconSource.Glyph; + fontIcon.FontSize = fontIconSource.FontSize; + if (fontIconSource.Foreground is Brush newForeground) + { + fontIcon.Foreground = newForeground; + } + + if (fontIconSource.FontFamily != null) + { + fontIcon.FontFamily = fontIconSource.FontFamily; + } + + fontIcon.FontWeight = fontIconSource.FontWeight; + fontIcon.FontStyle = fontIconSource.FontStyle; + //fontIcon.IsTextScaleFactorEnabled(fontIconSource.IsTextScaleFactorEnabled()); + //fontIcon.MirroredWhenRightToLeft(fontIconSource.MirroredWhenRightToLeft()); + + return fontIcon; + } + else if (iconSource is SymbolIconSource symbolIconSource) + { + SymbolIcon symbolIcon = new SymbolIcon(); + symbolIcon.Symbol = symbolIconSource.Symbol; + if (symbolIconSource.Foreground is Brush newForeground) + { + symbolIcon.Foreground = newForeground; + } + + return symbolIcon; + } + else if (iconSource is BitmapIconSource bitmapIconSource) + { + BitmapIcon bitmapIcon = new BitmapIcon(); + + if (bitmapIconSource.UriSource != null) + { + bitmapIcon.UriSource = bitmapIconSource.UriSource; + } + + bitmapIcon.ShowAsMonochrome = bitmapIconSource.ShowAsMonochrome; + if (bitmapIconSource.Foreground is Brush newForeground) + { + bitmapIcon.Foreground = newForeground; + } + + return bitmapIcon; + } + else if (iconSource is PathIconSource pathIconSource) + { + PathIcon pathIcon = new PathIcon(); + + if (pathIconSource.Data != null) + { + pathIcon.Data = pathIconSource.Data; + } + if (pathIconSource.Foreground is Brush newForeground) + { + pathIcon.Foreground = newForeground; + } + + return pathIcon; + } + + return null; + } + public static BindingExpressionBase SetBinding( this FrameworkElement element, DependencyProperty dp, diff --git a/ModernWpf/IconSource/BitmapIconSource.cs b/ModernWpf/IconSource/BitmapIconSource.cs new file mode 100644 index 00000000..13dc2b77 --- /dev/null +++ b/ModernWpf/IconSource/BitmapIconSource.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Windows; +using System.Windows.Media.Imaging; + +namespace ModernWpf.Controls +{ + /// + /// Represents an icon source that uses a bitmap as its content. + /// + public class BitmapIconSource : IconSource + { + /// + /// Initializes a new instance of the class. + /// + public BitmapIconSource() + { + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty UriSourceProperty = + BitmapImage.UriSourceProperty.AddOwner(typeof(BitmapIconSource)); + + /// + /// Gets or sets the Uniform Resource Identifier (URI) of the bitmap to use as the icon content. + /// + /// + /// The of the bitmap to use as the icon content. The default is . + /// + public Uri UriSource + { + get => (Uri)GetValue(UriSourceProperty); + set => SetValue(UriSourceProperty, value); + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ShowAsMonochromeProperty = + DependencyProperty.Register( + nameof(ShowAsMonochrome), + typeof(bool), + typeof(BitmapIconSource), + new PropertyMetadata(true)); + + /// + /// Gets or sets a value that indicates whether the bitmap is shown in a single color. + /// + /// + /// to show the bitmap in a single color; + /// to show the bitmap in full color. The default is . + /// + public bool ShowAsMonochrome + { + get => (bool)GetValue(ShowAsMonochromeProperty); + set => SetValue(ShowAsMonochromeProperty, value); + } + } +} diff --git a/ModernWpf/IconSource/FontIconSource.cs b/ModernWpf/IconSource/FontIconSource.cs new file mode 100644 index 00000000..5b1f29cf --- /dev/null +++ b/ModernWpf/IconSource/FontIconSource.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; +using System.Windows.Media; + +namespace ModernWpf.Controls +{ + /// + /// Represents an icon source that uses a glyph from the specified font. + /// + public class FontIconSource : IconSource + { + const string c_fontIconSourceDefaultFontFamily = "Segoe MDL2 Assets"; + + /// + /// Initializes a new instance of the class. + /// + public FontIconSource() + { + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FontFamilyProperty = + DependencyProperty.Register( + nameof(FontFamily), + typeof(FontFamily), + typeof(FontIconSource), + new PropertyMetadata(new FontFamily(c_fontIconSourceDefaultFontFamily))); + + /// + /// Gets or sets the font used to display the icon glyph. + /// + /// + /// The font used to display the icon glyph. + /// + public FontFamily FontFamily + { + get => (FontFamily)GetValue(FontFamilyProperty); + set => SetValue(FontFamilyProperty, value); + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FontSizeProperty = + DependencyProperty.Register( + nameof(FontSize), + typeof(double), + typeof(FontIconSource), + new PropertyMetadata(20.0)); + + /// + /// Gets or sets the size of the icon glyph. + /// + /// + /// A non-negative value that specifies the font size, measured in pixels. + /// + public double FontSize + { + get => (double)GetValue(FontSizeProperty); + set => SetValue(FontSizeProperty, value); + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FontStyleProperty = + DependencyProperty.Register( + nameof(FontStyle), + typeof(FontStyle), + typeof(FontIconSource), + new PropertyMetadata(FontStyles.Normal)); + + /// + /// Gets or sets the font style for the icon glyph. + /// + /// + /// A named constant of the enumeration that specifies the style in which the icon glyph is rendered. + /// The default is . + /// + public FontStyle FontStyle + { + get => (FontStyle)GetValue(FontStyleProperty); + set => SetValue(FontStyleProperty, value); + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FontWeightProperty = + DependencyProperty.Register( + nameof(FontWeight), + typeof(FontWeight), + typeof(FontIconSource), + new PropertyMetadata(FontWeights.Normal)); + + /// + /// Gets or sets the thickness of the icon glyph. + /// + /// + /// A value that specifies the thickness of the icon glyph. + /// The default is . + /// + public FontWeight FontWeight + { + get => (FontWeight)GetValue(FontWeightProperty); + set => SetValue(FontWeightProperty, value); + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty GlyphProperty = + DependencyProperty.Register( + nameof(Glyph), + typeof(string), + typeof(FontIconSource), + new PropertyMetadata(string.Empty)); + + /// + /// Gets or sets the character code that identifies the icon glyph. + /// + /// + /// The hexadecimal character code for the icon glyph. + /// + public string Glyph + { + get => (string)GetValue(GlyphProperty); + set => SetValue(GlyphProperty, value); + } + } +} diff --git a/ModernWpf/IconSource/IconSource.cs b/ModernWpf/IconSource/IconSource.cs new file mode 100644 index 00000000..47170504 --- /dev/null +++ b/ModernWpf/IconSource/IconSource.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; +using System.Windows.Media; + +namespace ModernWpf.Controls +{ + /// + /// Represents the base class for an icon source. + /// + public class IconSource : DependencyObject + { + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ForegroundProperty = + DependencyProperty.Register( + nameof(Foreground), + typeof(Brush), + typeof(IconSource)); + + /// + /// Gets or sets a brush that describes the foreground color. + /// + /// + /// The brush that paints the foreground of the control. The default is , (a null brush) which is + /// evaluated as Transparent for rendering. + /// + public Brush Foreground + { + get => (Brush)GetValue(ForegroundProperty); + set => SetValue(ForegroundProperty, value); + } + } +} diff --git a/ModernWpf/IconSource/PathIconSource.cs b/ModernWpf/IconSource/PathIconSource.cs new file mode 100644 index 00000000..17151a95 --- /dev/null +++ b/ModernWpf/IconSource/PathIconSource.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; +using System.Windows.Media; + +namespace ModernWpf.Controls +{ + /// + /// Represents an icon source that uses a vector path as its content. + /// + public class PathIconSource : IconSource + { + /// + /// Initializes a new instance of the class. + /// + public PathIconSource() + { + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty DataProperty = + DependencyProperty.Register( + nameof(Data), + typeof(Geometry), + typeof(PathIconSource)); + + /// + /// Gets or sets a . + /// + /// + /// A description of the shape to be drawn. + /// + public Geometry Data + { + get => (Geometry)GetValue(DataProperty); + set => SetValue(DataProperty, value); + } + } +} diff --git a/ModernWpf/IconSource/SymbolIconSource.cs b/ModernWpf/IconSource/SymbolIconSource.cs new file mode 100644 index 00000000..e15983c0 --- /dev/null +++ b/ModernWpf/IconSource/SymbolIconSource.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; + +namespace ModernWpf.Controls +{ + /// + /// Represents an icon source that uses a glyph from the Segoe MDL2 Assets font as its content. + /// + public class SymbolIconSource : IconSource + { + /// + /// Initializes a new instance of the class. + /// + public SymbolIconSource() + { + } + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty SymbolProperty = + DependencyProperty.Register( + nameof(Symbol), + typeof(Symbol), + typeof(SymbolIconSource), + new PropertyMetadata(Symbol.Emoji)); + + /// + /// Gets or sets the Segoe MDL2 Assets glyph used as the icon content. + /// + /// + /// A named constant of the enumeration that specifies the Segoe MDL2 Assets glyph to use. + /// + public Symbol Symbol + { + get => (Symbol)GetValue(SymbolProperty); + set => SetValue(SymbolProperty, value); + } + } +} From decf9bd470dd80a27af5ca454e4ebbbebefc6e65 Mon Sep 17 00:00:00 2001 From: Shankar Date: Fri, 6 Nov 2020 23:24:05 +0530 Subject: [PATCH 05/10] Ported theme resources of TeachingTip --- .../TeachingTip/TeachingTip.xaml | 48 +++++++++++++++ .../TeachingTip/TeachingTipAutomationPeer.cs | 58 +++++++++---------- ModernWpf/ThemeResources/Dark.xaml | 10 ++++ ModernWpf/ThemeResources/HighContrast.xaml | 10 ++++ ModernWpf/ThemeResources/Light.xaml | 10 ++++ 5 files changed, 107 insertions(+), 29 deletions(-) create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTip.xaml diff --git a/ModernWpf.Controls/TeachingTip/TeachingTip.xaml b/ModernWpf.Controls/TeachingTip/TeachingTip.xaml new file mode 100644 index 00000000..eb97a01c --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTip.xaml @@ -0,0 +1,48 @@ + + + + 40 + 520 + 320 + 336 + + 6,12,0,0 + 0,12,6,0 + + 0,12,0,0 + 0,0,0,0 + + 0,0,28,0 + 0,0,0,0 + + 0,0,12,0 + 0,0,0,0 + + 1,1,1,0 + 1,0,1,1 + 1,1,0,1 + 0,1,1,1 + 1,1,1,1 + + 0,-2,0,0 + 0,0,0,-2 + -2,0,0,0 + 0,0,-2,0 + + 8 + 10 + + 40 + 12 + + 12 + + 1 + 1 + 0,1,0,0 + + \ No newline at end of file diff --git a/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs b/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs index c830dfdc..d881cd2d 100644 --- a/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs +++ b/ModernWpf.Controls/TeachingTip/TeachingTipAutomationPeer.cs @@ -92,35 +92,35 @@ private bool WaitForInputIdle(int milliseconds) // Didn't implement these as AutomationEvents.WindowOpened & AutomationEvents.WindowClosed are not present in WPF - //internal void RaiseWindowClosedEvent() - //{ - // We only report as a window when light dismiss is enabled. - // if (GetTeachingTip().IsLightDismissEnabled && - // ListenerExists(AutomationEvents.WindowClosed)) - // { - // RaiseAutomationEvent(AutomationEvents.WindowClosed); - // } - //} - - //internal void RaiseWindowOpenedEvent(string displayString) - //{ - // AutomationPeer automationPeer7 = this; - // if (automationPeer7 != null) - // { - // //automationPeer7.RaiseNotificationEvent( - // // Automation.Peers.AutomationNotificationKind.Other, - // // Peers.AutomationNotificationProcessing.CurrentThenMostRecent, - // // displayString, - // // L"TeachingTipOpenedActivityId"); - // } - - // // We only report as a window when light dismiss is enabled. - // if (GetTeachingTip().IsLightDismissEnabled && - // AutomationPeer.ListenerExists(AutomationEvents.WindowOpened)) - // { - // RaiseAutomationEvent(AutomationEvents.WindowOpened); - // } - //} + internal void RaiseWindowClosedEvent() + { + //We only report as a window when light dismiss is enabled. + //if (GetTeachingTip().IsLightDismissEnabled && + // ListenerExists(AutomationEvents.WindowClosed)) + //{ + // RaiseAutomationEvent(AutomationEvents.WindowClosed); + //} + } + + internal void RaiseWindowOpenedEvent(string displayString) + { + //AutomationPeer automationPeer7 = this; + //if (automationPeer7 != null) + //{ + // //automationPeer7.RaiseNotificationEvent( + // // Automation.Peers.AutomationNotificationKind.Other, + // // Peers.AutomationNotificationProcessing.CurrentThenMostRecent, + // // displayString, + // // L"TeachingTipOpenedActivityId"); + //} + + //// We only report as a window when light dismiss is enabled. + //if (GetTeachingTip().IsLightDismissEnabled && + // AutomationPeer.ListenerExists(AutomationEvents.WindowOpened)) + //{ + // RaiseAutomationEvent(AutomationEvents.WindowOpened); + //} + } TeachingTip GetTeachingTip() { diff --git a/ModernWpf/ThemeResources/Dark.xaml b/ModernWpf/ThemeResources/Dark.xaml index 01a44e86..3a061066 100644 --- a/ModernWpf/ThemeResources/Dark.xaml +++ b/ModernWpf/ThemeResources/Dark.xaml @@ -1182,6 +1182,16 @@ + + + + + + + + + 0 + diff --git a/ModernWpf/ThemeResources/HighContrast.xaml b/ModernWpf/ThemeResources/HighContrast.xaml index da08ec64..7c7b735c 100644 --- a/ModernWpf/ThemeResources/HighContrast.xaml +++ b/ModernWpf/ThemeResources/HighContrast.xaml @@ -1184,6 +1184,16 @@ + + + + + + + + + 2 + diff --git a/ModernWpf/ThemeResources/Light.xaml b/ModernWpf/ThemeResources/Light.xaml index 9ea0b147..22964d60 100644 --- a/ModernWpf/ThemeResources/Light.xaml +++ b/ModernWpf/ThemeResources/Light.xaml @@ -1181,6 +1181,16 @@ + + + + + + + + + 0 + From 502cee4da7c4e3fb52d543dda4d2c0335c65fd6f Mon Sep 17 00:00:00 2001 From: Shankar Date: Thu, 12 Nov 2020 15:42:29 +0530 Subject: [PATCH 06/10] Added properties, DPs and events --- .../TeachingTip/TeachingTip.Properties.cs | 513 ++++ ModernWpf.Controls/TeachingTip/TeachingTip.cs | 2445 ++++++++++++++++- .../TeachingTip/TeachingTipAutomationPeer.cs | 44 +- 3 files changed, 2977 insertions(+), 25 deletions(-) create mode 100644 ModernWpf.Controls/TeachingTip/TeachingTip.Properties.cs diff --git a/ModernWpf.Controls/TeachingTip/TeachingTip.Properties.cs b/ModernWpf.Controls/TeachingTip/TeachingTip.Properties.cs new file mode 100644 index 00000000..7a326539 --- /dev/null +++ b/ModernWpf.Controls/TeachingTip/TeachingTip.Properties.cs @@ -0,0 +1,513 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; +using System.Windows.Input; +using ModernWpf.Controls.Primitives; + +namespace ModernWpf.Controls +{ + public partial class TeachingTip + { + #region ActionButtonCommand + + public static readonly DependencyProperty ActionButtonCommandProperty = + DependencyProperty.Register( + nameof(ActionButtonCommand), + typeof(ICommand), + typeof(TeachingTip), + new PropertyMetadata(OnActionButtonCommandPropertyChanged)); + + public ICommand ActionButtonCommand + { + get => (ICommand)GetValue(ActionButtonCommandProperty); + set => SetValue(ActionButtonCommandProperty, value); + } + + private static void OnActionButtonCommandPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region ActionButtonCommandParameter + + public static readonly DependencyProperty ActionButtonCommandParameterProperty = + DependencyProperty.Register( + nameof(ActionButtonCommandParameter), + typeof(object), + typeof(TeachingTip), + new PropertyMetadata(OnActionButtonCommandParameterPropertyChanged)); + + public object ActionButtonCommandParameter + { + get => (object)GetValue(ActionButtonCommandParameterProperty); + set => SetValue(ActionButtonCommandParameterProperty, value); + } + + private static void OnActionButtonCommandParameterPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region ActionButtonContent + + public static readonly DependencyProperty ActionButtonContentProperty = + DependencyProperty.Register( + nameof(ActionButtonContent), + typeof(object), + typeof(TeachingTip), + new PropertyMetadata(OnActionButtonContentPropertyChanged)); + + public object ActionButtonContent + { + get => (object)GetValue(ActionButtonContentProperty); + set => SetValue(ActionButtonContentProperty, value); + } + + private static void OnActionButtonContentPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region ActionButtonStyle + + public static readonly DependencyProperty ActionButtonStyleProperty = + DependencyProperty.Register( + nameof(ActionButtonStyle), + typeof(Style), + typeof(TeachingTip), + new PropertyMetadata(OnActionButtonStylePropertyChanged)); + + public Style ActionButtonStyle + { + get => (Style)GetValue(ActionButtonStyleProperty); + set => SetValue(ActionButtonStyleProperty, value); + } + + private static void OnActionButtonStylePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region CloseButtonCommand + + public static readonly DependencyProperty CloseButtonCommandProperty = + DependencyProperty.Register( + nameof(CloseButtonCommand), + typeof(ICommand), + typeof(TeachingTip), + new PropertyMetadata(OnCloseButtonCommandPropertyChanged)); + + public ICommand CloseButtonCommand + { + get => (ICommand)GetValue(CloseButtonCommandProperty); + set => SetValue(CloseButtonCommandProperty, value); + } + + private static void OnCloseButtonCommandPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region CloseButtonCommandParameter + + public static readonly DependencyProperty CloseButtonCommandParameterProperty = + DependencyProperty.Register( + nameof(CloseButtonCommandParameter), + typeof(object), + typeof(TeachingTip), + new PropertyMetadata(OnCloseButtonCommandParameterPropertyChanged)); + + public object CloseButtonCommandParameter + { + get => (object)GetValue(CloseButtonCommandParameterProperty); + set => SetValue(CloseButtonCommandParameterProperty, value); + } + + private static void OnCloseButtonCommandParameterPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region CloseButtonContent + + public static readonly DependencyProperty CloseButtonContentProperty = + DependencyProperty.Register( + nameof(CloseButtonContent), + typeof(object), + typeof(TeachingTip), + new PropertyMetadata(OnCloseButtonContentPropertyChanged)); + + public object CloseButtonContent + { + get => (object)GetValue(CloseButtonContentProperty); + set => SetValue(CloseButtonContentProperty, value); + } + + private static void OnCloseButtonContentPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region CloseButtonStyle + + public static readonly DependencyProperty CloseButtonStyleProperty = + DependencyProperty.Register( + nameof(CloseButtonStyle), + typeof(Style), + typeof(TeachingTip), + new PropertyMetadata(OnCloseButtonStylePropertyChanged)); + + public Style CloseButtonStyle + { + get => (Style)GetValue(CloseButtonStyleProperty); + set => SetValue(CloseButtonStyleProperty, value); + } + + private static void OnCloseButtonStylePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region HeroContent + + public static readonly DependencyProperty HeroContentProperty = + DependencyProperty.Register( + nameof(HeroContent), + typeof(UIElement), + typeof(TeachingTip), + new PropertyMetadata(OnHeroContentPropertyChanged)); + + public UIElement HeroContent + { + get => (UIElement)GetValue(HeroContentProperty); + set => SetValue(HeroContentProperty, value); + } + + private static void OnHeroContentPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region HeroContentPlacement + + public static readonly DependencyProperty HeroContentPlacementProperty = + DependencyProperty.Register( + nameof(HeroContentPlacement), + typeof(TeachingTipHeroContentPlacementMode), + typeof(TeachingTip), + new PropertyMetadata(TeachingTipHeroContentPlacementMode.Auto, OnHeroContentPlacementPropertyChanged)); + + public TeachingTipHeroContentPlacementMode HeroContentPlacement + { + get => (TeachingTipHeroContentPlacementMode)GetValue(HeroContentPlacementProperty); + set => SetValue(HeroContentPlacementProperty, value); + } + + private static void OnHeroContentPlacementPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region IconSource + + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register( + nameof(IconSource), + typeof(IconSource), + typeof(TeachingTip), + new PropertyMetadata(OnIconSourcePropertyChanged)); + + public IconSource IconSource + { + get => (IconSource)GetValue(IconSourceProperty); + set => SetValue(IconSourceProperty, value); + } + + private static void OnIconSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region IsLightDismissEnabled + + public static readonly DependencyProperty IsLightDismissEnabledProperty = + DependencyProperty.Register( + nameof(IsLightDismissEnabled), + typeof(bool), + typeof(TeachingTip), + new PropertyMetadata(false, OnIsLightDismissEnabledPropertyChanged)); + + public bool IsLightDismissEnabled + { + get => (bool)GetValue(IsLightDismissEnabledProperty); + set => SetValue(IsLightDismissEnabledProperty, value); + } + + private static void OnIsLightDismissEnabledPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region IsOpen + + public static readonly DependencyProperty IsOpenProperty = + DependencyProperty.Register( + nameof(IsOpen), + typeof(bool), + typeof(TeachingTip), + new PropertyMetadata(false, OnIsOpenPropertyChanged)); + + public bool IsOpen + { + get => (bool)GetValue(IsOpenProperty); + set => SetValue(IsOpenProperty, value); + } + + private static void OnIsOpenPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region PlacementMargin + + public static readonly DependencyProperty PlacementMarginProperty = + DependencyProperty.Register( + nameof(PlacementMargin), + typeof(Thickness), + typeof(TeachingTip), + new PropertyMetadata(default(Thickness), OnPlacementMarginPropertyChanged)); + + public Thickness PlacementMargin + { + get => (Thickness)GetValue(PlacementMarginProperty); + set => SetValue(PlacementMarginProperty, value); + } + + private static void OnPlacementMarginPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region PreferredPlacement + + public static readonly DependencyProperty PreferredPlacementProperty = + DependencyProperty.Register( + nameof(PreferredPlacement), + typeof(TeachingTipPlacementMode), + typeof(TeachingTip), + new PropertyMetadata(TeachingTipPlacementMode.Auto, OnPreferredPlacementPropertyChanged)); + + public TeachingTipPlacementMode PreferredPlacement + { + get => (TeachingTipPlacementMode)GetValue(PreferredPlacementProperty); + set => SetValue(PreferredPlacementProperty, value); + } + + private static void OnPreferredPlacementPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region ShouldConstrainToRootBounds + + public static readonly DependencyProperty ShouldConstrainToRootBoundsProperty = + DependencyProperty.Register( + nameof(ShouldConstrainToRootBounds), + typeof(bool), + typeof(TeachingTip), + new PropertyMetadata(true, OnShouldConstrainToRootBoundsPropertyChanged)); + + public bool ShouldConstrainToRootBounds + { + get => (bool)GetValue(ShouldConstrainToRootBoundsProperty); + set => SetValue(ShouldConstrainToRootBoundsProperty, value); + } + + private static void OnShouldConstrainToRootBoundsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region Subtitle + + public static readonly DependencyProperty SubtitleProperty = + DependencyProperty.Register( + nameof(Subtitle), + typeof(string), + typeof(TeachingTip), + new PropertyMetadata(OnSubtitlePropertyChanged)); + + public string Subtitle + { + get => (string)GetValue(SubtitleProperty); + set => SetValue(SubtitleProperty, value); + } + + private static void OnSubtitlePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region TailVisibility + + public static readonly DependencyProperty TailVisibilityProperty = + DependencyProperty.Register( + nameof(TailVisibility), + typeof(TeachingTipTailVisibility), + typeof(TeachingTip), + new PropertyMetadata(TeachingTipTailVisibility.Auto, OnTailVisibilityPropertyChanged)); + + public TeachingTipTailVisibility TailVisibility + { + get => (TeachingTipTailVisibility)GetValue(TailVisibilityProperty); + set => SetValue(TailVisibilityProperty, value); + } + + private static void OnTailVisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region Target + + public static readonly DependencyProperty TargetProperty = + DependencyProperty.Register( + nameof(Target), + typeof(FrameworkElement), + typeof(TeachingTip), + new PropertyMetadata(OnTargetPropertyChanged)); + + public FrameworkElement Target + { + get => (FrameworkElement)GetValue(TargetProperty); + set => SetValue(TargetProperty, value); + } + + private static void OnTargetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region TemplateSettings + + public static readonly DependencyProperty TemplateSettingsProperty = + DependencyProperty.Register( + nameof(TemplateSettings), + typeof(TeachingTipTemplateSettings), + typeof(TeachingTip), + new PropertyMetadata(OnTemplateSettingsPropertyChanged)); + + public TeachingTipTemplateSettings TemplateSettings + { + get => (TeachingTipTemplateSettings)GetValue(TemplateSettingsProperty); + set => SetValue(TemplateSettingsProperty, value); + } + + private static void OnTemplateSettingsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region Title + + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register( + nameof(Title), + typeof(string), + typeof(TeachingTip), + new PropertyMetadata(OnTitlePropertyChanged)); + + public string Title + { + get => (string)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + private static void OnTitlePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var owner = (TeachingTip)sender; + owner.OnPropertyChanged(args); + } + + #endregion + + #region CornerRadius + + public static readonly DependencyProperty CornerRadiusProperty = + ControlHelper.CornerRadiusProperty.AddOwner(typeof(TeachingTip)); + + public CornerRadius CornerRadius + { + get => (CornerRadius)GetValue(CornerRadiusProperty); + set => SetValue(CornerRadiusProperty, value); + } + + #endregion + + public event TypedEventHandler ActionButtonClick; + public event TypedEventHandler CloseButtonClick; + public event TypedEventHandler Closing; + public event TypedEventHandler Closed; + } +} diff --git a/ModernWpf.Controls/TeachingTip/TeachingTip.cs b/ModernWpf.Controls/TeachingTip/TeachingTip.cs index 6385f7c1..592ee84a 100644 --- a/ModernWpf.Controls/TeachingTip/TeachingTip.cs +++ b/ModernWpf.Controls/TeachingTip/TeachingTip.cs @@ -1,8 +1,2449 @@ -using System.Windows.Controls; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Windows; +using System.Windows.Controls; namespace ModernWpf.Controls { - public class TeachingTip : ContentControl + public partial class TeachingTip : ContentControl { + // TeachingTip() + //{ + // __RP_Marker_ClassById(RuntimeProfiler.ProfId_TeachingTip); + // SetDefaultStyleKey(this); + // EnsureProperties(); + // Unloaded({ this, &ClosePopupOnUnloadEvent }); + // m_automationNameChangedRevoker = RegisterPropertyChanged(this, AutomationProperties.NameProperty(), { this, &OnAutomationNameChanged }); + // m_automationIdChangedRevoker = RegisterPropertyChanged(this, AutomationProperties.AutomationIdProperty(), { this, &OnAutomationIdChanged }); + // SetValue(s_TemplateSettingsProperty, make<.TeachingTipTemplateSettings>()); + // } + + // AutomationPeer OnCreateAutomationPeer() + // { + // return make(this); + // } + + // void OnApplyTemplate() + // { + // m_acceleratorKeyActivatedRevoker.revoke(); + // m_effectiveViewportChangedRevoker.revoke(); + // m_contentSizeChangedRevoker.revoke(); + // m_closeButtonClickedRevoker.revoke(); + // m_alternateCloseButtonClickedRevoker.revoke(); + // m_actionButtonClickedRevoker.revoke(); + // m_windowSizeChangedRevoker.revoke(); + + // IControlProtected controlProtected{ this }; + + // m_container.set(GetTemplateChildT(s_containerName, controlProtected)); + // m_rootElement.set(m_container.get().Child()); + // m_tailOcclusionGrid.set(GetTemplateChildT(s_tailOcclusionGridName, controlProtected)); + // m_contentRootGrid.set(GetTemplateChildT(s_contentRootGridName, controlProtected)); + // m_nonHeroContentRootGrid.set(GetTemplateChildT(s_nonHeroContentRootGridName, controlProtected)); + // m_heroContentBorder.set(GetTemplateChildT(s_heroContentBorderName, controlProtected)); + // m_actionButton.set(GetTemplateChildT