From 0d9b13b0e225ac20f96a8ff1e1589f57586ab38b Mon Sep 17 00:00:00 2001 From: "Paul Campbell (CMD)" Date: Wed, 28 Aug 2019 15:34:02 -0700 Subject: [PATCH 01/16] [UWP] Clean up XamlBuilder --- .../uwp/Renderer/AdaptiveCardRenderer.vcxproj | 3 + .../AdaptiveCardRenderer.vcxproj.filters | 5 +- source/uwp/Renderer/lib/ActionHelpers.cpp | 595 +++ source/uwp/Renderer/lib/ActionHelpers.h | 39 + .../Renderer/lib/AdaptiveActionElement.cpp | 1 - .../uwp/Renderer/lib/AdaptiveActionElement.h | 4 - source/uwp/Renderer/lib/AdaptiveActionSet.cpp | 35 +- source/uwp/Renderer/lib/AdaptiveActionSet.h | 9 +- .../lib/AdaptiveActionSetRenderer.cpp | 47 +- .../Renderer/lib/AdaptiveActionSetRenderer.h | 7 +- .../Renderer/lib/AdaptiveActionsConfig.cpp | 1 - .../uwp/Renderer/lib/AdaptiveActionsConfig.h | 4 - .../Renderer/lib/AdaptiveBackgroundImage.h | 3 - source/uwp/Renderer/lib/AdaptiveCard.h | 1 - source/uwp/Renderer/lib/AdaptiveCardConfig.h | 4 - source/uwp/Renderer/lib/AdaptiveCardElement.h | 3 +- .../lib/AdaptiveCardRendererComponent.cpp | 55 +- source/uwp/Renderer/lib/AdaptiveChoiceInput.h | 2 - .../uwp/Renderer/lib/AdaptiveChoiceSetInput.h | 3 - .../lib/AdaptiveChoiceSetInputRenderer.cpp | 217 +- .../lib/AdaptiveChoiceSetInputRenderer.h | 12 +- source/uwp/Renderer/lib/AdaptiveColorConfig.h | 4 - .../uwp/Renderer/lib/AdaptiveColorsConfig.h | 4 - source/uwp/Renderer/lib/AdaptiveColumn.h | 4 - .../Renderer/lib/AdaptiveColumnRenderer.cpp | 113 +- .../uwp/Renderer/lib/AdaptiveColumnRenderer.h | 2 - source/uwp/Renderer/lib/AdaptiveColumnSet.h | 4 - .../lib/AdaptiveColumnSetRenderer.cpp | 205 +- .../Renderer/lib/AdaptiveColumnSetRenderer.h | 2 - source/uwp/Renderer/lib/AdaptiveContainer.h | 4 - .../lib/AdaptiveContainerRenderer.cpp | 118 +- .../Renderer/lib/AdaptiveContainerRenderer.h | 2 - .../lib/AdaptiveContainerStyleDefinition.h | 4 - .../lib/AdaptiveContainerStylesDefinition.h | 4 - source/uwp/Renderer/lib/AdaptiveDateInput.h | 2 - .../lib/AdaptiveDateInputRenderer.cpp | 97 +- .../Renderer/lib/AdaptiveDateInputRenderer.h | 2 - source/uwp/Renderer/lib/AdaptiveFact.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveFact.h | 2 - source/uwp/Renderer/lib/AdaptiveFactSet.h | 4 - .../Renderer/lib/AdaptiveFactSetConfig.cpp | 1 + .../uwp/Renderer/lib/AdaptiveFactSetConfig.h | 4 - .../Renderer/lib/AdaptiveFactSetRenderer.cpp | 139 +- .../Renderer/lib/AdaptiveFactSetRenderer.h | 2 - .../Renderer/lib/AdaptiveFontSizesConfig.cpp | 1 + .../Renderer/lib/AdaptiveFontSizesConfig.h | 4 - .../lib/AdaptiveFontTypeDefinition.cpp | 1 + .../Renderer/lib/AdaptiveFontTypeDefinition.h | 4 - .../lib/AdaptiveFontTypesDefinition.cpp | 1 + .../lib/AdaptiveFontTypesDefinition.h | 4 - .../lib/AdaptiveFontWeightsConfig.cpp | 1 + .../Renderer/lib/AdaptiveFontWeightsConfig.h | 4 - .../lib/AdaptiveHighlightColorConfig.cpp | 2 +- .../lib/AdaptiveHighlightColorConfig.h | 4 - .../uwp/Renderer/lib/AdaptiveHostConfig.cpp | 8 +- source/uwp/Renderer/lib/AdaptiveHostConfig.h | 4 - source/uwp/Renderer/lib/AdaptiveImage.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveImage.h | 4 - .../uwp/Renderer/lib/AdaptiveImageConfig.cpp | 1 + source/uwp/Renderer/lib/AdaptiveImageConfig.h | 4 - .../Renderer/lib/AdaptiveImageRenderer.cpp | 714 ++- .../uwp/Renderer/lib/AdaptiveImageRenderer.h | 3 - source/uwp/Renderer/lib/AdaptiveImageSet.cpp | 5 +- source/uwp/Renderer/lib/AdaptiveImageSet.h | 4 - .../Renderer/lib/AdaptiveImageSetConfig.cpp | 1 + .../uwp/Renderer/lib/AdaptiveImageSetConfig.h | 4 - .../Renderer/lib/AdaptiveImageSetRenderer.cpp | 91 +- .../Renderer/lib/AdaptiveImageSetRenderer.h | 2 - .../Renderer/lib/AdaptiveImageSizesConfig.cpp | 1 + .../Renderer/lib/AdaptiveImageSizesConfig.h | 4 - .../uwp/Renderer/lib/AdaptiveInputElement.cpp | 1 + .../uwp/Renderer/lib/AdaptiveInputElement.h | 3 - .../uwp/Renderer/lib/AdaptiveMediaConfig.cpp | 2 +- source/uwp/Renderer/lib/AdaptiveMediaConfig.h | 4 - .../Renderer/lib/AdaptiveMediaRenderer.cpp | 149 +- .../uwp/Renderer/lib/AdaptiveNumberInput.cpp | 4 +- source/uwp/Renderer/lib/AdaptiveNumberInput.h | 2 - .../lib/AdaptiveNumberInputRenderer.cpp | 67 +- .../lib/AdaptiveNumberInputRenderer.h | 4 - .../Renderer/lib/AdaptiveOpenUrlAction.cpp | 2 +- .../uwp/Renderer/lib/AdaptiveOpenUrlAction.h | 2 - .../lib/AdaptiveOpenUrlActionRenderer.cpp | 4 +- .../lib/AdaptiveRemoteResourceInformation.cpp | 2 +- .../lib/AdaptiveRemoteResourceInformation.h | 3 - .../Renderer/lib/AdaptiveRichTextBlock.cpp | 4 +- .../uwp/Renderer/lib/AdaptiveRichTextBlock.h | 3 - .../lib/AdaptiveRichTextBlockRenderer.cpp | 144 +- .../lib/AdaptiveRichTextBlockRenderer.h | 2 - source/uwp/Renderer/lib/AdaptiveSeparator.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveSeparator.h | 2 - .../Renderer/lib/AdaptiveSeparatorConfig.cpp | 1 + .../Renderer/lib/AdaptiveSeparatorConfig.h | 4 - .../Renderer/lib/AdaptiveShowCardAction.cpp | 2 +- .../uwp/Renderer/lib/AdaptiveShowCardAction.h | 2 - .../lib/AdaptiveShowCardActionConfig.cpp | 2 +- .../lib/AdaptiveShowCardActionConfig.h | 4 - .../lib/AdaptiveShowCardActionRenderer.cpp | 75 +- .../lib/AdaptiveShowCardActionRenderer.h | 6 + .../Renderer/lib/AdaptiveSpacingConfig.cpp | 1 + .../uwp/Renderer/lib/AdaptiveSpacingConfig.h | 4 - .../uwp/Renderer/lib/AdaptiveSubmitAction.cpp | 2 +- .../uwp/Renderer/lib/AdaptiveSubmitAction.h | 2 - .../lib/AdaptiveSubmitActionRenderer.cpp | 5 +- source/uwp/Renderer/lib/AdaptiveTextBlock.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveTextBlock.h | 3 - .../lib/AdaptiveTextBlockRenderer.cpp | 40 +- .../Renderer/lib/AdaptiveTextBlockRenderer.h | 4 - .../uwp/Renderer/lib/AdaptiveTextConfig.cpp | 2 +- source/uwp/Renderer/lib/AdaptiveTextConfig.h | 4 - .../uwp/Renderer/lib/AdaptiveTextElement.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveTextElement.h | 3 - source/uwp/Renderer/lib/AdaptiveTextInput.cpp | 4 +- source/uwp/Renderer/lib/AdaptiveTextInput.h | 2 - .../lib/AdaptiveTextInputRenderer.cpp | 111 +- .../Renderer/lib/AdaptiveTextInputRenderer.h | 2 - source/uwp/Renderer/lib/AdaptiveTextRun.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveTextRun.h | 2 - source/uwp/Renderer/lib/AdaptiveTimeInput.cpp | 4 +- source/uwp/Renderer/lib/AdaptiveTimeInput.h | 2 - .../lib/AdaptiveTimeInputRenderer.cpp | 56 +- .../Renderer/lib/AdaptiveTimeInputRenderer.h | 2 - .../uwp/Renderer/lib/AdaptiveToggleInput.cpp | 4 +- source/uwp/Renderer/lib/AdaptiveToggleInput.h | 2 - .../lib/AdaptiveToggleInputRenderer.cpp | 63 +- .../lib/AdaptiveToggleInputRenderer.h | 2 - .../lib/AdaptiveToggleVisibilityAction.cpp | 3 +- .../lib/AdaptiveToggleVisibilityAction.h | 2 - ...AdaptiveToggleVisibilityActionRenderer.cpp | 5 +- .../lib/AdaptiveToggleVisibilityTarget.cpp | 3 +- .../lib/AdaptiveToggleVisibilityTarget.h | 2 - .../lib/AdaptiveUnsupportedAction.cpp | 1 - .../Renderer/lib/AdaptiveUnsupportedAction.h | 2 - .../lib/AdaptiveUnsupportedElement.cpp | 3 - .../Renderer/lib/AdaptiveUnsupportedElement.h | 3 - source/uwp/Renderer/lib/AsyncOperations.h | 2 +- .../uwp/Renderer/lib/RenderedAdaptiveCard.cpp | 114 +- source/uwp/Renderer/lib/TileControl.cpp | 6 - source/uwp/Renderer/lib/TileControl.h | 3 - source/uwp/Renderer/lib/Util.cpp | 6 +- source/uwp/Renderer/lib/XamlBuilder.cpp | 4381 +---------------- source/uwp/Renderer/lib/XamlBuilder.h | 244 +- source/uwp/Renderer/lib/XamlHelpers.cpp | 1059 ++++ source/uwp/Renderer/lib/XamlHelpers.h | 200 +- source/uwp/Renderer/lib/pch.h | 18 +- 144 files changed, 4624 insertions(+), 4926 deletions(-) create mode 100644 source/uwp/Renderer/lib/ActionHelpers.cpp create mode 100644 source/uwp/Renderer/lib/ActionHelpers.h create mode 100644 source/uwp/Renderer/lib/XamlHelpers.cpp diff --git a/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj b/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj index 361c13fcf9..d42e31cf2e 100644 --- a/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj +++ b/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj @@ -126,9 +126,12 @@ + + + diff --git a/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj.filters b/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj.filters index 8ceff937a5..29c109ca98 100644 --- a/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj.filters +++ b/source/uwp/Renderer/AdaptiveCardRenderer.vcxproj.filters @@ -112,6 +112,8 @@ + + @@ -231,8 +233,9 @@ + - \ No newline at end of file + diff --git a/source/uwp/Renderer/lib/ActionHelpers.cpp b/source/uwp/Renderer/lib/ActionHelpers.cpp new file mode 100644 index 0000000000..01279bcbd0 --- /dev/null +++ b/source/uwp/Renderer/lib/ActionHelpers.cpp @@ -0,0 +1,595 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "pch.h" + +#include "ActionHelpers.h" +#include "AdaptiveImage.h" +#include "AdaptiveRenderArgs.h" + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::AdaptiveNamespace; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; +using namespace ABI::Windows::UI::Xaml::Input; +using namespace ABI::Windows::UI::Xaml::Media; + +namespace AdaptiveNamespace::ActionHelpers +{ + HRESULT GetButtonMargin(_In_ IAdaptiveActionsConfig* actionsConfig, Thickness& buttonMargin) noexcept + { + buttonMargin = {0, 0, 0, 0}; + UINT32 buttonSpacing; + RETURN_IF_FAILED(actionsConfig->get_ButtonSpacing(&buttonSpacing)); + + ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; + RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); + + if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + buttonMargin.Left = buttonMargin.Right = buttonSpacing / 2; + } + else + { + buttonMargin.Top = buttonMargin.Bottom = buttonSpacing / 2; + } + + return S_OK; + } + + void ArrangeButtonContent(_In_ IAdaptiveActionElement* action, + _In_ IAdaptiveActionsConfig* actionsConfig, + _In_ IAdaptiveRenderContext* renderContext, + ABI::AdaptiveNamespace::ContainerStyle containerStyle, + _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, + bool allActionsHaveIcons, + _In_ IButton* button) + { + HString title; + THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); + + HSTRING iconUrl; + THROW_IF_FAILED(action->get_IconUrl(&iconUrl)); + + ComPtr localButton(button); + + // Check if the button has an iconUrl + if (iconUrl != nullptr) + { + // Get icon configs + ABI::AdaptiveNamespace::IconPlacement iconPlacement; + UINT32 iconSize; + + THROW_IF_FAILED(actionsConfig->get_IconPlacement(&iconPlacement)); + THROW_IF_FAILED(actionsConfig->get_IconSize(&iconSize)); + + // Define the alignment for the button contents + ComPtr buttonContentsStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + + // Create image and add it to the button + ComPtr adaptiveImage; + THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); + + adaptiveImage->put_Url(iconUrl); + adaptiveImage->put_HorizontalAlignment(ABI::AdaptiveNamespace::HAlignment::Center); + + ComPtr adaptiveCardElement; + THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); + ComPtr childRenderArgs; + THROW_IF_FAILED( + MakeAndInitialize(&childRenderArgs, containerStyle, buttonContentsStackPanel.Get(), nullptr)); + + ComPtr elementRenderers; + THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + + ComPtr buttonIcon; + ComPtr elementRenderer; + THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &elementRenderer)); + if (elementRenderer != nullptr) + { + elementRenderer->Render(adaptiveCardElement.Get(), renderContext, childRenderArgs.Get(), &buttonIcon); + if (buttonIcon == nullptr) + { + XamlHelpers::SetContent(localButton.Get(), title.Get()); + return; + } + } + + // Create title text block + ComPtr buttonText = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); + THROW_IF_FAILED(buttonText->put_Text(title.Get())); + THROW_IF_FAILED(buttonText->put_TextAlignment(TextAlignment::TextAlignment_Center)); + + // Handle different arrangements inside button + ComPtr buttonIconAsFrameworkElement; + THROW_IF_FAILED(buttonIcon.As(&buttonIconAsFrameworkElement)); + ComPtr separator; + if (iconPlacement == ABI::AdaptiveNamespace::IconPlacement::AboveTitle && allActionsHaveIcons) + { + THROW_IF_FAILED(buttonContentsStackPanel->put_Orientation(Orientation::Orientation_Vertical)); + + // Set icon height to iconSize (aspect ratio is automatically maintained) + THROW_IF_FAILED(buttonIconAsFrameworkElement->put_Height(iconSize)); + } + else + { + THROW_IF_FAILED(buttonContentsStackPanel->put_Orientation(Orientation::Orientation_Horizontal)); + + // Add event to the image to resize itself when the textblock is rendered + ComPtr buttonIconAsImage; + THROW_IF_FAILED(buttonIcon.As(&buttonIconAsImage)); + + EventRegistrationToken eventToken; + THROW_IF_FAILED(buttonIconAsImage->add_ImageOpened( + Callback([buttonIconAsFrameworkElement, + buttonText](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { + ComPtr buttonTextAsFrameworkElement; + RETURN_IF_FAILED(buttonText.As(&buttonTextAsFrameworkElement)); + + return SetMatchingHeight(buttonIconAsFrameworkElement.Get(), buttonTextAsFrameworkElement.Get()); + }).Get(), + &eventToken)); + + // Only add spacing when the icon must be located at the left of the title + UINT spacingSize; + THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig, ABI::AdaptiveNamespace::Spacing::Default, &spacingSize)); + + ABI::Windows::UI::Color color = {0}; + separator = XamlHelpers::CreateSeparator(renderContext, spacingSize, spacingSize, color, false); + } + + ComPtr buttonContentsPanel; + THROW_IF_FAILED(buttonContentsStackPanel.As(&buttonContentsPanel)); + + // Add image to stack panel + XamlHelpers::AppendXamlElementToPanel(buttonIcon.Get(), buttonContentsPanel.Get()); + + // Add separator to stack panel + if (separator != nullptr) + { + XamlHelpers::AppendXamlElementToPanel(separator.Get(), buttonContentsPanel.Get()); + } + + // Add text to stack panel + XamlHelpers::AppendXamlElementToPanel(buttonText.Get(), buttonContentsPanel.Get()); + + // Finally, put the stack panel inside the final button + ComPtr buttonContentControl; + THROW_IF_FAILED(localButton.As(&buttonContentControl)); + THROW_IF_FAILED(buttonContentControl->put_Content(buttonContentsPanel.Get())); + } + else + { + XamlHelpers::SetContent(localButton.Get(), title.Get()); + } + } + + HRESULT HandleActionStyling(_In_ IAdaptiveActionElement* adaptiveActionElement, + _In_ IFrameworkElement* buttonFrameworkElement, + _In_ IAdaptiveRenderContext* renderContext) + { + HString actionSentiment; + RETURN_IF_FAILED(adaptiveActionElement->get_Style(actionSentiment.GetAddressOf())); + + INT32 isSentimentPositive{}, isSentimentDestructive{}, isSentimentDefault{}; + + ComPtr resourceDictionary; + RETURN_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); + ComPtr styleToApply; + + ComPtr contextImpl = + PeekInnards(renderContext); + + if ((SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"default").Get(), &isSentimentDefault)) && + (isSentimentDefault == 0)) || + WindowsIsStringEmpty(actionSentiment.Get())) + { + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Action", buttonFrameworkElement)); + } + else if (SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"positive").Get(), &isSentimentPositive)) && + (isSentimentPositive == 0)) + { + if (SUCCEEDED(XamlHelpers::TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), + L"Adaptive.Action.Positive", + &styleToApply))) + { + RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); + } + else + { + // By default, set the action background color to accent color + ComPtr actionSentimentDictionary = contextImpl->GetDefaultActionSentimentDictionary(); + + if (SUCCEEDED(XamlHelpers::TryGetResourceFromResourceDictionaries(actionSentimentDictionary.Get(), + L"PositiveActionDefaultStyle", + styleToApply.GetAddressOf()))) + { + RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); + } + } + } + else if (SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"destructive").Get(), &isSentimentDestructive)) && + (isSentimentDestructive == 0)) + { + if (SUCCEEDED(XamlHelpers::TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), + L"Adaptive.Action.Destructive", + &styleToApply))) + { + RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); + } + else + { + // By default, set the action text color to attention color + ComPtr actionSentimentDictionary = contextImpl->GetDefaultActionSentimentDictionary(); + + if (SUCCEEDED(XamlHelpers::TryGetResourceFromResourceDictionaries(actionSentimentDictionary.Get(), + L"DestructiveActionDefaultStyle", + styleToApply.GetAddressOf()))) + { + RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); + } + } + } + else + { + HString actionSentimentStyle; + RETURN_IF_FAILED(WindowsConcatString(HStringReference(L"Adaptive.Action.").Get(), + actionSentiment.Get(), + actionSentimentStyle.GetAddressOf())); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary( + renderContext, StringToWstring(HStringToUTF8(actionSentimentStyle.Get())), buttonFrameworkElement)); + } + return S_OK; + } + + HRESULT SetMatchingHeight(_In_ IFrameworkElement* elementToChange, _In_ IFrameworkElement* elementToMatch) + { + DOUBLE actualHeight; + RETURN_IF_FAILED(elementToMatch->get_ActualHeight(&actualHeight)); + + ComPtr localElement(elementToChange); + RETURN_IF_FAILED(localElement->put_Height(actualHeight)); + + ComPtr frameworkElementAsUIElement; + RETURN_IF_FAILED(localElement.As(&frameworkElementAsUIElement)); + RETURN_IF_FAILED(frameworkElementAsUIElement->put_Visibility(Visibility::Visibility_Visible)); + return S_OK; + } + + HRESULT BuildAction(_In_ IAdaptiveActionElement* adaptiveActionElement, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _Outptr_ IUIElement** actionControl) + { + // Render a button for the action + ComPtr action(adaptiveActionElement); + ComPtr button = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); + + ComPtr buttonFrameworkElement; + RETURN_IF_FAILED(button.As(&buttonFrameworkElement)); + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); + + Thickness buttonMargin; + RETURN_IF_FAILED(GetButtonMargin(actionsConfig.Get(), buttonMargin)); + RETURN_IF_FAILED(buttonFrameworkElement->put_Margin(buttonMargin)); + + ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; + RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); + + ABI::AdaptiveNamespace::ActionAlignment actionAlignment; + RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); + + if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + // For horizontal alignment, we always use stretch + RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment( + ABI::Windows::UI::Xaml::HorizontalAlignment::HorizontalAlignment_Stretch)); + } + else + { + switch (actionAlignment) + { + case ABI::AdaptiveNamespace::ActionAlignment::Center: + RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Left: + RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Right: + RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Stretch: + RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); + break; + } + } + + ABI::AdaptiveNamespace::ContainerStyle containerStyle; + renderArgs->get_ContainerStyle(&containerStyle); + + boolean allowAboveTitleIconPlacement; + RETURN_IF_FAILED(renderArgs->get_AllowAboveTitleIconPlacement(&allowAboveTitleIconPlacement)); + + ArrangeButtonContent(action.Get(), + actionsConfig.Get(), + renderContext, + containerStyle, + hostConfig.Get(), + allowAboveTitleIconPlacement, + button.Get()); + + ABI::AdaptiveNamespace::ActionType actionType; + RETURN_IF_FAILED(action->get_ActionType(&actionType)); + + ComPtr showCardActionConfig; + RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); + ABI::AdaptiveNamespace::ActionMode showCardActionMode; + RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); + std::shared_ptr>> allShowCards = std::make_shared>>(); + + // Add click handler which calls IAdaptiveActionInvoker::SendActionEvent + ComPtr buttonBase; + RETURN_IF_FAILED(button.As(&buttonBase)); + + ComPtr actionInvoker; + RETURN_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); + EventRegistrationToken clickToken; + RETURN_IF_FAILED(buttonBase->add_Click(Callback([action, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + return actionInvoker->SendActionEvent(action.Get()); + }).Get(), + &clickToken)); + + RETURN_IF_FAILED(HandleActionStyling(adaptiveActionElement, buttonFrameworkElement.Get(), renderContext)); + + ComPtr buttonAsUIElement; + RETURN_IF_FAILED(button.As(&buttonAsUIElement)); + *actionControl = buttonAsUIElement.Detach(); + return S_OK; + } + + bool WarnForInlineShowCard(_In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveActionElement* action, const std::wstring& warning) + { + if (action != nullptr) + { + ABI::AdaptiveNamespace::ActionType actionType; + THROW_IF_FAILED(action->get_ActionType(&actionType)); + + if (actionType == ABI::AdaptiveNamespace::ActionType::ShowCard) + { + THROW_IF_FAILED(renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::UnsupportedValue, + HStringReference(warning.c_str()).Get())); + return true; + } + } + + return false; + } + + static HRESULT HandleKeydownForInlineAction(_In_ IKeyRoutedEventArgs* args, + _In_ IAdaptiveActionInvoker* actionInvoker, + _In_ IAdaptiveActionElement* inlineAction) + { + ABI::Windows::System::VirtualKey key; + RETURN_IF_FAILED(args->get_Key(&key)); + + if (key == ABI::Windows::System::VirtualKey::VirtualKey_Enter) + { + ComPtr coreWindowStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Core_CoreWindow).Get(), &coreWindowStatics)); + + ComPtr coreWindow; + RETURN_IF_FAILED(coreWindowStatics->GetForCurrentThread(&coreWindow)); + + ABI::Windows::UI::Core::CoreVirtualKeyStates shiftKeyState; + RETURN_IF_FAILED(coreWindow->GetKeyState(ABI::Windows::System::VirtualKey_Shift, &shiftKeyState)); + + ABI::Windows::UI::Core::CoreVirtualKeyStates ctrlKeyState; + RETURN_IF_FAILED(coreWindow->GetKeyState(ABI::Windows::System::VirtualKey_Control, &ctrlKeyState)); + + if (shiftKeyState == ABI::Windows::UI::Core::CoreVirtualKeyStates_None && + ctrlKeyState == ABI::Windows::UI::Core::CoreVirtualKeyStates_None) + { + RETURN_IF_FAILED(actionInvoker->SendActionEvent(inlineAction)); + RETURN_IF_FAILED(args->put_Handled(true)); + } + } + + return S_OK; + } + + void HandleInlineAction(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _In_ ITextBox* textBox, + _In_ IAdaptiveActionElement* inlineAction, + _COM_Outptr_ IUIElement** textBoxWithInlineAction) + { + ComPtr localTextBox(textBox); + ComPtr localInlineAction(inlineAction); + + ABI::AdaptiveNamespace::ActionType actionType; + THROW_IF_FAILED(localInlineAction->get_ActionType(&actionType)); + + ComPtr hostConfig; + THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + // Inline ShowCards are not supported for inline actions + if (WarnForInlineShowCard(renderContext, localInlineAction.Get(), L"Inline ShowCard not supported for InlineAction")) + { + THROW_IF_FAILED(localTextBox.CopyTo(textBoxWithInlineAction)); + return; + } + + // Create a grid to hold the text box and the action button + ComPtr gridStatics; + THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); + + ComPtr xamlGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr> columnDefinitions; + THROW_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); + ComPtr gridAsPanel; + THROW_IF_FAILED(xamlGrid.As(&gridAsPanel)); + + // Create the first column and add the text box to it + ComPtr textBoxColumnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + THROW_IF_FAILED(textBoxColumnDefinition->put_Width({1, GridUnitType::GridUnitType_Star})); + THROW_IF_FAILED(columnDefinitions->Append(textBoxColumnDefinition.Get())); + + ComPtr textBoxAsFrameworkElement; + THROW_IF_FAILED(localTextBox.As(&textBoxAsFrameworkElement)); + + THROW_IF_FAILED(gridStatics->SetColumn(textBoxAsFrameworkElement.Get(), 0)); + XamlHelpers::AppendXamlElementToPanel(textBox, gridAsPanel.Get()); + + // Create a separator column + ComPtr separatorColumnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + THROW_IF_FAILED(separatorColumnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Auto})); + THROW_IF_FAILED(columnDefinitions->Append(separatorColumnDefinition.Get())); + + UINT spacingSize; + THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), ABI::AdaptiveNamespace::Spacing::Default, &spacingSize)); + + auto separator = XamlHelpers::CreateSeparator(renderContext, spacingSize, 0, {0}, false); + + ComPtr separatorAsFrameworkElement; + THROW_IF_FAILED(separator.As(&separatorAsFrameworkElement)); + + THROW_IF_FAILED(gridStatics->SetColumn(separatorAsFrameworkElement.Get(), 1)); + XamlHelpers::AppendXamlElementToPanel(separator.Get(), gridAsPanel.Get()); + + // Create a column for the button + ComPtr inlineActionColumnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + THROW_IF_FAILED(inlineActionColumnDefinition->put_Width({0, GridUnitType::GridUnitType_Auto})); + THROW_IF_FAILED(columnDefinitions->Append(inlineActionColumnDefinition.Get())); + + // Create a text box with the action title. This will be the tool tip if there's an icon + // or the content of the button otherwise + ComPtr titleTextBlock = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); + HString title; + THROW_IF_FAILED(localInlineAction->get_Title(title.GetAddressOf())); + THROW_IF_FAILED(titleTextBlock->put_Text(title.Get())); + + HString iconUrl; + THROW_IF_FAILED(localInlineAction->get_IconUrl(iconUrl.GetAddressOf())); + ComPtr actionUIElement; + if (iconUrl != nullptr) + { + // Render the icon using the adaptive image renderer + ComPtr elementRenderers; + THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + ComPtr imageRenderer; + THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &imageRenderer)); + + ComPtr adaptiveImage; + THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); + + THROW_IF_FAILED(adaptiveImage->put_Url(iconUrl.Get())); + + ComPtr adaptiveImageAsElement; + THROW_IF_FAILED(adaptiveImage.As(&adaptiveImageAsElement)); + + THROW_IF_FAILED(imageRenderer->Render(adaptiveImageAsElement.Get(), renderContext, renderArgs, &actionUIElement)); + + // Add the tool tip + ComPtr toolTip = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ToolTip)); + ComPtr toolTipAsContentControl; + THROW_IF_FAILED(toolTip.As(&toolTipAsContentControl)); + THROW_IF_FAILED(toolTipAsContentControl->put_Content(titleTextBlock.Get())); + + ComPtr toolTipService; + THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ToolTipService).Get(), + &toolTipService)); + + ComPtr actionAsDependencyObject; + THROW_IF_FAILED(actionUIElement.As(&actionAsDependencyObject)); + + THROW_IF_FAILED(toolTipService->SetToolTip(actionAsDependencyObject.Get(), toolTip.Get())); + } + else + { + // If there's no icon, just use the title text. Put it centered in a grid so it is + // centered relative to the text box. + ComPtr textBlockAsFrameworkElement; + THROW_IF_FAILED(titleTextBlock.As(&textBlockAsFrameworkElement)); + THROW_IF_FAILED(textBlockAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Center)); + + ComPtr titleGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr panel; + THROW_IF_FAILED(titleGrid.As(&panel)); + XamlHelpers::AppendXamlElementToPanel(titleTextBlock.Get(), panel.Get()); + + THROW_IF_FAILED(panel.As(&actionUIElement)); + } + + // Make the action the same size as the text box + EventRegistrationToken eventToken; + THROW_IF_FAILED(textBoxAsFrameworkElement->add_Loaded( + Callback([actionUIElement, textBoxAsFrameworkElement](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + ComPtr actionFrameworkElement; + RETURN_IF_FAILED(actionUIElement.As(&actionFrameworkElement)); + + return ActionHelpers::SetMatchingHeight(actionFrameworkElement.Get(), textBoxAsFrameworkElement.Get()); + }).Get(), + &eventToken)); + + // Wrap the action in a button + ComPtr touchTargetUIElement; + XamlHelpers::WrapInTouchTarget(nullptr, + actionUIElement.Get(), + localInlineAction.Get(), + renderContext, + false, + L"Adaptive.Input.Text.InlineAction", + &touchTargetUIElement); + + ComPtr touchTargetFrameworkElement; + THROW_IF_FAILED(touchTargetUIElement.As(&touchTargetFrameworkElement)); + + // Align to bottom so the icon stays with the bottom of the text box as it grows in the multiline case + THROW_IF_FAILED(touchTargetFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Bottom)); + + // Add the action to the column + THROW_IF_FAILED(gridStatics->SetColumn(touchTargetFrameworkElement.Get(), 2)); + XamlHelpers::AppendXamlElementToPanel(touchTargetFrameworkElement.Get(), gridAsPanel.Get()); + + // If this isn't a multiline input, enter should invoke the action + ComPtr actionInvoker; + THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); + + boolean isMultiLine; + THROW_IF_FAILED(textBox->get_AcceptsReturn(&isMultiLine)); + + if (!isMultiLine) + { + ComPtr textBoxAsUIElement; + THROW_IF_FAILED(localTextBox.As(&textBoxAsUIElement)); + + EventRegistrationToken keyDownEventToken; + THROW_IF_FAILED(textBoxAsUIElement->add_KeyDown( + Callback([actionInvoker, localInlineAction](IInspectable* /*sender*/, IKeyRoutedEventArgs* args) -> HRESULT { + return HandleKeydownForInlineAction(args, actionInvoker.Get(), localInlineAction.Get()); + }).Get(), + &keyDownEventToken)); + } + + THROW_IF_FAILED(xamlGrid.CopyTo(textBoxWithInlineAction)); + } +} diff --git a/source/uwp/Renderer/lib/ActionHelpers.h b/source/uwp/Renderer/lib/ActionHelpers.h new file mode 100644 index 0000000000..e428535171 --- /dev/null +++ b/source/uwp/Renderer/lib/ActionHelpers.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#pragma once + +namespace AdaptiveNamespace::ActionHelpers +{ + HRESULT BuildAction(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* adaptiveActionElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionControl); + + HRESULT GetButtonMargin(_In_ ABI::AdaptiveNamespace::IAdaptiveActionsConfig* actionsConfig, + ABI::Windows::UI::Xaml::Thickness& buttonMargin) noexcept; + + void ArrangeButtonContent(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionsConfig* actionsConfig, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + ABI::AdaptiveNamespace::ContainerStyle containerStyle, + _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, + bool allActionsHaveIcons, + _In_ ABI::Windows::UI::Xaml::Controls::IButton* button); + + HRESULT SetMatchingHeight(_In_ ABI::Windows::UI::Xaml::IFrameworkElement* elementToChange, + _In_ ABI::Windows::UI::Xaml::IFrameworkElement* elementToMatch); + + HRESULT HandleActionStyling(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* adaptiveActionElement, + _In_ ABI::Windows::UI::Xaml::IFrameworkElement* buttonFrameworkElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); + + bool WarnForInlineShowCard(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + const std::wstring& warning); + + void HandleInlineAction(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _In_ ABI::Windows::UI::Xaml::Controls::ITextBox* textBox, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* inlineAction, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textBoxWithInlineAction); +} diff --git a/source/uwp/Renderer/lib/AdaptiveActionElement.cpp b/source/uwp/Renderer/lib/AdaptiveActionElement.cpp index 311ad7801c..bb4a2cb7dc 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionElement.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT License. #include "pch.h" #include "AdaptiveActionElement.h" -#include "Util.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveActionElement.h b/source/uwp/Renderer/lib/AdaptiveActionElement.h index a488e72628..2dcbf08e0c 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionElement.h +++ b/source/uwp/Renderer/lib/AdaptiveActionElement.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include -#include "Enums.h" - namespace AdaptiveNamespace { class DECLSPEC_UUID("CDCCC115-7C53-4A04-9F5B-754BBC00C80E") AdaptiveActionElementBase : public IUnknown diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp index 291c330f97..4af193c90c 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp @@ -3,10 +3,6 @@ #include "pch.h" #include "AdaptiveActionSet.h" -#include "Util.h" -#include "Vector.h" -#include - using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; @@ -14,21 +10,19 @@ using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::UI::Xaml; using namespace ABI::Windows::UI::Xaml::Controls; -namespace AdaptiveCards { namespace Rendering { namespace Uwp +namespace AdaptiveNamespace { - AdaptiveActionSet::AdaptiveActionSet() - { - m_actions = Microsoft::WRL::Make>(); - } + AdaptiveActionSet::AdaptiveActionSet() { m_actions = Microsoft::WRL::Make>(); } HRESULT AdaptiveActionSet::RuntimeClassInitialize() noexcept try { std::shared_ptr ActionSet = std::make_shared(); return RuntimeClassInitialize(ActionSet); - } CATCH_RETURN; + } + CATCH_RETURN; - _Use_decl_annotations_ - HRESULT AdaptiveActionSet::RuntimeClassInitialize(const std::shared_ptr& sharedActionSet) try + _Use_decl_annotations_ HRESULT AdaptiveActionSet::RuntimeClassInitialize(const std::shared_ptr& sharedActionSet) + try { if (sharedActionSet == nullptr) { @@ -38,22 +32,22 @@ namespace AdaptiveCards { namespace Rendering { namespace Uwp RETURN_IF_FAILED(GenerateActionsProjection(sharedActionSet->GetActions(), m_actions.Get())); InitializeBaseElement(std::static_pointer_cast(sharedActionSet)); return S_OK; - } CATCH_RETURN; + } + CATCH_RETURN; - _Use_decl_annotations_ - HRESULT AdaptiveActionSet::get_Actions(IVector** items) + _Use_decl_annotations_ HRESULT AdaptiveActionSet::get_Actions(IVector** items) { return m_actions.CopyTo(items); } - _Use_decl_annotations_ - HRESULT AdaptiveActionSet::get_ElementType(ElementType* elementType) + _Use_decl_annotations_ HRESULT AdaptiveActionSet::get_ElementType(ElementType* elementType) { *elementType = ElementType::ActionSet; return S_OK; } - HRESULT AdaptiveActionSet::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveActionSet::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr actionSet = std::make_shared(); RETURN_IF_FAILED(SetSharedElementProperties(std::static_pointer_cast(actionSet))); @@ -62,5 +56,6 @@ namespace AdaptiveCards { namespace Rendering { namespace Uwp sharedModel = actionSet; return S_OK; - }CATCH_RETURN; -}}} + } + CATCH_RETURN; +} diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.h b/source/uwp/Renderer/lib/AdaptiveActionSet.h index c56d53d3fe..79461d0a6e 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.h +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ActionSet.h" -#include -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { @@ -17,9 +13,10 @@ namespace AdaptiveNamespace Microsoft::WRL::CloakedIid, Microsoft::WRL::CloakedIid> { - InspectableClass(RuntimeClass_AdaptiveCards_Rendering_Uwp_AdaptiveActionSet, BaseTrust) + InspectableClass(RuntimeClass_AdaptiveCards_Rendering_Uwp_AdaptiveActionSet, BaseTrust); - public : AdaptiveActionSet(); + public: + AdaptiveActionSet(); HRESULT RuntimeClassInitialize() noexcept; HRESULT RuntimeClassInitialize(_In_ const std::shared_ptr& sharedActionSet); diff --git a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp index 48fd18580a..da82d6ee49 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp @@ -4,15 +4,20 @@ #include "AdaptiveActionSet.h" #include "AdaptiveActionSetRenderer.h" +#include "AdaptiveShowCardActionRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "AdaptiveImage.h" +#include "AdaptiveRenderArgs.h" +#include "ActionHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { @@ -22,15 +27,6 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveActionSetRenderer::Render(_In_ IAdaptiveCardElement* cardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try - { - return XamlBuilder::BuildActionSet(cardElement, renderContext, renderArgs, result); - } - CATCH_RETURN; - HRESULT AdaptiveActionSetRenderer::FromJson( _In_ ABI::Windows::Data::Json::IJsonObject* jsonObject, _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, @@ -42,4 +38,31 @@ namespace AdaptiveNamespace jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); } CATCH_RETURN; + + HRESULT AdaptiveActionSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ IUIElement** actionSetControl) noexcept try + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"ActionSet was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveActionSet; + RETURN_IF_FAILED(cardElement.As(&adaptiveActionSet)); + + ComPtr> actions; + RETURN_IF_FAILED(adaptiveActionSet->get_Actions(&actions)); + + return XamlHelpers::BuildActionSetHelper(nullptr, adaptiveActionSet.Get(), actions.Get(), renderContext, renderArgs, actionSetControl); + } + CATCH_RETURN; } diff --git a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.h b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.h index 7ab0816f05..6e20f53f37 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ActionSet.h" namespace AdaptiveNamespace @@ -13,9 +11,10 @@ namespace AdaptiveNamespace ABI::AdaptiveNamespace::IAdaptiveElementRenderer, ABI::AdaptiveNamespace::IAdaptiveElementParser> { - InspectableClass(RuntimeClass_AdaptiveCards_Rendering_Uwp_AdaptiveActionSetRenderer, BaseTrust) + InspectableClass(RuntimeClass_AdaptiveCards_Rendering_Uwp_AdaptiveActionSetRenderer, BaseTrust); - public : HRESULT RuntimeClassInitialize() noexcept; + public: + HRESULT RuntimeClassInitialize() noexcept; IFACEMETHODIMP Render(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* cardElement, _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, diff --git a/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp b/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp index 7477c811e5..44d58168fc 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp @@ -3,7 +3,6 @@ #include "pch.h" #include "AdaptiveActionsConfig.h" #include "AdaptiveShowCardActionConfig.h" -#include "Util.h" using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveActionsConfig.h b/source/uwp/Renderer/lib/AdaptiveActionsConfig.h index 2694b33521..fb600ed5df 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionsConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveActionsConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveActionsConfig diff --git a/source/uwp/Renderer/lib/AdaptiveBackgroundImage.h b/source/uwp/Renderer/lib/AdaptiveBackgroundImage.h index d5a1ccda4f..a877d81621 100644 --- a/source/uwp/Renderer/lib/AdaptiveBackgroundImage.h +++ b/source/uwp/Renderer/lib/AdaptiveBackgroundImage.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "BackgroundImage.h" -#include namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveCard.h b/source/uwp/Renderer/lib/AdaptiveCard.h index 602c058e89..adab26cb37 100644 --- a/source/uwp/Renderer/lib/AdaptiveCard.h +++ b/source/uwp/Renderer/lib/AdaptiveCard.h @@ -2,7 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" #include "SharedAdaptiveCard.h" #include "AdaptiveBackgroundImage.h" diff --git a/source/uwp/Renderer/lib/AdaptiveCardConfig.h b/source/uwp/Renderer/lib/AdaptiveCardConfig.h index b0b9704c6a..361f030536 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveCardConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveCardConfig diff --git a/source/uwp/Renderer/lib/AdaptiveCardElement.h b/source/uwp/Renderer/lib/AdaptiveCardElement.h index 7a96538b8d..55da085639 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardElement.h +++ b/source/uwp/Renderer/lib/AdaptiveCardElement.h @@ -2,9 +2,8 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" #include "SemanticVersion.h" -#include "Enums.h" +#include "BaseElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp index a0594d681d..ad18804d08 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp @@ -34,10 +34,6 @@ #include "DefaultResourceDictionary.h" #include "InputValue.h" #include "RenderedAdaptiveCard.h" -#include "XamlHelpers.h" -#include -#include -#include using namespace concurrency; using namespace Microsoft::WRL; @@ -138,7 +134,7 @@ namespace AdaptiveNamespace if (m_explicitDimensions) { - RETURN_IF_FAILED(m_xamlBuilder->SetFixedDimensions(m_desiredWidth, m_desiredHeight)); + m_xamlBuilder->SetFixedDimensions(m_desiredWidth, m_desiredHeight); } ComPtr renderContext; @@ -300,6 +296,31 @@ namespace AdaptiveNamespace m_actionSentimentResourceDictionary = actionSentimentResourceDictionary; } + static HRESULT TryInsertResourceToResourceDictionaries(_In_ IResourceDictionary* resourceDictionary, + const std::wstring& resourceName, + _In_ IInspectable* value) + { + if (!resourceDictionary) + { + return E_INVALIDARG; + } + + ComPtr propertyValueStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), + &propertyValueStatics)); + + ComPtr resourceKey; + RETURN_IF_FAILED(propertyValueStatics->CreateString(HStringReference(resourceName.c_str()).Get(), resourceKey.GetAddressOf())); + + ComPtr strongDictionary = resourceDictionary; + ComPtr> resourceDictionaryMap; + RETURN_IF_FAILED(strongDictionary.As(&resourceDictionaryMap)); + + boolean replaced{}; + RETURN_IF_FAILED(resourceDictionaryMap->Insert(resourceKey.Get(), value, &replaced)); + return S_OK; + } + void AdaptiveCardRenderer::UpdateActionSentimentResourceDictionary() { ABI::Windows::UI::Color accentColor; @@ -322,24 +343,24 @@ namespace AdaptiveNamespace ABI::Windows::UI::Color lighterAttentionColor = GenerateLighterColor(attentionColor); ComPtr accentColorBrush = XamlHelpers::GetSolidColorBrush(accentColor); - THROW_IF_FAILED(XamlBuilder::TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Positive.Button.Static.Background", - accentColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), + L"Adaptive.Action.Positive.Button.Static.Background", + accentColorBrush.Get())); ComPtr lightAccentColorBrush = XamlHelpers::GetSolidColorBrush(lighterAccentColor); - THROW_IF_FAILED(XamlBuilder::TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Positive.Button.MouseOver.Background", - lightAccentColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), + L"Adaptive.Action.Positive.Button.MouseOver.Background", + lightAccentColorBrush.Get())); ComPtr attentionColorBrush = XamlHelpers::GetSolidColorBrush(attentionColor); - THROW_IF_FAILED(XamlBuilder::TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Destructive.Button.Foreground", - attentionColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), + L"Adaptive.Action.Destructive.Button.Foreground", + attentionColorBrush.Get())); ComPtr lightAttentionColorBrush = XamlHelpers::GetSolidColorBrush(lighterAttentionColor); - THROW_IF_FAILED(XamlBuilder::TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Destructive.Button.MouseOver.Foreground", - lightAttentionColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), + L"Adaptive.Action.Destructive.Button.MouseOver.Foreground", + lightAttentionColorBrush.Get())); } HRESULT AdaptiveCardRenderer::SetMergedDictionary() diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceInput.h b/source/uwp/Renderer/lib/AdaptiveChoiceInput.h index 889fc0fcef..d64834e90a 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceInput.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceInput.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ChoiceInput.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h index 38220c38d0..71eb9f1359 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" #include "ChoiceSetInput.h" -#include "Enums.h" -#include #include "AdaptiveInputElement.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp index ec95ed970e..b8a49c820d 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveChoiceSetInput.h" #include "AdaptiveChoiceSetInputRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { @@ -22,12 +23,42 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveChoiceSetInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveChoiceSetInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _In_ IAdaptiveRenderArgs* /*renderArgs*/, + _COM_Outptr_ IUIElement** choiceInputSet) noexcept try { - return XamlBuilder::BuildChoiceSetInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"ChoiceSet was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveChoiceSetInput; + RETURN_IF_FAILED(cardElement.As(&adaptiveChoiceSetInput)); + + ABI::AdaptiveNamespace::ChoiceSetStyle choiceSetStyle; + RETURN_IF_FAILED(adaptiveChoiceSetInput->get_ChoiceSetStyle(&choiceSetStyle)); + + boolean isMultiSelect; + RETURN_IF_FAILED(adaptiveChoiceSetInput->get_IsMultiSelect(&isMultiSelect)); + + if (choiceSetStyle == ABI::AdaptiveNamespace::ChoiceSetStyle_Compact && !isMultiSelect) + { + _BuildCompactChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), choiceInputSet); + } + else + { + _BuildExpandedChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), isMultiSelect, choiceInputSet); + } + + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *choiceInputSet); + return S_OK; } CATCH_RETURN; @@ -42,4 +73,176 @@ namespace AdaptiveNamespace jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); } CATCH_RETURN; + + static std::vector GetChoiceSetValueVector(_In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput) + { + HString value; + THROW_IF_FAILED(adaptiveChoiceSetInput->get_Value(value.GetAddressOf())); + + std::vector values; + std::string stdValue = HStringToUTF8(value.Get()); + std::stringstream streamValue(stdValue); + + while (streamValue.good()) + { + std::string subString; + std::getline(streamValue, subString, ','); + values.push_back(subString); + } + + return values; + } + + static bool IsChoiceSelected(std::vector selectedValues, _In_ IAdaptiveChoiceInput* choice) + { + HString value; + THROW_IF_FAILED(choice->get_Value(value.GetAddressOf())); + std::string stdValue = HStringToUTF8(value.Get()); + return std::find(selectedValues.begin(), selectedValues.end(), stdValue) != selectedValues.end(); + } + + HRESULT AdaptiveChoiceSetInputRenderer::_BuildCompactChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + _COM_Outptr_ IUIElement** choiceInputSet) + { + ComPtr comboBox = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ComboBox)); + + // Set HorizontalAlignment to Stretch (defaults to Left for combo boxes) + ComPtr comboBoxAsFrameworkElement; + RETURN_IF_FAILED(comboBox.As(&comboBoxAsFrameworkElement)); + RETURN_IF_FAILED(comboBoxAsFrameworkElement->put_HorizontalAlignment(HorizontalAlignment_Stretch)); + + ComPtr itemsControl; + RETURN_IF_FAILED(comboBox.As(&itemsControl)); + + ComPtr> items; + RETURN_IF_FAILED(itemsControl->get_Items(items.GetAddressOf())); + + ComPtr> itemsVector; + RETURN_IF_FAILED(items.As(&itemsVector)); + + ComPtr> choices; + RETURN_IF_FAILED(adaptiveChoiceSetInput->get_Choices(&choices)); + + std::vector values = GetChoiceSetValueVector(adaptiveChoiceSetInput); + boolean wrap; + adaptiveChoiceSetInput->get_Wrap(&wrap); + + int currentIndex = 0; + int selectedIndex = -1; + XamlHelpers::IterateOverVector( + choices.Get(), [¤tIndex, &selectedIndex, itemsVector, values, wrap](IAdaptiveChoiceInput* adaptiveChoiceInput) { + HString title; + RETURN_IF_FAILED(adaptiveChoiceInput->get_Title(title.GetAddressOf())); + + ComPtr comboBoxItem = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ComboBoxItem)); + + XamlHelpers::SetContent(comboBoxItem.Get(), title.Get(), wrap); + + // If multiple values are specified, no option is selected + if (values.size() == 1 && IsChoiceSelected(values, adaptiveChoiceInput)) + { + selectedIndex = currentIndex; + } + + ComPtr inspectable; + RETURN_IF_FAILED(comboBoxItem.As(&inspectable)); + + RETURN_IF_FAILED(itemsVector->Append(inspectable.Get())); + currentIndex++; + return S_OK; + }); + + ComPtr selector; + RETURN_IF_FAILED(comboBox.As(&selector)); + RETURN_IF_FAILED(selector->put_SelectedIndex(selectedIndex)); + + ComPtr comboBoxAsUIElement; + RETURN_IF_FAILED(comboBox.As(&comboBoxAsUIElement)); + RETURN_IF_FAILED(XamlHelpers::AddHandledTappedEvent(comboBoxAsUIElement.Get())); + + XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.ChoiceSet.Compact", + comboBoxAsFrameworkElement.Get()); + + return comboBoxAsUIElement.CopyTo(choiceInputSet); + } + + HRESULT AdaptiveChoiceSetInputRenderer::_BuildExpandedChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + boolean isMultiSelect, + _COM_Outptr_ IUIElement** choiceInputSet) + { + ComPtr> choices; + RETURN_IF_FAILED(adaptiveChoiceSetInput->get_Choices(&choices)); + + ComPtr stackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + stackPanel->put_Orientation(Orientation::Orientation_Vertical); + + ComPtr panel; + RETURN_IF_FAILED(stackPanel.As(&panel)); + + std::vector values = GetChoiceSetValueVector(adaptiveChoiceSetInput); + + boolean wrap; + adaptiveChoiceSetInput->get_Wrap(&wrap); + + XamlHelpers::IterateOverVector( + choices.Get(), [panel, isMultiSelect, renderContext, values, wrap](IAdaptiveChoiceInput* adaptiveChoiceInput) { + ComPtr choiceItem; + if (isMultiSelect) + { + ComPtr checkBox = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CheckBox)); + RETURN_IF_FAILED(checkBox.As(&choiceItem)); + + ComPtr frameworkElement; + RETURN_IF_FAILED(checkBox.As(&frameworkElement)); + XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.Choice.Multiselect", + frameworkElement.Get()); + + XamlHelpers::SetToggleValue(choiceItem.Get(), IsChoiceSelected(values, adaptiveChoiceInput)); + } + else + { + ComPtr radioButton = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RadioButton)); + RETURN_IF_FAILED(radioButton.As(&choiceItem)); + + ComPtr frameworkElement; + RETURN_IF_FAILED(radioButton.As(&frameworkElement)); + XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.Choice.SingleSelect", + frameworkElement.Get()); + + if (values.size() == 1) + { + // When isMultiSelect is false, only 1 specified value is accepted. + // Otherwise, leave all options unset + XamlHelpers::SetToggleValue(choiceItem.Get(), IsChoiceSelected(values, adaptiveChoiceInput)); + } + } + + HString title; + RETURN_IF_FAILED(adaptiveChoiceInput->get_Title(title.GetAddressOf())); + XamlHelpers::SetContent(choiceItem.Get(), title.Get(), wrap); + + RETURN_IF_FAILED(XamlHelpers::AddHandledTappedEvent(choiceItem.Get())); + + XamlHelpers::AppendXamlElementToPanel(choiceItem.Get(), panel.Get()); + return S_OK; + }); + + ComPtr choiceSetAsFrameworkElement; + RETURN_IF_FAILED(stackPanel.As(&choiceSetAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.ChoiceSet.Expanded", + choiceSetAsFrameworkElement.Get())); + + return stackPanel.CopyTo(choiceInputSet); + } } diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h index af94926e9c..8ab53c6e8e 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ChoiceSetInput.h" namespace AdaptiveNamespace @@ -28,6 +26,16 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParsers, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept override; + + private: + HRESULT _BuildExpandedChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + boolean isMultiSelect, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSet); + + HRESULT _BuildCompactChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSet); }; ActivatableClass(AdaptiveChoiceSetInputRenderer); diff --git a/source/uwp/Renderer/lib/AdaptiveColorConfig.h b/source/uwp/Renderer/lib/AdaptiveColorConfig.h index fad0fa37e4..50bc759321 100644 --- a/source/uwp/Renderer/lib/AdaptiveColorConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveColorConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveColorConfig diff --git a/source/uwp/Renderer/lib/AdaptiveColorsConfig.h b/source/uwp/Renderer/lib/AdaptiveColorsConfig.h index b6d7643573..1fdcf9ba71 100644 --- a/source/uwp/Renderer/lib/AdaptiveColorsConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveColorsConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveColorsConfig diff --git a/source/uwp/Renderer/lib/AdaptiveColumn.h b/source/uwp/Renderer/lib/AdaptiveColumn.h index e120f97bc3..c2ec5f8767 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumn.h +++ b/source/uwp/Renderer/lib/AdaptiveColumn.h @@ -2,12 +2,8 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "AdaptiveCardElement.h" #include "AdaptiveBackgroundImage.h" -#include "Enums.h" #include "Column.h" -#include namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp index c881603484..972be5c9ce 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp @@ -3,16 +3,17 @@ #include "pch.h" #include "AdaptiveColumnRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" #include "AdaptiveColumn.h" #include "AdaptiveElementParserRegistration.h" +#include "AdaptiveRenderArgs.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +23,112 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveColumnRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveColumnRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** ColumnControl) noexcept try { - return XamlBuilder::BuildColumn(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveColumn; + RETURN_IF_FAILED(cardElement.As(&adaptiveColumn)); + + ComPtr columnBorder = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); + + ComPtr columnPanel; + RETURN_IF_FAILED(MakeAndInitialize(&columnPanel)); + + ComPtr columnPanelAsUIElement; + RETURN_IF_FAILED(columnPanel.As(&columnPanelAsUIElement)); + + RETURN_IF_FAILED(columnBorder->put_Child(columnPanelAsUIElement.Get())); + + ComPtr columnAsContainerBase; + RETURN_IF_FAILED(adaptiveColumn.As(&columnAsContainerBase)); + + ABI::AdaptiveNamespace::ContainerStyle containerStyle; + RETURN_IF_FAILED( + XamlHelpers::HandleStylingAndPadding(columnAsContainerBase.Get(), columnBorder.Get(), renderContext, renderArgs, &containerStyle)); + + ComPtr parentElement; + RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); + ComPtr newRenderArgs; + RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); + + ComPtr columnAsPanel; + THROW_IF_FAILED(columnPanel.As(&columnAsPanel)); + + ComPtr> childItems; + RETURN_IF_FAILED(adaptiveColumn->get_Items(&childItems)); + RETURN_IF_FAILED(XamlBuilder::BuildPanelChildren( + childItems.Get(), columnAsPanel.Get(), renderContext, newRenderArgs.Get(), [](IUIElement*) {})); + + ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment; + RETURN_IF_FAILED(adaptiveColumn->get_VerticalContentAlignment(&verticalContentAlignment)); + + XamlHelpers::SetVerticalContentAlignmentToChildren(columnPanel.Get(), verticalContentAlignment); + + // Assign vertical alignment to the top so that on fixed height cards, the content + // still renders at the top even if the content is shorter than the full card + ComPtr columnPanelAsFrameworkElement; + RETURN_IF_FAILED(columnPanel.As(&columnPanelAsFrameworkElement)); + RETURN_IF_FAILED(columnPanelAsFrameworkElement->put_VerticalAlignment(VerticalAlignment_Stretch)); + + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Column", columnPanelAsFrameworkElement.Get())); + + UINT32 columnMinHeight{}; + RETURN_IF_FAILED(columnAsContainerBase->get_MinHeight(&columnMinHeight)); + if (columnMinHeight > 0) + { + RETURN_IF_FAILED(columnPanelAsFrameworkElement->put_MinHeight(columnMinHeight)); + } + + ComPtr selectAction; + RETURN_IF_FAILED(columnAsContainerBase->get_SelectAction(&selectAction)); + + // Define columnAsUIElement based on the existence of a backgroundImage + ComPtr columnAsUIElement; + ComPtr backgroundImage; + BOOL backgroundImageIsValid; + RETURN_IF_FAILED(adaptiveColumn->get_BackgroundImage(&backgroundImage)); + RETURN_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); + if (backgroundImageIsValid) + { + ComPtr rootElement = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr rootAsPanel; + RETURN_IF_FAILED(rootElement.As(&rootAsPanel)); + + XamlHelpers::ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, newRenderArgs.Get()); + + // get HeightType for column + ABI::AdaptiveNamespace::HeightType columnHeightType{}; + RETURN_IF_FAILED(cardElement->get_Height(&columnHeightType)); + + // Add columnBorder to rootElement + ComPtr columnBorderAsFElement; + RETURN_IF_FAILED(columnBorder.As(&columnBorderAsFElement)); + XamlHelpers::AppendXamlElementToPanel(columnBorderAsFElement.Get(), rootAsPanel.Get(), columnHeightType); + + RETURN_IF_FAILED(rootElement.As(&columnAsUIElement)); + } + else + { + RETURN_IF_FAILED(columnBorder.As(&columnAsUIElement)); + } + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + XamlHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + columnAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + false, + ColumnControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.h b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.h index 1aefc7efd7..7c4e01720b 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Column.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSet.h b/source/uwp/Renderer/lib/AdaptiveColumnSet.h index b0b0616af5..612b0d3730 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSet.h +++ b/source/uwp/Renderer/lib/AdaptiveColumnSet.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ColumnSet.h" -#include -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp index 736f5d75e6..53831cdac7 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveColumnSet.h" #include "AdaptiveColumnSetRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "AdaptiveRenderArgs.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +23,204 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveColumnSetRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveColumnSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** columnSetControl) noexcept try { - return XamlBuilder::BuildColumnSet(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveColumnSet; + RETURN_IF_FAILED(cardElement.As(&adaptiveColumnSet)); + + ComPtr columnSetBorder = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); + + ComPtr gridContainer; + RETURN_IF_FAILED(MakeAndInitialize(&gridContainer)); + + ComPtr gridContainerAsUIElement; + RETURN_IF_FAILED(gridContainer.As(&gridContainerAsUIElement)); + + RETURN_IF_FAILED(columnSetBorder->put_Child(gridContainerAsUIElement.Get())); + + ComPtr columnSetAsContainerBase; + RETURN_IF_FAILED(adaptiveColumnSet.As(&columnSetAsContainerBase)); + + ABI::AdaptiveNamespace::ContainerStyle containerStyle; + RETURN_IF_FAILED(XamlHelpers::HandleStylingAndPadding( + columnSetAsContainerBase.Get(), columnSetBorder.Get(), renderContext, renderArgs, &containerStyle)); + + ComPtr parentElement; + RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); + ComPtr newRenderArgs; + RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); + + ComPtr xamlGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr gridStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); + + ComPtr> columns; + RETURN_IF_FAILED(adaptiveColumnSet->get_Columns(&columns)); + int currentColumn{}; + ComPtr elementRenderers; + RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + ComPtr columnRenderer; + RETURN_IF_FAILED(elementRenderers->Get(HStringReference(L"Column").Get(), &columnRenderer)); + + if (columnRenderer == nullptr) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, + HStringReference(L"No renderer found for type: Column").Get()); + *columnSetControl = nullptr; + return S_OK; + } + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + boolean ancestorHasFallback; + RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); + + ComPtr gridAsPanel; + RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); + + HRESULT hrColumns = XamlHelpers::IterateOverVectorWithFailure(columns.Get(), ancestorHasFallback, [&](IAdaptiveColumn* column) { + ComPtr columnAsCardElement; + ComPtr localColumn(column); + RETURN_IF_FAILED(localColumn.As(&columnAsCardElement)); + + ComPtr testColumn; + columnAsCardElement.As(&testColumn); + + ComPtr> columnDefinitions; + RETURN_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); + + ABI::AdaptiveNamespace::FallbackType fallbackType; + RETURN_IF_FAILED(columnAsCardElement->get_FallbackType(&fallbackType)); + + // Build the Column + RETURN_IF_FAILED(newRenderArgs->put_AncestorHasFallback( + ancestorHasFallback || fallbackType != ABI::AdaptiveNamespace::FallbackType::None)); + + ComPtr xamlColumn; + HRESULT hr = columnRenderer->Render(columnAsCardElement.Get(), renderContext, newRenderArgs.Get(), &xamlColumn); + if (hr == E_PERFORM_FALLBACK) + { + RETURN_IF_FAILED(XamlHelpers::RenderFallback(columnAsCardElement.Get(), renderContext, newRenderArgs.Get(), &xamlColumn)); + } + + RETURN_IF_FAILED(newRenderArgs->put_AncestorHasFallback(ancestorHasFallback)); + + // Check the column for nullptr as it may have been dropped due to fallback + if (xamlColumn != nullptr) + { + // If not the first column + ComPtr separator; + if (currentColumn > 0) + { + // Add Separator to the columnSet + bool needsSeparator; + UINT spacing; + UINT separatorThickness; + ABI::Windows::UI::Color separatorColor; + XamlHelpers::GetSeparationConfigForElement( + columnAsCardElement.Get(), hostConfig.Get(), &spacing, &separatorThickness, &separatorColor, &needsSeparator); + + if (needsSeparator) + { + // Create a new ColumnDefinition for the separator + ComPtr separatorColumnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + RETURN_IF_FAILED(separatorColumnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Auto})); + RETURN_IF_FAILED(columnDefinitions->Append(separatorColumnDefinition.Get())); + + separator = XamlHelpers::CreateSeparator(renderContext, spacing, separatorThickness, separatorColor, false); + ComPtr separatorAsFrameworkElement; + RETURN_IF_FAILED(separator.As(&separatorAsFrameworkElement)); + gridStatics->SetColumn(separatorAsFrameworkElement.Get(), currentColumn++); + XamlHelpers::AppendXamlElementToPanel(separator.Get(), gridAsPanel.Get()); + } + } + + // Determine if the column is auto, stretch, or percentage width, and set the column width appropriately + ComPtr columnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + + boolean isVisible; + RETURN_IF_FAILED(columnAsCardElement->get_IsVisible(&isVisible)); + + RETURN_IF_FAILED(XamlHelpers::HandleColumnWidth(column, isVisible, columnDefinition.Get())); + + RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); + + // Mark the column container with the current column + ComPtr columnAsFrameworkElement; + RETURN_IF_FAILED(xamlColumn.As(&columnAsFrameworkElement)); + gridStatics->SetColumn(columnAsFrameworkElement.Get(), currentColumn++); + + // Finally add the column container to the grid + RETURN_IF_FAILED(XamlHelpers::AddRenderedControl(xamlColumn.Get(), + columnAsCardElement.Get(), + gridAsPanel.Get(), + separator.Get(), + columnDefinition.Get(), + [](IUIElement*) {})); + } + return S_OK; + }); + RETURN_IF_FAILED(hrColumns); + + RETURN_IF_FAILED(XamlHelpers::SetSeparatorVisibility(gridAsPanel.Get())); + + ComPtr columnSetAsFrameworkElement; + RETURN_IF_FAILED(xamlGrid.As(&columnSetAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.ColumnSet", + columnSetAsFrameworkElement.Get())); + RETURN_IF_FAILED(columnSetAsFrameworkElement->put_VerticalAlignment(VerticalAlignment_Stretch)); + + ComPtr selectAction; + RETURN_IF_FAILED(columnSetAsContainerBase->get_SelectAction(&selectAction)); + + ComPtr gridContainerAsPanel; + RETURN_IF_FAILED(gridContainer.As(&gridContainerAsPanel)); + + ComPtr gridContainerAsFrameworkElement; + RETURN_IF_FAILED(gridContainer.As(&gridContainerAsFrameworkElement)); + + ComPtr gridAsUIElement; + RETURN_IF_FAILED(xamlGrid.As(&gridAsUIElement)); + + ComPtr columnSetAsCardElement; + RETURN_IF_FAILED(adaptiveColumnSet.As(&columnSetAsCardElement)); + + ABI::AdaptiveNamespace::HeightType columnSetHeightType; + RETURN_IF_FAILED(columnSetAsCardElement->get_Height(&columnSetHeightType)); + + ComPtr columnAsContainerBase; + RETURN_IF_FAILED(adaptiveColumnSet.As(&columnAsContainerBase)); + + UINT32 columnSetMinHeight{}; + RETURN_IF_FAILED(columnAsContainerBase->get_MinHeight(&columnSetMinHeight)); + if (columnSetMinHeight > 0) + { + RETURN_IF_FAILED(gridContainerAsFrameworkElement->put_MinHeight(columnSetMinHeight)); + } + + XamlHelpers::AppendXamlElementToPanel(xamlGrid.Get(), gridContainerAsPanel.Get(), columnSetHeightType); + + ComPtr columnSetBorderAsUIElement; + RETURN_IF_FAILED(columnSetBorder.As(&columnSetBorderAsUIElement)); + + XamlHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + columnSetBorderAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + columnSetControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.h b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.h index 5b1626d5dc..fe60baaa23 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ColumnSet.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveContainer.h b/source/uwp/Renderer/lib/AdaptiveContainer.h index 206847d190..823701ed20 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainer.h +++ b/source/uwp/Renderer/lib/AdaptiveContainer.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Container.h" -#include -#include "AdaptiveCardElement.h" #include "AdaptiveBackgroundImage.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp index ae3ac231f6..16b10c9401 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveContainer.h" #include "AdaptiveContainerRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "AdaptiveRenderArgs.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +23,117 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveContainerRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveContainerRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** containerControl) noexcept try { - return XamlBuilder::BuildContainer(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveContainer; + RETURN_IF_FAILED(cardElement.As(&adaptiveContainer)); + + ComPtr containerPanel; + RETURN_IF_FAILED(MakeAndInitialize(&containerPanel)); + + ComPtr containerPanelAsFrameWorkElement; + RETURN_IF_FAILED(containerPanel.As(&containerPanelAsFrameWorkElement)); + + // Assign vertical alignment to the top so that on fixed height cards, the content + // still renders at the top even if the content is shorter than the full card + ABI::AdaptiveNamespace::HeightType containerHeightType{}; + RETURN_IF_FAILED(cardElement->get_Height(&containerHeightType)); + if (containerHeightType == ABI::AdaptiveNamespace::HeightType::Auto) + { + RETURN_IF_FAILED(containerPanelAsFrameWorkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + } + + ComPtr containerAsContainerBase; + RETURN_IF_FAILED(adaptiveContainer.As(&containerAsContainerBase)); + + UINT32 containerMinHeight{}; + RETURN_IF_FAILED(containerAsContainerBase->get_MinHeight(&containerMinHeight)); + if (containerMinHeight > 0) + { + RETURN_IF_FAILED(containerPanelAsFrameWorkElement->put_MinHeight(containerMinHeight)); + } + + ComPtr containerBorder = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); + + ABI::AdaptiveNamespace::ContainerStyle containerStyle; + RETURN_IF_FAILED(XamlHelpers::HandleStylingAndPadding( + containerAsContainerBase.Get(), containerBorder.Get(), renderContext, renderArgs, &containerStyle)); + + ComPtr parentElement; + RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); + ComPtr newRenderArgs; + RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); + + ComPtr containerPanelAsPanel; + RETURN_IF_FAILED(containerPanel.As(&containerPanelAsPanel)); + ComPtr> childItems; + RETURN_IF_FAILED(adaptiveContainer->get_Items(&childItems)); + RETURN_IF_FAILED(XamlBuilder::BuildPanelChildren( + childItems.Get(), containerPanelAsPanel.Get(), renderContext, newRenderArgs.Get(), [](IUIElement*) {})); + + ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment; + RETURN_IF_FAILED(adaptiveContainer->get_VerticalContentAlignment(&verticalContentAlignment)); + + XamlHelpers::SetVerticalContentAlignmentToChildren(containerPanel.Get(), verticalContentAlignment); + + // Check if backgroundImage defined + ComPtr backgroundImage; + BOOL backgroundImageIsValid; + RETURN_IF_FAILED(adaptiveContainer->get_BackgroundImage(&backgroundImage)); + RETURN_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); + if (backgroundImageIsValid) + { + ComPtr rootElement = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr rootAsPanel; + RETURN_IF_FAILED(rootElement.As(&rootAsPanel)); + + XamlHelpers::ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, newRenderArgs.Get()); + + // Add rootElement to containerBorder + ComPtr rootAsUIElement; + RETURN_IF_FAILED(rootElement.As(&rootAsUIElement)); + RETURN_IF_FAILED(containerBorder->put_Child(rootAsUIElement.Get())); + + // Add containerPanel to rootElement + ComPtr containerPanelAsFElement; + RETURN_IF_FAILED(containerPanel.As(&containerPanelAsFElement)); + XamlHelpers::AppendXamlElementToPanel(containerPanelAsFElement.Get(), rootAsPanel.Get(), containerHeightType); + } + else + { + // instead, directly add containerPanel to containerBorder + ComPtr containerPanelAsUIElement; + RETURN_IF_FAILED(containerPanel.As(&containerPanelAsUIElement)); + RETURN_IF_FAILED(containerBorder->put_Child(containerPanelAsUIElement.Get())); + } + + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Container", + containerPanelAsFrameWorkElement.Get())); + + ComPtr selectAction; + RETURN_IF_FAILED(containerAsContainerBase->get_SelectAction(&selectAction)); + + ComPtr containerBorderAsUIElement; + RETURN_IF_FAILED(containerBorder.As(&containerBorderAsUIElement)); + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + XamlHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + containerBorderAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + containerControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.h b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.h index 3e2f8b0b7f..48a06463d3 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Container.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.h b/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.h index 65b80d79e1..61f1722f20 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.h +++ b/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveContainerStyleDefinition diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h index c6521895a3..6ab85011ee 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h +++ b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveContainerStylesDefinition diff --git a/source/uwp/Renderer/lib/AdaptiveDateInput.h b/source/uwp/Renderer/lib/AdaptiveDateInput.h index 95f82cecc8..16b58aa0cf 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInput.h +++ b/source/uwp/Renderer/lib/AdaptiveDateInput.h @@ -2,9 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" #include "DateInput.h" -#include "Enums.h" #include "AdaptiveInputElement.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp index 21d5fc953e..7ef8394a92 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp @@ -5,14 +5,14 @@ #include "AdaptiveDateInput.h" #include "AdaptiveDateInputRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +22,95 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveDateInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveDateInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _In_ IAdaptiveRenderArgs* /*renderArgs*/, + _COM_Outptr_ IUIElement** dateInputControl) noexcept try { - return XamlBuilder::BuildDateInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Date input was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveDateInput; + RETURN_IF_FAILED(cardElement.As(&adaptiveDateInput)); + + ComPtr datePicker = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CalendarDatePicker)); + + HString placeHolderText; + RETURN_IF_FAILED(adaptiveDateInput->get_Placeholder(placeHolderText.GetAddressOf())); + RETURN_IF_FAILED(datePicker->put_PlaceholderText(placeHolderText.Get())); + + // Make the picker stretch full width + ComPtr datePickerAsFrameworkElement; + RETURN_IF_FAILED(datePicker.As(&datePickerAsFrameworkElement)); + RETURN_IF_FAILED(datePickerAsFrameworkElement->put_HorizontalAlignment(HorizontalAlignment_Stretch)); + RETURN_IF_FAILED(datePickerAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + + RETURN_IF_FAILED(datePicker.CopyTo(dateInputControl)); + + // Value + HString hstringValue; + RETURN_IF_FAILED(adaptiveDateInput->get_Value(hstringValue.GetAddressOf())); + std::string value = HStringToUTF8(hstringValue.Get()); + unsigned int year, month, day; + if (DateTimePreparser::TryParseSimpleDate(value, year, month, day)) + { + ComPtr> initialDateTimeReference; + RETURN_IF_FAILED(GetDateTimeReference(year, month, day, &initialDateTimeReference)); + RETURN_IF_FAILED(datePicker->put_Date(initialDateTimeReference.Get())); + } + + // Min date + HString hstringMin; + RETURN_IF_FAILED(adaptiveDateInput->get_Min(hstringMin.GetAddressOf())); + std::string min = HStringToUTF8(hstringMin.Get()); + DateTime minDate{}; + boolean isMinValid{DateTimePreparser::TryParseSimpleDate(min, year, month, day)}; + if (isMinValid) + { + minDate = GetDateTime(year, month, day); + RETURN_IF_FAILED(datePicker->put_MinDate(minDate)); + } + + // Max date + HString hstringMax; + RETURN_IF_FAILED(adaptiveDateInput->get_Max(hstringMax.GetAddressOf())); + std::string max = HStringToUTF8(hstringMax.Get()); + if (DateTimePreparser::TryParseSimpleDate(max, year, month, day)) + { + DateTime maxDate = GetDateTime(year, month, day); + if (isMinValid) + { + if (maxDate.UniversalTime > minDate.UniversalTime) + { + RETURN_IF_FAILED(datePicker->put_MaxDate(maxDate)); + } + else + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InvalidValue, + HStringReference(L"Min value must be less than max in Input.Date").Get()); + } + } + else + { + RETURN_IF_FAILED(datePicker->put_MaxDate(maxDate)); + } + } + + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.Date", + datePickerAsFrameworkElement.Get())); + + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *dateInputControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.h index 1bfb83bf14..2acb9adc6f 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "DateInput.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveFact.cpp b/source/uwp/Renderer/lib/AdaptiveFact.cpp index bd40fd3145..e25eade52f 100644 --- a/source/uwp/Renderer/lib/AdaptiveFact.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFact.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFact.h" -#include "Util.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveFact.h b/source/uwp/Renderer/lib/AdaptiveFact.h index 6bc5ac3044..14d42aaec2 100644 --- a/source/uwp/Renderer/lib/AdaptiveFact.h +++ b/source/uwp/Renderer/lib/AdaptiveFact.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Fact.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveFactSet.h b/source/uwp/Renderer/lib/AdaptiveFactSet.h index 161a6e73d2..03206285cf 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSet.h +++ b/source/uwp/Renderer/lib/AdaptiveFactSet.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "FactSet.h" -#include -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp index 8cf73f335a..d7a5e65aa6 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFactSetConfig.h" #include "AdaptiveTextConfig.h" diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.h b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.h index 34445bc049..1e23cd469f 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveFactSetConfig diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp index 82991d0f6e..419a5b10de 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp @@ -5,29 +5,154 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveFactSet.h" #include "AdaptiveFactSetRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "TextHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveFactSetRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFactSetRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } CATCH_RETURN; - HRESULT AdaptiveFactSetRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveFactSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** factSetControl) noexcept try { - return XamlBuilder::BuildFactSet(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveFactSet; + + RETURN_IF_FAILED(cardElement.As(&adaptiveFactSet)); + + ComPtr xamlGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr gridStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); + + ComPtr titleColumn = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + ComPtr valueColumn = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + GridLength factSetGridTitleLength = {0, GridUnitType::GridUnitType_Auto}; + GridLength factSetGridValueLength = {1, GridUnitType::GridUnitType_Star}; + + RETURN_IF_FAILED(titleColumn->put_Width(factSetGridTitleLength)); + RETURN_IF_FAILED(valueColumn->put_Width(factSetGridValueLength)); + ComPtr> columnDefinitions; + RETURN_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); + RETURN_IF_FAILED(columnDefinitions->Append(titleColumn.Get())); + RETURN_IF_FAILED(columnDefinitions->Append(valueColumn.Get())); + + GridLength factSetGridHeight = {0, GridUnitType::GridUnitType_Auto}; + ABI::AdaptiveNamespace::HeightType heightType; + RETURN_IF_FAILED(cardElement->get_Height(&heightType)); + if (heightType == ABI::AdaptiveNamespace::HeightType::Stretch) + { + factSetGridHeight = {1, GridUnitType::GridUnitType_Star}; + } + + ComPtr> facts; + RETURN_IF_FAILED(adaptiveFactSet->get_Facts(&facts)); + int currentFact = 0; + XamlHelpers::IterateOverVector( + facts.Get(), [xamlGrid, gridStatics, factSetGridHeight, ¤tFact, renderContext, renderArgs](IAdaptiveFact* fact) { + ComPtr factRow = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RowDefinition)); + RETURN_IF_FAILED(factRow->put_Height(factSetGridHeight)); + + ComPtr> rowDefinitions; + RETURN_IF_FAILED(xamlGrid->get_RowDefinitions(&rowDefinitions)); + RETURN_IF_FAILED(rowDefinitions->Append(factRow.Get())); + + ComPtr localFact(fact); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr factSetConfig; + RETURN_IF_FAILED(hostConfig->get_FactSet(&factSetConfig)); + + // Get Language + HString language; + RETURN_IF_FAILED(localFact->get_Language(language.GetAddressOf())); + + // Create the title xaml textblock and style it from Host options + ComPtr titleTextConfig; + RETURN_IF_FAILED(factSetConfig->get_Title(&titleTextConfig)); + + ComPtr titleTextBlock = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); + + HString factTitle; + RETURN_IF_FAILED(localFact->get_Title(factTitle.GetAddressOf())); + + RETURN_IF_FAILED(SetXamlInlinesWithTextConfig( + renderContext, renderArgs, titleTextConfig.Get(), language.Get(), factTitle.Get(), titleTextBlock.Get())); + + // Create the value xaml textblock and style it from Host options + ComPtr valueTextConfig; + RETURN_IF_FAILED(factSetConfig->get_Value(&valueTextConfig)); + + ComPtr valueTextBlock = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); + + HString factValue; + RETURN_IF_FAILED(localFact->get_Value(factValue.GetAddressOf())); + + RETURN_IF_FAILED(SetXamlInlinesWithTextConfig( + renderContext, renderArgs, valueTextConfig.Get(), language.Get(), factValue.Get(), valueTextBlock.Get())); + + // Mark the column container with the current column + ComPtr titleTextBlockAsFrameWorkElement; + RETURN_IF_FAILED(titleTextBlock.As(&titleTextBlockAsFrameWorkElement)); + ComPtr valueTextBlockAsFrameWorkElement; + RETURN_IF_FAILED(valueTextBlock.As(&valueTextBlockAsFrameWorkElement)); + + UINT32 spacing; + RETURN_IF_FAILED(factSetConfig->get_Spacing(&spacing)); + // Add spacing from hostconfig to right margin of title. + titleTextBlockAsFrameWorkElement->put_Margin({0, 0, (double)spacing, 0}); + + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Fact.Title", + titleTextBlockAsFrameWorkElement.Get())); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Fact.Value", + valueTextBlockAsFrameWorkElement.Get())); + + RETURN_IF_FAILED(gridStatics->SetColumn(titleTextBlockAsFrameWorkElement.Get(), 0)); + RETURN_IF_FAILED(gridStatics->SetRow(titleTextBlockAsFrameWorkElement.Get(), currentFact)); + + RETURN_IF_FAILED(gridStatics->SetColumn(valueTextBlockAsFrameWorkElement.Get(), 1)); + RETURN_IF_FAILED(gridStatics->SetRow(valueTextBlockAsFrameWorkElement.Get(), currentFact)); + + // Finally add the column container to the grid, and increment the column count + ComPtr gridAsPanel; + RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); + ComPtr titleUIElement; + RETURN_IF_FAILED(titleTextBlockAsFrameWorkElement.As(&titleUIElement)); + ComPtr valueUIElement; + RETURN_IF_FAILED(valueTextBlockAsFrameWorkElement.As(&valueUIElement)); + + XamlHelpers::AppendXamlElementToPanel(titleUIElement.Get(), gridAsPanel.Get()); + XamlHelpers::AppendXamlElementToPanel(valueUIElement.Get(), gridAsPanel.Get()); + ++currentFact; + return S_OK; + }); + + ComPtr factSetAsFrameworkElement; + RETURN_IF_FAILED(xamlGrid.As(&factSetAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.FactSet", factSetAsFrameworkElement.Get())); + + return xamlGrid.CopyTo(factSetControl); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.h b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.h index 04f5f64ad1..6927e32664 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "FactSet.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp index 9f9fd89545..f6ec36af9c 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFontSizesConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.h b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.h index e247879924..34ad2b6833 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveFontSizesConfig diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp index aecaf16f19..fc2e3f058a 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFontTypeDefinition.h" #include "AdaptiveFontWeightsConfig.h" #include "AdaptiveFontSizesConfig.h" diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.h b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.h index 77bed7fd68..16be36b1c2 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.h +++ b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveFontTypeDefinition diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp index 937f860520..e71d1f8e4b 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFontTypeDefinition.h" #include "AdaptiveFontTypesDefinition.h" diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.h b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.h index 80721cccf3..60ccbee1f1 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.h +++ b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveFontTypesDefinition diff --git a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp index beaa899b8b..86e07ecf33 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveFontWeightsConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.h b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.h index cf8f4d771b..e1384d009e 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveFontWeightsConfig diff --git a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp index 789bc47e42..cb264d0a69 100644 --- a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "Util.h" + #include "AdaptiveHighlightColorConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.h b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.h index 3c50f9f5d3..097fff532d 100644 --- a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveHighlightColorConfig diff --git a/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp b/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp index e28ad4d53c..3a50dcff50 100644 --- a/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp @@ -1,24 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveHostConfig.h" -#include "Util.h" + #include "AdaptiveActionsConfig.h" #include "AdaptiveCardConfig.h" #include "AdaptiveColorsConfig.h" #include "AdaptiveContainerStylesDefinition.h" #include "AdaptiveFactSetConfig.h" #include "AdaptiveFontSizesConfig.h" -#include "AdaptiveFontWeightsConfig.h" #include "AdaptiveFontTypeDefinition.h" #include "AdaptiveFontTypesDefinition.h" +#include "AdaptiveFontWeightsConfig.h" +#include "AdaptiveHostConfig.h" #include "AdaptiveHostConfigParseResult.h" #include "AdaptiveImageConfig.h" #include "AdaptiveImageSetConfig.h" #include "AdaptiveImageSizesConfig.h" #include "AdaptiveMediaConfig.h" -#include "AdaptiveSpacingConfig.h" #include "AdaptiveSeparatorConfig.h" +#include "AdaptiveSpacingConfig.h" using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveHostConfig.h b/source/uwp/Renderer/lib/AdaptiveHostConfig.h index e74b1f273f..aa673e5e13 100644 --- a/source/uwp/Renderer/lib/AdaptiveHostConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveHostConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveHostConfig diff --git a/source/uwp/Renderer/lib/AdaptiveImage.cpp b/source/uwp/Renderer/lib/AdaptiveImage.cpp index e57972248f..a25add3e5b 100644 --- a/source/uwp/Renderer/lib/AdaptiveImage.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImage.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveImage.h" -#include "Util.h" +#include "AdaptiveImage.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveImage.h b/source/uwp/Renderer/lib/AdaptiveImage.h index 254facfbd7..f8fa4422ba 100644 --- a/source/uwp/Renderer/lib/AdaptiveImage.h +++ b/source/uwp/Renderer/lib/AdaptiveImage.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Image.h" -#include -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp index f97dc83fd3..09ef8a7bf5 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveImageConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveImageConfig.h b/source/uwp/Renderer/lib/AdaptiveImageConfig.h index c450cc1c10..98f71e6341 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveImageConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveImageConfig diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index 066dbcbf96..2c2ff63edf 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -2,24 +2,43 @@ // Licensed under the MIT License. #include "pch.h" +#include "AdaptiveImageRenderer.h" + #include "AdaptiveElementParserRegistration.h" #include "AdaptiveImage.h" -#include "AdaptiveImageRenderer.h" -#include "enums.h" -#include "Util.h" +#include "AdaptiveBase64Util.h" +#include "AdaptiveCardGetResourceStreamArgs.h" +#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; +using namespace ABI::Windows::Data::Json; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::Storage::Streams; +using namespace ABI::Windows::UI; +using namespace ABI::Windows::UI::Text; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Data; +using namespace ABI::Windows::UI::Xaml::Documents; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; +using namespace ABI::Windows::UI::Xaml::Markup; +using namespace ABI::Windows::UI::Xaml::Media; +using namespace ABI::Windows::UI::Xaml::Media::Imaging; +using namespace ABI::Windows::UI::Xaml::Shapes; +using namespace ABI::Windows::UI::Xaml::Input; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::Web::Http; +using namespace ABI::Windows::Web::Http::Filters; namespace AdaptiveNamespace { AdaptiveImageRenderer::AdaptiveImageRenderer() {} - AdaptiveImageRenderer::AdaptiveImageRenderer(ComPtr xamlBuilder) : m_xamlBuilder(xamlBuilder) - { - } + AdaptiveImageRenderer::AdaptiveImageRenderer(ComPtr xamlBuilder) : m_xamlBuilder(xamlBuilder) {} HRESULT AdaptiveImageRenderer::RuntimeClassInitialize() noexcept try { @@ -48,4 +67,687 @@ namespace AdaptiveNamespace jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); } CATCH_RETURN; + + HRESULT XamlBuilder::BuildImage(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ IUIElement** imageControl) + { + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveImage; + RETURN_IF_FAILED(cardElement.As(&adaptiveImage)); + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + HSTRING url; + RETURN_IF_FAILED(adaptiveImage->get_Url(&url)); + + ComPtr imageUrl; + GetUrlFromString(hostConfig.Get(), url, imageUrl.GetAddressOf()); + + if (imageUrl == nullptr) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::AssetLoadFailed, + HStringReference(L"Image not found").Get()); + *imageControl = nullptr; + return S_OK; + } + + UINT32 pixelWidth = 0, pixelHeight = 0; + RETURN_IF_FAILED(adaptiveImage->get_PixelWidth(&pixelWidth)); + RETURN_IF_FAILED(adaptiveImage->get_PixelHeight(&pixelHeight)); + bool hasExplicitMeasurements = (pixelWidth || pixelHeight); + bool isAspectRatioNeeded = (pixelWidth && pixelHeight); + + // Get the image's size and style + ABI::AdaptiveNamespace::ImageSize size = ABI::AdaptiveNamespace::ImageSize::None; + if (!hasExplicitMeasurements) + { + RETURN_IF_FAILED(adaptiveImage->get_Size(&size)); + } + + if (size == ABI::AdaptiveNamespace::ImageSize::None && !hasExplicitMeasurements) + { + ComPtr imageConfig; + RETURN_IF_FAILED(hostConfig->get_Image(&imageConfig)); + RETURN_IF_FAILED(imageConfig->get_ImageSize(&size)); + } + + ABI::AdaptiveNamespace::ImageStyle imageStyle; + RETURN_IF_FAILED(adaptiveImage->get_Style(&imageStyle)); + ComPtr resourceResolvers; + RETURN_IF_FAILED(renderContext->get_ResourceResolvers(&resourceResolvers)); + + HSTRING backgroundColor; + RETURN_IF_FAILED(adaptiveImage->get_BackgroundColor(&backgroundColor)); + + boolean isVisible; + RETURN_IF_FAILED(adaptiveCardElement->get_IsVisible(&isVisible)); + + ComPtr frameworkElement; + if (imageStyle == ImageStyle_Person) + { + ComPtr ellipse = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Ellipse)); + ComPtr backgroundEllipse = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Ellipse)); + + Stretch imageStretch = (isAspectRatioNeeded) ? Stretch::Stretch_Fill : Stretch::Stretch_UniformToFill; + bool mustHideElement{true}; + + ComPtr parentElement; + RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); + + ComPtr ellipseAsShape; + RETURN_IF_FAILED(ellipse.As(&ellipseAsShape)); + + SetImageOnUIElement(imageUrl.Get(), + ellipse.Get(), + resourceResolvers.Get(), + (size == ABI::AdaptiveNamespace::ImageSize_Auto), + parentElement.Get(), + ellipseAsShape.Get(), + isVisible, + &mustHideElement, + imageStretch); + + ComPtr backgroundEllipseAsShape; + RETURN_IF_FAILED(backgroundEllipse.As(&backgroundEllipseAsShape)); + + if (size == ABI::AdaptiveNamespace::ImageSize::None || size == ABI::AdaptiveNamespace::ImageSize::Stretch || + size == ABI::AdaptiveNamespace::ImageSize::Auto || hasExplicitMeasurements) + { + RETURN_IF_FAILED(ellipseAsShape->put_Stretch(imageStretch)); + RETURN_IF_FAILED(backgroundEllipseAsShape->put_Stretch(imageStretch)); + } + else + { + // Set the stretch for the ellipse - this is different to the stretch used for the image brush + // above. This will force the ellipse to conform to fit within the confines of its parent. + Stretch ellipseStretch = Stretch::Stretch_UniformToFill; + RETURN_IF_FAILED(ellipseAsShape->put_Stretch(ellipseStretch)); + RETURN_IF_FAILED(backgroundEllipseAsShape->put_Stretch(ellipseStretch)); + } + + if (backgroundColor != nullptr) + { + // Fill the background ellipse with solid color brush + ABI::Windows::UI::Color color; + RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); + ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); + RETURN_IF_FAILED(backgroundEllipseAsShape->put_Fill(backgroundColorBrush.Get())); + + // Create a grid to contain the background color ellipse and the image ellipse + ComPtr imageGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + + ComPtr panel; + RETURN_IF_FAILED(imageGrid.As(&panel)); + + XamlHelpers::AppendXamlElementToPanel(backgroundEllipse.Get(), panel.Get()); + XamlHelpers::AppendXamlElementToPanel(ellipse.Get(), panel.Get()); + + RETURN_IF_FAILED(imageGrid.As(&frameworkElement)); + } + else + { + RETURN_IF_FAILED(ellipse.As(&frameworkElement)); + } + } + else + { + ComPtr xamlImage = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Image)); + + if (backgroundColor != nullptr) + { + // Create a surrounding border with solid color background to contain the image + ComPtr border = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); + + ABI::Windows::UI::Color color; + RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); + ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); + RETURN_IF_FAILED(border->put_Background(backgroundColorBrush.Get())); + + ComPtr imageAsUiElement; + RETURN_IF_FAILED(xamlImage.CopyTo(imageAsUiElement.GetAddressOf())); + RETURN_IF_FAILED(border->put_Child(imageAsUiElement.Get())); + + RETURN_IF_FAILED(border.As(&frameworkElement)); + } + else + { + RETURN_IF_FAILED(xamlImage.As(&frameworkElement)); + } + + if (isAspectRatioNeeded) + { + xamlImage->put_Stretch(Stretch::Stretch_Fill); + } + + ComPtr parentElement; + RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); + + bool mustHideElement{true}; + SetImageOnUIElement(imageUrl.Get(), + xamlImage.Get(), + resourceResolvers.Get(), + (size == ABI::AdaptiveNamespace::ImageSize_Auto), + parentElement.Get(), + frameworkElement.Get(), + isVisible, + &mustHideElement); + } + + ComPtr sizeOptions; + RETURN_IF_FAILED(hostConfig->get_ImageSizes(sizeOptions.GetAddressOf())); + + if (hasExplicitMeasurements) + { + if (pixelWidth) + { + if (imageStyle == ImageStyle_Person) + { + RETURN_IF_FAILED(frameworkElement->put_Width(pixelWidth)); + } + else + { + RETURN_IF_FAILED(frameworkElement->put_MaxWidth(pixelWidth)); + } + } + + if (pixelHeight) + { + if (imageStyle == ImageStyle_Person) + { + RETURN_IF_FAILED(frameworkElement->put_Height(pixelHeight)); + } + else + { + RETURN_IF_FAILED(frameworkElement->put_MaxHeight(pixelHeight)); + } + } + } + else + { + if (size == ABI::AdaptiveNamespace::ImageSize::Small || size == ABI::AdaptiveNamespace::ImageSize::Medium || + size == ABI::AdaptiveNamespace::ImageSize::Large) + { + UINT32 imageSize; + switch (size) + { + case ABI::AdaptiveNamespace::ImageSize::Small: + { + RETURN_IF_FAILED(sizeOptions->get_Small(&imageSize)); + break; + } + + case ABI::AdaptiveNamespace::ImageSize::Medium: + { + RETURN_IF_FAILED(sizeOptions->get_Medium(&imageSize)); + break; + } + + case ABI::AdaptiveNamespace::ImageSize::Large: + { + RETURN_IF_FAILED(sizeOptions->get_Large(&imageSize)); + + break; + } + default: + { + return E_UNEXPECTED; + } + } + + RETURN_IF_FAILED(frameworkElement->put_MaxWidth(imageSize)); + + // We don't want to set a max height on the person ellipse as ellipses do not understand preserving + // aspect ratio when constrained on both axes. + if (imageStyle != ImageStyle_Person) + { + RETURN_IF_FAILED(frameworkElement->put_MaxHeight(imageSize)); + } + } + } + + ABI::AdaptiveNamespace::HAlignment adaptiveHorizontalAlignment; + RETURN_IF_FAILED(adaptiveImage->get_HorizontalAlignment(&adaptiveHorizontalAlignment)); + + switch (adaptiveHorizontalAlignment) + { + case ABI::AdaptiveNamespace::HAlignment::Left: + RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); + break; + case ABI::AdaptiveNamespace::HAlignment::Right: + RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); + break; + case ABI::AdaptiveNamespace::HAlignment::Center: + RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); + break; + } + + RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Image", frameworkElement.Get())); + + ComPtr selectAction; + RETURN_IF_FAILED(adaptiveImage->get_SelectAction(&selectAction)); + + ComPtr imageAsUIElement; + RETURN_IF_FAILED(frameworkElement.As(&imageAsUIElement)); + + HString altText; + RETURN_IF_FAILED(adaptiveImage->get_AltText(altText.GetAddressOf())); + + ComPtr imageAsDependencyObject; + RETURN_IF_FAILED(imageAsUIElement.As(&imageAsDependencyObject)); + + ComPtr automationPropertiesStatics; + RETURN_IF_FAILED( + GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), + &automationPropertiesStatics)); + + RETURN_IF_FAILED(automationPropertiesStatics->SetName(imageAsDependencyObject.Get(), altText.Get())); + + XamlHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + imageAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + imageControl); + + return S_OK; + } + + template + void XamlBuilder::SetImageOnUIElement(_In_ ABI::Windows::Foundation::IUriRuntimeClass* imageUrl, + _In_ T* uiElement, + _In_opt_ IAdaptiveCardResourceResolvers* resolvers, + bool isAutoSize, + IInspectable* parentElement, + IInspectable* imageContainer, + bool isVisible, + _Out_ bool* mustHideElement, + ABI::Windows::UI::Xaml::Media::Stretch stretch) + { + *mustHideElement = true; + + // Get the image url scheme + HString schemeName; + THROW_IF_FAILED(imageUrl->get_SchemeName(schemeName.GetAddressOf())); + + // Get the resolver for the image + ComPtr resolver; + if (resolvers != nullptr) + { + THROW_IF_FAILED(resolvers->Get(schemeName.Get(), &resolver)); + // If we have a resolver + if (resolver != nullptr) + { + // Create a BitmapImage to hold the image data. We use BitmapImage in order to allow + // the tracker to subscribe to the ImageLoaded/Failed events + ComPtr bitmapImage = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); + + if (!m_enableXamlImageHandling && (m_listeners.size() != 0)) + { + m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); + } + + THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_None)); + ComPtr bitmapSource; + bitmapImage.As(&bitmapSource); + + // Create the arguments to pass to the resolver + ComPtr args; + THROW_IF_FAILED(MakeAndInitialize(&args, imageUrl)); + + // And call the resolver to get the image stream + ComPtr> getResourceStreamOperation; + THROW_IF_FAILED(resolver->GetResourceStreamAsync(args.Get(), &getResourceStreamOperation)); + + ComPtr strongImageControl(uiElement); + ComPtr strongThis(this); + THROW_IF_FAILED(getResourceStreamOperation->put_Completed( + Callback, IAsyncOperationCompletedHandler>>( + [strongThis, this, bitmapSource, strongImageControl, bitmapImage, stretch, isAutoSize, parentElement, imageContainer, isVisible]( + IAsyncOperation* operation, AsyncStatus status) -> HRESULT { + if (status == AsyncStatus::Completed) + { + // Get the random access stream + ComPtr randomAccessStream; + RETURN_IF_FAILED(operation->GetResults(&randomAccessStream)); + + if (randomAccessStream == nullptr) + { + m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); + return S_OK; + } + + RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); + + ComPtr imageSource; + RETURN_IF_FAILED(bitmapSource.As(&imageSource)); + + SetImageSource(strongImageControl.Get(), imageSource.Get(), stretch); + + // Here should be the auto resizing, at this time we already have the image and everything set + if (isAutoSize) + { + SetAutoSize(strongImageControl.Get(), parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */); + } + + return S_OK; + } + else + { + m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); + return S_OK; + } + }) + .Get())); + + return; + } + } + + INT32 isDataUriImage{}; + THROW_IF_FAILED(WindowsCompareStringOrdinal(schemeName.Get(), HStringReference(L"data").Get(), &isDataUriImage)); + if (isDataUriImage == 0) + { + // Decode base 64 string + HString dataPath; + THROW_IF_FAILED(imageUrl->get_Path(dataPath.GetAddressOf())); + + std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath.Get())); + std::vector decodedData = AdaptiveBase64Util::Decode(data); + + ComPtr bufferFactory; + THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + bufferFactory.GetAddressOf())); + + ComPtr buffer; + THROW_IF_FAILED(bufferFactory->Create(static_cast(decodedData.size()), buffer.GetAddressOf())); + + ComPtr<::Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess; + THROW_IF_FAILED(buffer.As(&bufferByteAccess)); + + BYTE* dataInternal{}; + THROW_IF_FAILED(bufferByteAccess->Buffer(&dataInternal)); + + memcpy_s(dataInternal, decodedData.size(), decodedData.data(), decodedData.size()); + + THROW_IF_FAILED(buffer->put_Length(static_cast(decodedData.size()))); + + ComPtr bitmapImage = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); + m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); + THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_IgnoreImageCache)); + ComPtr bitmapSource; + THROW_IF_FAILED(bitmapImage.As(&bitmapSource)); + + ComPtr randomAccessStream = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream)); + + ComPtr outputStream; + THROW_IF_FAILED(randomAccessStream.As(&outputStream)); + + ComPtr> bufferWriteOperation; + THROW_IF_FAILED(outputStream->WriteAsync(buffer.Get(), &bufferWriteOperation)); + + ComPtr strongImageControl(uiElement); + ComPtr strongThis(this); + THROW_IF_FAILED(bufferWriteOperation->put_Completed( + Callback, IAsyncOperationWithProgressCompletedHandler>>( + [strongThis, this, bitmapSource, randomAccessStream, strongImageControl, isAutoSize, parentElement, imageContainer, isVisible]( + IAsyncOperationWithProgress* /*operation*/, AsyncStatus /*status*/) -> HRESULT { + randomAccessStream->Seek(0); + RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); + + ComPtr imageSource; + RETURN_IF_FAILED(bitmapSource.As(&imageSource)); + + SetImageSource(strongImageControl.Get(), imageSource.Get()); + + if (isAutoSize) + { + SetAutoSize(strongImageControl.Get(), parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */); + } + + return S_OK; + }) + .Get())); + + m_writeAsyncOperations.push_back(bufferWriteOperation); + *mustHideElement = false; + return; + } + + // Otherwise, no resolver... + if ((m_enableXamlImageHandling) || (m_listeners.size() == 0)) + { + // If we've been explicitly told to let Xaml handle the image loading, or there are + // no listeners waiting on the image load callbacks, use Xaml to load the images + ComPtr bitmapImage = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); + THROW_IF_FAILED(bitmapImage->put_UriSource(imageUrl)); + + ComPtr bitmapImageSource; + THROW_IF_FAILED(bitmapImage.As(&bitmapImageSource)); + SetImageSource(uiElement, bitmapImageSource.Get(), stretch); + + if (isAutoSize) + { + SetAutoSize(uiElement, parentElement, imageContainer, isVisible, true /* imageFiresOpenEvent */); + } + } + else + { + PopulateImageFromUrlAsync(imageUrl, uiElement); + } + } + + template + void XamlBuilder::PopulateImageFromUrlAsync(_In_ IUriRuntimeClass* imageUrl, _In_ T* imageControl) + { + // Create the HttpClient to load the image stream + ComPtr httpBaseProtocolFilter = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_Web_Http_Filters_HttpBaseProtocolFilter)); + THROW_IF_FAILED(httpBaseProtocolFilter->put_AllowUI(false)); + ComPtr httpFilter; + THROW_IF_FAILED(httpBaseProtocolFilter.As(&httpFilter)); + ComPtr httpClient; + ComPtr httpClientFactory; + THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Web_Http_HttpClient).Get(), + httpClientFactory.ReleaseAndGetAddressOf())); + THROW_IF_FAILED(httpClientFactory->Create(httpFilter.Get(), httpClient.ReleaseAndGetAddressOf())); + + // Create a BitmapImage to hold the image data. We use BitmapImage in order to allow + // the tracker to subscribe to the ImageLoaded/Failed events + ComPtr bitmapImage = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); + m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); + THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_None)); + ComPtr bitmapSource; + bitmapImage.As(&bitmapSource); + ComPtr> getStreamOperation; + THROW_IF_FAILED(httpClient->GetInputStreamAsync(imageUrl, &getStreamOperation)); + + ComPtr strongImageControl(imageControl); + ComPtr strongThis(this); + THROW_IF_FAILED(getStreamOperation->put_Completed( + Callback, IAsyncOperationWithProgressCompletedHandler>>( + [strongThis, this, bitmapSource, strongImageControl, bitmapImage]( + IAsyncOperationWithProgress* operation, AsyncStatus status) -> HRESULT { + if (status == AsyncStatus::Completed) + { + // Load the image stream into an in memory random access stream, which is what + // SetSource needs + ComPtr imageStream; + RETURN_IF_FAILED(operation->GetResults(&imageStream)); + ComPtr randomAccessStream = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream)); + ComPtr outputStream; + RETURN_IF_FAILED(randomAccessStream.As(&outputStream)); + ComPtr> copyStreamOperation; + RETURN_IF_FAILED(m_randomAccessStreamStatics->CopyAsync(imageStream.Get(), outputStream.Get(), ©StreamOperation)); + + m_copyStreamOperations.push_back(copyStreamOperation); + return copyStreamOperation->put_Completed( + Callback, IAsyncOperationWithProgressCompletedHandler>>( + [strongThis, this, bitmapSource, randomAccessStream, strongImageControl]( + IAsyncOperationWithProgress* /*operation*/, AsyncStatus /*status*/) -> HRESULT { + randomAccessStream->Seek(0); + RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); + + ComPtr imageSource; + RETURN_IF_FAILED(bitmapSource.As(&imageSource)); + + SetImageSource(strongImageControl.Get(), imageSource.Get()); + return S_OK; + }) + .Get()); + } + else + { + m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); + return S_OK; + } + }) + .Get())); + m_getStreamOperations.push_back(getStreamOperation); + } + + template + void XamlBuilder::SetImageSource(_In_ T* destination, _In_ IImageSource* imageSource, ABI::Windows::UI::Xaml::Media::Stretch /*stretch*/) + { + THROW_IF_FAILED(destination->put_Source(imageSource)); + }; + + template<> + void XamlBuilder::SetImageSource(_In_ IEllipse* destination, + _In_ IImageSource* imageSource, + ABI::Windows::UI::Xaml::Media::Stretch stretch) + { + ComPtr imageBrush = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Media_ImageBrush)); + THROW_IF_FAILED(imageBrush->put_ImageSource(imageSource)); + + ComPtr tileBrush; + THROW_IF_FAILED(imageBrush.As(&tileBrush)); + THROW_IF_FAILED(tileBrush->put_Stretch(stretch)); + + ComPtr brush; + THROW_IF_FAILED(imageBrush.As(&brush)); + + ComPtr ellipseAsShape; + ComPtr ellipse(destination); + THROW_IF_FAILED(ellipse.As(&ellipseAsShape)); + + THROW_IF_FAILED(ellipseAsShape->put_Fill(brush.Get())); + }; + + template<> + void XamlBuilder::SetAutoSize(IEllipse* destination, IInspectable* parentElement, IInspectable* imageContainer, bool isVisible, bool imageFiresOpenEvent) + { + // Check if the image source fits in the parent container, if so, set the framework element's size to match the original image. + if (parentElement != nullptr && m_enableXamlImageHandling) + { + ComPtr ellipseShape(imageContainer); + ComPtr ellipseAsShape; + THROW_IF_FAILED(ellipseShape.As(&ellipseAsShape)); + + ComPtr ellipseBrush; + THROW_IF_FAILED(ellipseAsShape->get_Fill(&ellipseBrush)); + ComPtr brushAsImageBrush; + THROW_IF_FAILED(ellipseBrush.As(&brushAsImageBrush)); + + ComPtr ellipse(destination); + + ComPtr ellipseAsUIElement; + THROW_IF_FAILED(ellipse.As(&ellipseAsUIElement)); + + ComPtr ellipseAsFrameworkElement; + THROW_IF_FAILED(ellipse.As(&ellipseAsFrameworkElement)); + + ComPtr imageSource; + THROW_IF_FAILED(brushAsImageBrush->get_ImageSource(&imageSource)); + ComPtr imageSourceAsBitmap; + THROW_IF_FAILED(imageSource.As(&imageSourceAsBitmap)); + + // If the image hasn't loaded yet + if (imageFiresOpenEvent) + { + // Collapse the Ellipse while the image loads, so that resizing is not noticeable + THROW_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); + // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent + EventRegistrationToken eventToken; + ComPtr strongParentElement(parentElement); + THROW_IF_FAILED(brushAsImageBrush->add_ImageOpened( + Callback([ellipseAsUIElement, ellipseAsFrameworkElement, imageSourceAsBitmap, strongParentElement, isVisible]( + IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { + if (isVisible) + { + RETURN_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Visible)); + RETURN_IF_FAILED(XamlHelpers::SetAutoImageSize(ellipseAsFrameworkElement.Get(), + strongParentElement.Get(), + imageSourceAsBitmap.Get(), + isVisible)); + } + return S_OK; + }).Get(), + &eventToken)); + } + else + { + XamlHelpers::SetAutoImageSize(ellipseAsFrameworkElement.Get(), parentElement, imageSourceAsBitmap.Get(), isVisible); + } + } + } + + template + void XamlBuilder::SetAutoSize(T* destination, IInspectable* parentElement, IInspectable* /* imageContainer */, bool isVisible, bool imageFiresOpenEvent) + { + if (parentElement != nullptr && m_enableXamlImageHandling) + { + ComPtr xamlImage(destination); + ComPtr imageAsFrameworkElement; + THROW_IF_FAILED(xamlImage.As(&imageAsFrameworkElement)); + ComPtr imageSource; + THROW_IF_FAILED(xamlImage->get_Source(&imageSource)); + ComPtr imageSourceAsBitmap; + THROW_IF_FAILED(imageSource.As(&imageSourceAsBitmap)); + + ComPtr imageAsUIElement; + THROW_IF_FAILED(xamlImage.As(&imageAsUIElement)); + + // If the image hasn't loaded yet + if (imageFiresOpenEvent) + { + // Collapse the Image control while the image loads, so that resizing is not noticeable + THROW_IF_FAILED(imageAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); + + // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent + ComPtr strongParentElement(parentElement); + EventRegistrationToken eventToken; + THROW_IF_FAILED(xamlImage->add_ImageOpened( + Callback([imageAsFrameworkElement, strongParentElement, imageSourceAsBitmap, isVisible]( + IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + return XamlHelpers::SetAutoImageSize(imageAsFrameworkElement.Get(), + strongParentElement.Get(), + imageSourceAsBitmap.Get(), + isVisible); + }).Get(), + &eventToken)); + } + else + { + XamlHelpers::SetAutoImageSize(imageAsFrameworkElement.Get(), parentElement, imageSourceAsBitmap.Get(), isVisible); + } + } + } } diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.h b/source/uwp/Renderer/lib/AdaptiveImageRenderer.h index e2f16dc7cc..f8219fb773 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Image.h" -#include "XamlBuilder.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveImageSet.cpp b/source/uwp/Renderer/lib/AdaptiveImageSet.cpp index 5b83274408..b3617ae48d 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSet.cpp @@ -1,11 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveImageSet.h" -#include "Util.h" -#include "Vector.h" -#include +#include "AdaptiveImageSet.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveImageSet.h b/source/uwp/Renderer/lib/AdaptiveImageSet.h index f59618c5dc..224dffb8f6 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSet.h +++ b/source/uwp/Renderer/lib/AdaptiveImageSet.h @@ -2,11 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ImageSet.h" -#include -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp index 51ddb1b7c0..dd422d7ae9 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveImageSetConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.h b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.h index 86e4cc7fce..708e3d8d17 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveImageSetConfig diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp index 3287b33269..cd501b5930 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveImageSet.h" #include "AdaptiveImageSetRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "AdaptiveRenderArgs.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +23,86 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveImageSetRenderer::Render(_In_ IAdaptiveCardElement* cardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + HRESULT AdaptiveImageSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ IUIElement** imageSetControl) noexcept try { - return XamlBuilder::BuildImageSet(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveImageSet; + RETURN_IF_FAILED(cardElement.As(&adaptiveImageSet)); + + ComPtr xamlGrid = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_VariableSizedWrapGrid)); + + RETURN_IF_FAILED(xamlGrid->put_Orientation(Orientation_Horizontal)); + + ComPtr> images; + RETURN_IF_FAILED(adaptiveImageSet->get_Images(&images)); + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr imageSetConfig; + RETURN_IF_FAILED(hostConfig->get_ImageSet(&imageSetConfig)); + + ABI::AdaptiveNamespace::ImageSize imageSize; + RETURN_IF_FAILED(adaptiveImageSet->get_ImageSize(&imageSize)); + + if (imageSize == ABI::AdaptiveNamespace::ImageSize::None) + { + RETURN_IF_FAILED(imageSetConfig->get_ImageSize(&imageSize)); + } + + ComPtr elementRenderers; + RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + ComPtr imageRenderer; + RETURN_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &imageRenderer)); + if (imageRenderer != nullptr) + { + ABI::AdaptiveNamespace::ContainerStyle containerStyle; + RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&containerStyle)); + + ComPtr childRenderArgs; + RETURN_IF_FAILED(MakeAndInitialize(&childRenderArgs, containerStyle, xamlGrid.Get(), renderArgs)); + + XamlHelpers::IterateOverVector( + images.Get(), + [imageSize, xamlGrid, renderContext, childRenderArgs, imageRenderer, imageSetConfig](IAdaptiveImage* adaptiveImage) { + ComPtr uiImage; + ComPtr localAdaptiveImage(adaptiveImage); + RETURN_IF_FAILED(localAdaptiveImage->put_Size(imageSize)); + + ComPtr adaptiveElementImage; + localAdaptiveImage.As(&adaptiveElementImage); + RETURN_IF_FAILED(imageRenderer->Render(adaptiveElementImage.Get(), renderContext, childRenderArgs.Get(), &uiImage)); + + ComPtr imageAsFrameworkElement; + RETURN_IF_FAILED(uiImage.As(&imageAsFrameworkElement)); + + UINT32 maxImageHeight; + RETURN_IF_FAILED(imageSetConfig->get_MaxImageHeight(&maxImageHeight)); + RETURN_IF_FAILED(imageAsFrameworkElement->put_MaxHeight(maxImageHeight)); + + ComPtr gridAsPanel; + RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); + + XamlHelpers::AppendXamlElementToPanel(uiImage.Get(), gridAsPanel.Get()); + return S_OK; + }); + } + else + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, + HStringReference(L"No renderer found for type: Image").Get()); + *imageSetControl = nullptr; + return S_OK; + } + + ComPtr imageSetAsFrameworkElement; + RETURN_IF_FAILED(xamlGrid.As(&imageSetAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.ImageSet", imageSetAsFrameworkElement.Get())); + + return xamlGrid.CopyTo(imageSetControl); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.h b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.h index be46fd96e3..61c10aee56 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ImageSet.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp index 6185875f15..cf7af8889d 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveImageSizesConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.h b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.h index 82d5c747d3..39be92dbc6 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveImageSizesConfig diff --git a/source/uwp/Renderer/lib/AdaptiveInputElement.cpp b/source/uwp/Renderer/lib/AdaptiveInputElement.cpp index a2c7f9d19e..f01fc4eec8 100644 --- a/source/uwp/Renderer/lib/AdaptiveInputElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveInputElement.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveInputElement.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveInputElement.h b/source/uwp/Renderer/lib/AdaptiveInputElement.h index 35eea6bf92..674d687cca 100644 --- a/source/uwp/Renderer/lib/AdaptiveInputElement.h +++ b/source/uwp/Renderer/lib/AdaptiveInputElement.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "BaseInputElement.h" -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp b/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp index 0c41d43b83..c8fe337705 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "Util.h" + #include "AdaptiveMediaConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveMediaConfig.h b/source/uwp/Renderer/lib/AdaptiveMediaConfig.h index 890de2e390..82fc053c59 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveMediaConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveMediaConfig diff --git a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp index f85185d0ce..c79c137bd3 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp @@ -4,11 +4,18 @@ #include "AdaptiveMedia.h" #include "AdaptiveMediaRenderer.h" -#include "XamlBuilder.h" #include "AdaptiveElementParserRegistration.h" +#include "MediaHelpers.h" using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; +using namespace ABI::Windows::UI::Xaml::Media; namespace AdaptiveNamespace { @@ -18,12 +25,146 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveMediaRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveMediaRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** mediaControl) noexcept try { - return XamlBuilder::BuildMedia(cardElement, renderContext, renderArgs, result); + ComPtr localCardElement{adaptiveCardElement}; + ComPtr adaptiveMedia; + RETURN_IF_FAILED(localCardElement.As(&adaptiveMedia)); + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + // Get the poster image + ComPtr posterImage; + GetMediaPosterAsImage(renderContext, renderArgs, adaptiveMedia.Get(), &posterImage); + + // If the host doesn't support interactivity we're done here, just return the poster image + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Media was present in card, but interactivity is not supported").Get()); + + if (posterImage != nullptr) + { + RETURN_IF_FAILED(posterImage.CopyTo(mediaControl)); + } + + return S_OK; + } + + // Put the poster image in a container with a play button + ComPtr posterContainer; + CreatePosterContainerWithPlayButton(posterImage.Get(), renderContext, renderArgs, &posterContainer); + + ComPtr touchTargetUIElement; + XamlHelpers::WrapInTouchTarget(adaptiveCardElement, posterContainer.Get(), nullptr, renderContext, true, L"Adaptive.SelectAction", &touchTargetUIElement); + + // Create a panel to hold the poster and the media element + ComPtr mediaStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + ComPtr mediaPanel; + RETURN_IF_FAILED(mediaStackPanel.As(&mediaPanel)); + + XamlHelpers::AppendXamlElementToPanel(touchTargetUIElement.Get(), mediaPanel.Get()); + + // Check if this host allows inline playback + ComPtr mediaConfig; + RETURN_IF_FAILED(hostConfig->get_Media(&mediaConfig)); + + boolean allowInlinePlayback; + RETURN_IF_FAILED(mediaConfig->get_AllowInlinePlayback(&allowInlinePlayback)); + + ComPtr mediaInvoker; + RETURN_IF_FAILED(renderContext->get_MediaEventInvoker(&mediaInvoker)); + + HString mimeType; + ComPtr mediaElement; + ComPtr mediaSourceUrl; + if (allowInlinePlayback) + { + // Create a media element and set it's source + mediaElement = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_MediaElement)); + + GetMediaSource(hostConfig.Get(), adaptiveMedia.Get(), mediaSourceUrl.GetAddressOf(), mimeType.GetAddressOf()); + + if (mediaSourceUrl == nullptr) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::UnsupportedMediaType, + HStringReference(L"Unsupported media element dropped").Get()); + return S_OK; + } + + // Configure Auto Play and Controls + RETURN_IF_FAILED(mediaElement->put_AutoPlay(false)); + + ComPtr mediaElement2; + RETURN_IF_FAILED(mediaElement.As(&mediaElement2)); + RETURN_IF_FAILED(mediaElement2->put_AreTransportControlsEnabled(true)); + ComPtr mediaElement3; + RETURN_IF_FAILED(mediaElement.As(&mediaElement3)); + ComPtr mediaTransportControl; + RETURN_IF_FAILED(mediaElement3->get_TransportControls(&mediaTransportControl)); + RETURN_IF_FAILED(mediaTransportControl->put_IsCompact(true)); + RETURN_IF_FAILED(mediaTransportControl->put_IsZoomButtonVisible(false)); + + ComPtr mediaUIElement; + RETURN_IF_FAILED(mediaElement.As(&mediaUIElement)); + + if (posterImage != nullptr) + { + // Set the poster on the media element + ComPtr posterImageSource; + RETURN_IF_FAILED(posterImage->get_Source(&posterImageSource)); + RETURN_IF_FAILED(mediaElement->put_PosterSource(posterImageSource.Get())); + } + + // Make the media element collapsed until the user clicks + RETURN_IF_FAILED(mediaUIElement->put_Visibility(Visibility_Collapsed)); + + XamlHelpers::AppendXamlElementToPanel(mediaElement.Get(), mediaPanel.Get()); + } + + ComPtr mediaPanelAsUIElement; + RETURN_IF_FAILED(mediaPanel.As(&mediaPanelAsUIElement)); + + ComPtr touchTargetAsButtonBase; + RETURN_IF_FAILED(touchTargetUIElement.As(&touchTargetAsButtonBase)); + + // Take a reference to the mime type string for the lambda + HSTRING lambdaMimeType; + WindowsDuplicateString(mimeType.Get(), &lambdaMimeType); + ComPtr lambdaRenderContext{renderContext}; + + EventRegistrationToken clickToken; + RETURN_IF_FAILED(touchTargetAsButtonBase->add_Click( + Callback([touchTargetUIElement, lambdaRenderContext, adaptiveMedia, mediaElement, mediaSourceUrl, lambdaMimeType, mediaInvoker]( + IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { + // Take ownership of the passed in HSTRING + HString localMimeType; + localMimeType.Attach(lambdaMimeType); + + // Turn off the button to prevent extra clicks + ComPtr buttonAsControl; + touchTargetUIElement.As(&buttonAsControl); + RETURN_IF_FAILED(buttonAsControl->put_IsEnabled(false)); + + // Handle the click + return HandleMediaClick(lambdaRenderContext.Get(), + adaptiveMedia.Get(), + mediaElement.Get(), + touchTargetUIElement.Get(), + mediaSourceUrl.Get(), + lambdaMimeType, + mediaInvoker.Get()); + }).Get(), + &clickToken)); + + RETURN_IF_FAILED(mediaPanelAsUIElement.CopyTo(mediaControl)); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp b/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp index 0634cf9f95..2cea66655f 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveNumberInput.h" -#include "Util.h" -#include +#include "AdaptiveNumberInput.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInput.h b/source/uwp/Renderer/lib/AdaptiveNumberInput.h index 81e3528fe2..1e4e63c679 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInput.h +++ b/source/uwp/Renderer/lib/AdaptiveNumberInput.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "NumberInput.h" #include "AdaptiveInputElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp index cd3488fcec..351be69dcc 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveNumberInput.h" #include "AdaptiveNumberInputRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Input; namespace AdaptiveNamespace { @@ -22,12 +23,64 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveNumberInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveNumberInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _In_ IAdaptiveRenderArgs* /*renderArgs*/, + _COM_Outptr_ IUIElement** numberInputControl) noexcept try { - return XamlBuilder::BuildNumberInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Number input was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveNumberInput; + RETURN_IF_FAILED(cardElement.As(&adaptiveNumberInput)); + + ComPtr textBox = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBox)); + + ComPtr inputScopeName = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScopeName)); + RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_Number)); + + ComPtr inputScope = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScope)); + ComPtr> names; + RETURN_IF_FAILED(inputScope->get_Names(names.GetAddressOf())); + RETURN_IF_FAILED(names->Append(inputScopeName.Get())); + + RETURN_IF_FAILED(textBox->put_InputScope(inputScope.Get())); + + INT32 value; + RETURN_IF_FAILED(adaptiveNumberInput->get_Value(&value)); + + std::wstring stringValue = std::to_wstring(value); + RETURN_IF_FAILED(textBox->put_Text(HStringReference(stringValue.c_str()).Get())); + + ComPtr textBox2; + RETURN_IF_FAILED(textBox.As(&textBox2)); + + HString placeHolderText; + RETURN_IF_FAILED(adaptiveNumberInput->get_Placeholder(placeHolderText.GetAddressOf())); + RETURN_IF_FAILED(textBox2->put_PlaceholderText(placeHolderText.Get())); + + ComPtr frameworkElement; + RETURN_IF_FAILED(textBox.As(&frameworkElement)); + RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Number", frameworkElement.Get())); + + // TODO: Handle max and min? + RETURN_IF_FAILED(textBox.CopyTo(numberInputControl)); + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *numberInputControl); + + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.h index 760aa56c16..01c8ecb1e1 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "NumberInput.h" - namespace AdaptiveNamespace { class AdaptiveNumberInputRenderer diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp index a64b810787..ae18e7b5b7 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveOpenUrlAction.h" -#include "Util.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h index 17f5b6c961..be8503aa6a 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "OpenUrlAction.h" #include "AdaptiveActionElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp index 4d416b9031..f6cf6ae869 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp @@ -6,7 +6,7 @@ #include "AdaptiveOpenUrlActionRenderer.h" #include "Util.h" #include "AdaptiveElementParserRegistration.h" -#include "XamlBuilder.h" +#include "ActionHelpers.h" using namespace ABI::AdaptiveNamespace; using namespace Microsoft::WRL; @@ -24,7 +24,7 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try { - return XamlBuilder::BuildAction(action, renderContext, renderArgs, result); + return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp index 27d2960290..f73ce9deee 100644 --- a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveRemoteResourceInformation.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.h b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.h index 3edf81f82d..05d28a7734 100644 --- a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.h +++ b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TextBlock.h" -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp index fc67f51978..814aabf5d9 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp @@ -1,11 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveRichTextBlock.h" -#include "Util.h" #include "DateTimeParser.h" -#include "Vector.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.h b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.h index f204d0fa95..c7ad67dc9b 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.h +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "RichTextBlock.h" -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp index 6535c46a16..9f0f737346 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp @@ -5,14 +5,17 @@ #include "AdaptiveRichTextBlock.h" #include "AdaptiveRichTextBlockRenderer.h" #include "AdaptiveRenderContext.h" -#include "Util.h" -#include "XamlBuilder.h" #include "AdaptiveElementParserRegistration.h" +#include "TextHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Documents; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -27,8 +30,141 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try { - XamlBuilder::BuildRichTextBlock(cardElement, renderContext, renderArgs, result); - return S_OK; + // Create the top level rich text block and set it's properties + ComPtr xamlRichTextBlock = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RichTextBlock)); + + ComPtr localAdaptiveCardElement(cardElement); + ComPtr adaptiveRichTextBlock; + RETURN_IF_FAILED(localAdaptiveCardElement.As(&adaptiveRichTextBlock)); + + // Set the horizontal Alingment + RETURN_IF_FAILED(SetHorizontalAlignment(adaptiveRichTextBlock.Get(), xamlRichTextBlock.Get())); + + // Get the highlighters + ComPtr xamlRichTextBlock5; + RETURN_IF_FAILED(xamlRichTextBlock.As(&xamlRichTextBlock5)); + + ComPtr> textHighlighters; + RETURN_IF_FAILED(xamlRichTextBlock5->get_TextHighlighters(&textHighlighters)); + + // Add a paragraph for the inlines + ComPtr> xamlBlocks; + RETURN_IF_FAILED(xamlRichTextBlock->get_Blocks(&xamlBlocks)); + + ComPtr xamlParagraph = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Documents_Paragraph)); + + ComPtr paragraphAsBlock; + RETURN_IF_FAILED(xamlParagraph.As(¶graphAsBlock)); + RETURN_IF_FAILED(xamlBlocks->Append(paragraphAsBlock.Get())); + + // Add the Inlines + ComPtr> xamlInlines; + RETURN_IF_FAILED(xamlParagraph->get_Inlines(&xamlInlines)); + + ComPtr> adaptiveInlines; + RETURN_IF_FAILED(adaptiveRichTextBlock->get_Inlines(&adaptiveInlines)); + + UINT currentOffset = 0; + XamlHelpers::IterateOverVector(adaptiveInlines.Get(), [&](IAdaptiveInline* adaptiveInline) { + // We only support TextRun inlines for now + ComPtr localInline(adaptiveInline); + ComPtr adaptiveTextRun; + RETURN_IF_FAILED(localInline.As(&adaptiveTextRun)); + + ComPtr selectAction; + RETURN_IF_FAILED(adaptiveTextRun->get_SelectAction(&selectAction)); + + ComPtr adaptiveTextElement; + RETURN_IF_FAILED(localInline.As(&adaptiveTextElement)); + + HString text; + RETURN_IF_FAILED(adaptiveTextElement->get_Text(text.GetAddressOf())); + + boolean isStrikethrough{false}; + RETURN_IF_FAILED(adaptiveTextRun->get_Strikethrough(&isStrikethrough)); + + boolean isItalic{false}; + RETURN_IF_FAILED(adaptiveTextRun->get_Italic(&isItalic)); + + boolean isUnderline{}; + RETURN_IF_FAILED(adaptiveTextRun->get_Underline(&isUnderline)); + + UINT inlineLength; + if (selectAction != nullptr) + { + // If there's a select action, create a hyperlink that triggers the action + ComPtr hyperlink = + XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Documents_Hyperlink)); + + ComPtr actionInvoker; + renderContext->get_ActionInvoker(&actionInvoker); + + EventRegistrationToken clickToken; + RETURN_IF_FAILED( + hyperlink->add_Click(Callback>( + [selectAction, actionInvoker](IInspectable*, IHyperlinkClickEventArgs*) -> HRESULT { + return actionInvoker->SendActionEvent(selectAction.Get()); + }) + .Get(), + &clickToken)); + + // Add the run text to the hyperlink's inlines + ComPtr hyperlinkAsSpan; + RETURN_IF_FAILED(hyperlink.As(&hyperlinkAsSpan)); + + ComPtr> hyperlinkInlines; + RETURN_IF_FAILED(hyperlinkAsSpan->get_Inlines(hyperlinkInlines.GetAddressOf())); + RETURN_IF_FAILED(AddSingleTextInline(adaptiveTextElement.Get(), + renderContext, + renderArgs, + text.Get(), + TextRunStyleParameters(isStrikethrough, isItalic, isUnderline, true), + hyperlinkInlines.Get(), + &inlineLength)); + + ComPtr hyperlinkAsInline; + RETURN_IF_FAILED(hyperlink.As(&hyperlinkAsInline)); + + // Add the hyperlink to the paragraph's inlines + RETURN_IF_FAILED(xamlInlines->Append(hyperlinkAsInline.Get())); + } + else + { + // Add the text to the paragraph's inlines + RETURN_IF_FAILED(AddSingleTextInline(adaptiveTextElement.Get(), + renderContext, + renderArgs, + text.Get(), + TextRunStyleParameters(isStrikethrough, isItalic, isUnderline, false), + xamlInlines.Get(), + &inlineLength)); + } + + boolean highlight; + RETURN_IF_FAILED(adaptiveTextRun->get_Highlight(&highlight)); + + if (highlight) + { + ComPtr textHighlighter; + RETURN_IF_FAILED(GetHighlighter(adaptiveTextElement.Get(), renderContext, renderArgs, &textHighlighter)); + + ComPtr> ranges; + RETURN_IF_FAILED(textHighlighter->get_Ranges(&ranges)); + + TextRange textRange = {(INT32)currentOffset, (INT32)inlineLength}; + RETURN_IF_FAILED(ranges->Append(textRange)); + + RETURN_IF_FAILED(textHighlighters->Append(textHighlighter.Get())); + } + + currentOffset += inlineLength; + return S_OK; + }); + + return xamlRichTextBlock.CopyTo(result); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.h b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.h index f694d16173..027a9bd3a7 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "RichTextBlock.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveSeparator.cpp b/source/uwp/Renderer/lib/AdaptiveSeparator.cpp index f1ecd14f2f..bb5ff0f359 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparator.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSeparator.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveSeparator.h" -#include "Util.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveSeparator.h b/source/uwp/Renderer/lib/AdaptiveSeparator.h index a6a00cc3f2..e62b9cb463 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparator.h +++ b/source/uwp/Renderer/lib/AdaptiveSeparator.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "Separator.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp index a558c063b1..2a6a5f3d85 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveSeparatorConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.h b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.h index a7281976f5..45bee70cdf 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveSeparatorConfig diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp index cf43706bc8..50877b81e1 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveCard.h" #include "AdaptiveShowCardAction.h" -#include "Util.h" using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardAction.h b/source/uwp/Renderer/lib/AdaptiveShowCardAction.h index 171a802958..314891f33c 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardAction.h +++ b/source/uwp/Renderer/lib/AdaptiveShowCardAction.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ShowCardAction.h" #include "AdaptiveActionElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp index d902de6f6c..31a0c9bf10 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "Util.h" + #include "AdaptiveShowCardActionConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.h b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.h index f0a55b08ae..bd5c84cad5 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveShowCardActionConfig diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp index b7806c633e..ca725d0286 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp @@ -4,12 +4,14 @@ #include "AdaptiveShowCardAction.h" #include "AdaptiveShowCardActionRenderer.h" -#include "Util.h" #include "AdaptiveElementParserRegistration.h" -#include "XamlBuilder.h" +#include "ActionHelpers.h" -using namespace ABI::AdaptiveNamespace; using namespace Microsoft::WRL; +using namespace ABI::AdaptiveNamespace; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -24,7 +26,7 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try { - return XamlBuilder::BuildAction(action, renderContext, renderArgs, result); + return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } CATCH_RETURN; @@ -39,4 +41,69 @@ namespace AdaptiveNamespace jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); } CATCH_RETURN; + + HRESULT AdaptiveShowCardActionRenderer::BuildShowCard(_In_ IAdaptiveCard* showCard, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + bool isBottomActionBar, + _Outptr_ IUIElement** uiShowCard) noexcept try + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(&actionsConfig)); + + ComPtr showCardActionConfig; + RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); + + ABI::AdaptiveNamespace::ContainerStyle showCardConfigStyle; + RETURN_IF_FAILED(showCardActionConfig->get_Style(&showCardConfigStyle)); + + boolean wasInShowCard; + RETURN_IF_FAILED(renderArgs->get_IsInShowCard(&wasInShowCard)); + RETURN_IF_FAILED(renderArgs->put_IsInShowCard(true)); + + ComPtr localUiShowCard; + RETURN_IF_FAILED(XamlBuilder::BuildXamlTreeFromAdaptiveCard(showCard, localUiShowCard.GetAddressOf(), renderContext, nullptr, showCardConfigStyle)); + + RETURN_IF_FAILED(renderArgs->put_IsInShowCard(wasInShowCard)); + + ComPtr showCardGrid; + RETURN_IF_FAILED(localUiShowCard.As(&showCardGrid)); + + // Set the padding + ComPtr spacingConfig; + RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + + UINT32 padding; + RETURN_IF_FAILED(spacingConfig->get_Padding(&padding)); + + ABI::AdaptiveNamespace::ActionMode showCardActionMode; + RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); + + // Set the top margin + ComPtr showCardFrameworkElement; + RETURN_IF_FAILED(localUiShowCard.As(&showCardFrameworkElement)); + + UINT32 inlineTopMargin; + RETURN_IF_FAILED(showCardActionConfig->get_InlineTopMargin(&inlineTopMargin)); + + double sideMargin = (double)padding * -1; + double topMargin = isBottomActionBar ? inlineTopMargin + padding : inlineTopMargin; + double bottomMargin = isBottomActionBar ? (double)padding * -1 : 0; + + Thickness margin = {sideMargin, topMargin, sideMargin, bottomMargin}; + RETURN_IF_FAILED(showCardFrameworkElement->put_Margin(margin)); + + ComPtr showCardUIElement; + RETURN_IF_FAILED(localUiShowCard.As(&showCardUIElement)); + + // Set the visibility as Collapsed until the action is triggered + RETURN_IF_FAILED(showCardUIElement->put_Visibility(Visibility_Collapsed)); + + *uiShowCard = showCardUIElement.Detach(); + return S_OK; + } + CATCH_RETURN; } diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.h b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.h index cf33f14d7c..f111d2a943 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.h @@ -26,6 +26,12 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept override; + + static HRESULT BuildShowCard(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* showCard, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + bool isBottomActionBar, + _Outptr_ ABI::Windows::UI::Xaml::IUIElement** uiShowCard) noexcept; }; ActivatableClass(AdaptiveShowCardActionRenderer); diff --git a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp index 9ad07f2b99..c1273a523b 100644 --- a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveSpacingConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.h b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.h index 953640e0c1..9d014f7a75 100644 --- a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveSpacingConfig diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp index 87940b3538..3a9756d850 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveSubmitAction.h" -#include "Util.h" using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h index 683ef0b7bc..ae4a2dcb53 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "SubmitAction.h" #include "AdaptiveActionElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp index 54c341ed59..163051e28f 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp @@ -4,9 +4,8 @@ #include "AdaptiveSubmitAction.h" #include "AdaptiveSubmitActionRenderer.h" -#include "Util.h" #include "AdaptiveElementParserRegistration.h" -#include "XamlBuilder.h" +#include "ActionHelpers.h" using namespace ABI::AdaptiveNamespace; using namespace Microsoft::WRL; @@ -24,7 +23,7 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try { - return XamlBuilder::BuildAction(action, renderContext, renderArgs, result); + return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp b/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp index 9670256b04..9f190fdf8e 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp @@ -1,10 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveTextBlock.h" -#include "Util.h" #include "DateTimeParser.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlock.h b/source/uwp/Renderer/lib/AdaptiveTextBlock.h index 6ed5d5a53d..d1ddec66bb 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlock.h +++ b/source/uwp/Renderer/lib/AdaptiveTextBlock.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TextBlock.h" -#include "AdaptiveCardElement.h" #include "AdaptiveTextElement.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp index 0ce9cca3ac..0d5c434992 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp @@ -5,14 +5,16 @@ #include "AdaptiveTextBlock.h" #include "AdaptiveTextBlockRenderer.h" #include "AdaptiveRenderContext.h" -#include "Util.h" -#include "XamlBuilder.h" #include "AdaptiveElementParserRegistration.h" +#include "TextHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +24,40 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveTextBlockRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveTextBlockRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** textBlockControl) noexcept try { - return XamlBuilder::BuildTextBlock(cardElement, renderContext, renderArgs, result); + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveTextBlock; + RETURN_IF_FAILED(cardElement.As(&adaptiveTextBlock)); + + ComPtr xamlTextBlock = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); + + ComPtr adaptiveTextElement; + RETURN_IF_FAILED(adaptiveTextBlock.As(&adaptiveTextElement)); + + RETURN_IF_FAILED(StyleXamlTextBlockProperties(adaptiveTextBlock.Get(), renderContext, renderArgs, xamlTextBlock.Get())); + + ComPtr> inlines; + RETURN_IF_FAILED(xamlTextBlock->get_Inlines(&inlines)); + + RETURN_IF_FAILED(SetXamlInlines(adaptiveTextElement.Get(), renderContext, renderArgs, false, inlines.Get())); + + // Ensure left edge of text is consistent regardless of font size, so both small and large fonts + // are flush on the left edge of the card by enabling TrimSideBearings + ComPtr xamlTextBlock2; + RETURN_IF_FAILED(xamlTextBlock.As(&xamlTextBlock2)); + RETURN_IF_FAILED(xamlTextBlock2->put_OpticalMarginAlignment(OpticalMarginAlignment_TrimSideBearings)); + + ComPtr frameworkElement; + RETURN_IF_FAILED(xamlTextBlock.As(&frameworkElement)); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.TextBlock", frameworkElement.Get())); + + return xamlTextBlock.CopyTo(textBlockControl); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.h b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.h index 58a4cb67b3..80e07aa00f 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "TextBlock.h" - namespace AdaptiveNamespace { class AdaptiveTextBlockRenderer diff --git a/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp b/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp index c542a978ba..b6e5335ade 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "Util.h" + #include "AdaptiveTextConfig.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveTextConfig.h b/source/uwp/Renderer/lib/AdaptiveTextConfig.h index eddb5b3cd8..0a58e6686e 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextConfig.h +++ b/source/uwp/Renderer/lib/AdaptiveTextConfig.h @@ -2,10 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" -#include "HostConfig.h" - namespace AdaptiveNamespace { class AdaptiveTextConfig diff --git a/source/uwp/Renderer/lib/AdaptiveTextElement.cpp b/source/uwp/Renderer/lib/AdaptiveTextElement.cpp index 10afcfdbbc..8d5af88f4f 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextElement.cpp @@ -1,10 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveTextElement.h" -#include "Util.h" #include "DateTimeParser.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveTextElement.h b/source/uwp/Renderer/lib/AdaptiveTextElement.h index 90d35fbce7..bd387e5f92 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextElement.h +++ b/source/uwp/Renderer/lib/AdaptiveTextElement.h @@ -2,9 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" - namespace AdaptiveNamespace { class DECLSPEC_UUID("4BC6640A-8FBE-4DE0-81FD-119BC10877F1") AdaptiveTextElement : public IUnknown diff --git a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp index c519f41486..dfa21ea7c9 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveTextInput.h" -#include "Util.h" -#include +#include "AdaptiveTextInput.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveTextInput.h b/source/uwp/Renderer/lib/AdaptiveTextInput.h index 94043b088a..1f934b7c5a 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInput.h +++ b/source/uwp/Renderer/lib/AdaptiveTextInput.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TextInput.h" #include "AdaptiveInputElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp index 603d89841b..73a53a85e6 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp @@ -5,14 +5,16 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveTextInput.h" #include "AdaptiveTextInputRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" +#include "ActionHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Input; namespace AdaptiveNamespace { @@ -22,12 +24,109 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveTextInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveTextInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ IUIElement** textInputControl) noexcept try { - return XamlBuilder::BuildTextInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Text Input was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveTextInput; + RETURN_IF_FAILED(cardElement.As(&adaptiveTextInput)); + + ComPtr textBox = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBox)); + + boolean isMultiLine; + RETURN_IF_FAILED(adaptiveTextInput->get_IsMultiline(&isMultiLine)); + RETURN_IF_FAILED(textBox->put_AcceptsReturn(isMultiLine)); + + HString textValue; + RETURN_IF_FAILED(adaptiveTextInput->get_Value(textValue.GetAddressOf())); + RETURN_IF_FAILED(textBox->put_Text(textValue.Get())); + + UINT32 maxLength; + RETURN_IF_FAILED(adaptiveTextInput->get_MaxLength(&maxLength)); + RETURN_IF_FAILED(textBox->put_MaxLength(maxLength)); + + ComPtr textBox2; + RETURN_IF_FAILED(textBox.As(&textBox2)); + + HString placeHolderText; + RETURN_IF_FAILED(adaptiveTextInput->get_Placeholder(placeHolderText.GetAddressOf())); + RETURN_IF_FAILED(textBox2->put_PlaceholderText(placeHolderText.Get())); + + ABI::AdaptiveNamespace::TextInputStyle textInputStyle; + RETURN_IF_FAILED(adaptiveTextInput->get_TextInputStyle(&textInputStyle)); + + ComPtr inputScopeName = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScopeName)); + switch (textInputStyle) + { + case ABI::AdaptiveNamespace::TextInputStyle::Email: + RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_EmailSmtpAddress)); + break; + + case ABI::AdaptiveNamespace::TextInputStyle::Tel: + RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_TelephoneNumber)); + break; + + case ABI::AdaptiveNamespace::TextInputStyle::Url: + RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_Url)); + break; + } + + ComPtr inputScope = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScope)); + ComPtr> names; + RETURN_IF_FAILED(inputScope->get_Names(names.GetAddressOf())); + RETURN_IF_FAILED(names->Append(inputScopeName.Get())); + + RETURN_IF_FAILED(textBox->put_InputScope(inputScope.Get())); + + ComPtr textBoxAsUIElement; + textBox.As(&textBoxAsUIElement); + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, textBoxAsUIElement.Get()); + + ComPtr inlineAction; + RETURN_IF_FAILED(adaptiveTextInput->get_InlineAction(&inlineAction)); + + ComPtr textBoxAsFrameworkElement; + RETURN_IF_FAILED(textBox.As(&textBoxAsFrameworkElement)); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Text", textBoxAsFrameworkElement.Get())); + + if (inlineAction != nullptr) + { + ComPtr textBoxWithInlineAction; + ActionHelpers::HandleInlineAction(renderContext, renderArgs, textBox.Get(), inlineAction.Get(), &textBoxWithInlineAction); + if (!isMultiLine) + { + RETURN_IF_FAILED(textBoxWithInlineAction.As(&textBoxAsFrameworkElement)); + RETURN_IF_FAILED(textBoxAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + } + + RETURN_IF_FAILED(textBoxWithInlineAction.CopyTo(textInputControl)); + } + else + { + if (!isMultiLine) + { + RETURN_IF_FAILED(textBoxAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + } + + RETURN_IF_FAILED(textBox.CopyTo(textInputControl)); + } + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.h index 3ff97a3c3a..521d60b1a4 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TextInput.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveTextRun.cpp b/source/uwp/Renderer/lib/AdaptiveTextRun.cpp index d168a394e5..d38b640828 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextRun.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextRun.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveTextRun.h" -#include "Util.h" -#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveTextRun.h b/source/uwp/Renderer/lib/AdaptiveTextRun.h index b60953de9a..206e4f0cac 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextRun.h +++ b/source/uwp/Renderer/lib/AdaptiveTextRun.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TextRun.h" #include "AdaptiveTextElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp b/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp index 0fb046e4d2..0d778679ed 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveTimeInput.h" -#include "Util.h" -#include +#include "AdaptiveTimeInput.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInput.h b/source/uwp/Renderer/lib/AdaptiveTimeInput.h index 6d575d6d20..b90ea43fbf 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInput.h +++ b/source/uwp/Renderer/lib/AdaptiveTimeInput.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TimeInput.h" #include "AdaptiveInputElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp index 901593b979..1d5c475f8f 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp @@ -5,14 +5,14 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveTimeInput.h" #include "AdaptiveTimeInputRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { @@ -22,12 +22,54 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveTimeInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveTimeInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _In_ IAdaptiveRenderArgs* /*renderArgs*/, + _COM_Outptr_ IUIElement** timeInputControl) noexcept try { - return XamlBuilder::BuildTimeInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Time Input was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr timePicker = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TimePicker)); + + // Make the picker stretch full width + ComPtr timePickerAsFrameworkElement; + RETURN_IF_FAILED(timePicker.As(&timePickerAsFrameworkElement)); + RETURN_IF_FAILED(timePickerAsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); + RETURN_IF_FAILED(timePickerAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Input.Time", + timePickerAsFrameworkElement.Get())); + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveTimeInput; + THROW_IF_FAILED(cardElement.As(&adaptiveTimeInput)); + + // Set initial value + HString hstringValue; + THROW_IF_FAILED(adaptiveTimeInput->get_Value(hstringValue.GetAddressOf())); + std::string value = HStringToUTF8(hstringValue.Get()); + unsigned int hours, minutes; + if (DateTimePreparser::TryParseSimpleTime(value, hours, minutes)) + { + TimeSpan initialTime{(INT64)(hours * 60 + minutes) * 10000000 * 60}; + THROW_IF_FAILED(timePicker->put_Time(initialTime)); + } + + // Note: Placeholder text and min/max are not supported by ITimePicker + + RETURN_IF_FAILED(timePicker.CopyTo(timeInputControl)); + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *timeInputControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.h index 1341204607..8d767c9f05 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "TimeInput.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp b/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp index 3bf5d4230c..58226e9a8c 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveToggleInput.h" -#include "Util.h" -#include +#include "AdaptiveToggleInput.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInput.h b/source/uwp/Renderer/lib/AdaptiveToggleInput.h index bccda9595d..8a467aea23 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInput.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleInput.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ToggleInput.h" #include "AdaptiveInputElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp index 86e2fff100..b659053e81 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp @@ -5,14 +5,15 @@ #include "AdaptiveElementParserRegistration.h" #include "AdaptiveToggleInput.h" #include "AdaptiveToggleInputRenderer.h" -#include "enums.h" -#include "Util.h" -#include "XamlBuilder.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { @@ -22,12 +23,60 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveToggleInputRenderer::Render(_In_ IAdaptiveCardElement* cardElement, + HRESULT AdaptiveToggleInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _In_ IAdaptiveRenderArgs* /*renderArgs*/, + _COM_Outptr_ IUIElement** toggleInputControl) noexcept try { - return XamlBuilder::BuildToggleInput(cardElement, renderContext, renderArgs, result); + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + if (!XamlHelpers::SupportsInteractivity(hostConfig.Get())) + { + renderContext->AddWarning( + ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"Toggle Input was stripped from card because interactivity is not supported").Get()); + return S_OK; + } + + ComPtr cardElement(adaptiveCardElement); + ComPtr adaptiveToggleInput; + RETURN_IF_FAILED(cardElement.As(&adaptiveToggleInput)); + + ComPtr checkBox = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CheckBox)); + + HString title; + RETURN_IF_FAILED(adaptiveToggleInput->get_Title(title.GetAddressOf())); + + boolean wrap; + adaptiveToggleInput->get_Wrap(&wrap); + + XamlHelpers::SetContent(checkBox.Get(), title.Get(), wrap); + + HString value; + RETURN_IF_FAILED(adaptiveToggleInput->get_Value(value.GetAddressOf())); + + HString valueOn; + RETURN_IF_FAILED(adaptiveToggleInput->get_ValueOn(valueOn.GetAddressOf())); + + INT32 compareValueOn; + RETURN_IF_FAILED(WindowsCompareStringOrdinal(value.Get(), valueOn.Get(), &compareValueOn)); + + XamlHelpers::SetToggleValue(checkBox.Get(), (compareValueOn == 0)); + + ComPtr checkboxAsUIElement; + RETURN_IF_FAILED(checkBox.As(&checkboxAsUIElement)); + RETURN_IF_FAILED(XamlHelpers::AddHandledTappedEvent(checkboxAsUIElement.Get())); + + ComPtr frameworkElement; + RETURN_IF_FAILED(checkBox.As(&frameworkElement)); + RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Toggle", frameworkElement.Get())); + + RETURN_IF_FAILED(checkboxAsUIElement.CopyTo(toggleInputControl)); + XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *toggleInputControl); + return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.h index 6c00c89410..49ac2feab6 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ToggleInput.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp index db9d4df968..9cf3e42f27 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveToggleVisibilityAction.h" -#include "Util.h" -#include "Vector.h" using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h index a74841fc9e..94f9bbd162 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ToggleVisibilityAction.h" #include "AdaptiveActionElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp index b4a81db52e..b0774cf1de 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp @@ -4,9 +4,8 @@ #include "AdaptiveToggleVisibilityAction.h" #include "AdaptiveToggleVisibilityActionRenderer.h" -#include "Util.h" #include "AdaptiveElementParserRegistration.h" -#include "XamlBuilder.h" +#include "ActionHelpers.h" using namespace ABI::AdaptiveNamespace; using namespace Microsoft::WRL; @@ -24,7 +23,7 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try { - return XamlBuilder::BuildAction(action, renderContext, renderArgs, result); + return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp index 0a81a2509e..894b15ca21 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" + #include "AdaptiveToggleVisibilityTarget.h" -#include "Util.h" -#include #include "ToggleVisibilityTarget.h" using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.h b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.h index 5dc2276409..1fd170baed 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "ToggleVisibilityTarget.h" namespace AdaptiveNamespace diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp index b43a4f7e61..cb5dd7443d 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp @@ -3,7 +3,6 @@ #include "pch.h" #include "AdaptiveUnsupportedAction.h" -#include "Util.h" using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h index 88b0d8799a..8a56f8cdd9 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h @@ -2,8 +2,6 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "UnknownAction.h" #include "AdaptiveActionElement.h" diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp index d57d339485..26fe5a7d7e 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp @@ -4,9 +4,6 @@ #include "AdaptiveUnsupportedElement.h" -#include "Util.h" -#include - using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.h b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.h index a753576e7c..b9d9b31790 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.h +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.h @@ -2,10 +2,7 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" #include "UnknownElement.h" -#include "AdaptiveCardElement.h" namespace AdaptiveNamespace { diff --git a/source/uwp/Renderer/lib/AsyncOperations.h b/source/uwp/Renderer/lib/AsyncOperations.h index ff72a507d2..5338915844 100644 --- a/source/uwp/Renderer/lib/AsyncOperations.h +++ b/source/uwp/Renderer/lib/AsyncOperations.h @@ -40,7 +40,7 @@ class RenderAsyncBase bool explicitDimensions = m_renderer->GetFixedDimensions(&width, &height); if (explicitDimensions) { - THROW_IF_FAILED(m_renderer->GetXamlBuilder()->SetFixedDimensions(width, height)); + m_renderer->GetXamlBuilder()->SetFixedDimensions(width, height); } } diff --git a/source/uwp/Renderer/lib/RenderedAdaptiveCard.cpp b/source/uwp/Renderer/lib/RenderedAdaptiveCard.cpp index 5faff30c3f..f309e1cf0e 100644 --- a/source/uwp/Renderer/lib/RenderedAdaptiveCard.cpp +++ b/source/uwp/Renderer/lib/RenderedAdaptiveCard.cpp @@ -10,11 +10,9 @@ #include "AdaptiveMediaEventArgs.h" #include "AdaptiveShowCardAction.h" #include "RenderedAdaptiveCard.h" -#include "vector.h" -#include -#include #include "XamlBuilder.h" #include "XamlHelpers.h" +#include "ElementTagContent.h" using namespace concurrency; using namespace Microsoft::WRL; @@ -153,6 +151,101 @@ namespace AdaptiveNamespace return S_OK; } + static HRESULT HandleToggleVisibilityClick(_In_ IFrameworkElement* cardFrameworkElement, _In_ IAdaptiveActionElement* action) + { + ComPtr localAction(action); + ComPtr toggleAction; + RETURN_IF_FAILED(localAction.As(&toggleAction)); + + ComPtr> targets; + RETURN_IF_FAILED(toggleAction->get_TargetElements(&targets)); + + ComPtr> targetsIterable; + RETURN_IF_FAILED(targets.As>(&targetsIterable)); + + boolean hasCurrent; + ComPtr> targetIterator; + HRESULT hr = targetsIterable->First(&targetIterator); + RETURN_IF_FAILED(targetIterator->get_HasCurrent(&hasCurrent)); + + std::unordered_set parentPanels; + while (SUCCEEDED(hr) && hasCurrent) + { + ComPtr currentTarget; + RETURN_IF_FAILED(targetIterator->get_Current(¤tTarget)); + + HString toggleId; + RETURN_IF_FAILED(currentTarget->get_ElementId(toggleId.GetAddressOf())); + + ABI::AdaptiveNamespace::IsVisible toggle; + RETURN_IF_FAILED(currentTarget->get_IsVisible(&toggle)); + + ComPtr toggleElement; + RETURN_IF_FAILED(cardFrameworkElement->FindName(toggleId.Get(), &toggleElement)); + + if (toggleElement != nullptr) + { + ComPtr toggleElementAsUIElement; + RETURN_IF_FAILED(toggleElement.As(&toggleElementAsUIElement)); + + ComPtr toggleElementAsFrameworkElement; + RETURN_IF_FAILED(toggleElement.As(&toggleElementAsFrameworkElement)); + + ComPtr tag; + RETURN_IF_FAILED(toggleElementAsFrameworkElement->get_Tag(&tag)); + + ComPtr elementTagContent; + RETURN_IF_FAILED(tag.As(&elementTagContent)); + + Visibility visibilityToSet = Visibility_Visible; + if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleTrue) + { + visibilityToSet = Visibility_Visible; + } + else if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleFalse) + { + visibilityToSet = Visibility_Collapsed; + } + else if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleToggle) + { + boolean currentVisibility{}; + RETURN_IF_FAILED(elementTagContent->get_ExpectedVisibility(¤tVisibility)); + visibilityToSet = (currentVisibility) ? Visibility_Collapsed : Visibility_Visible; + } + + RETURN_IF_FAILED(toggleElementAsUIElement->put_Visibility(visibilityToSet)); + RETURN_IF_FAILED(elementTagContent->set_ExpectedVisibility(visibilityToSet == Visibility_Visible)); + + ComPtr parentPanel; + RETURN_IF_FAILED(elementTagContent->get_ParentPanel(&parentPanel)); + parentPanels.insert(parentPanel.Get()); + + ComPtr cardElement; + RETURN_IF_FAILED(elementTagContent->get_AdaptiveCardElement(&cardElement)); + + // If the element we're toggling is a column, we'll need to change the width on the column definition + ComPtr cardElementAsColumn; + if (SUCCEEDED(cardElement.As(&cardElementAsColumn))) + { + ComPtr columnDefinition; + RETURN_IF_FAILED(elementTagContent->get_ColumnDefinition(&columnDefinition)); + RETURN_IF_FAILED(XamlHelpers::HandleColumnWidth(cardElementAsColumn.Get(), + (visibilityToSet == Visibility_Visible), + columnDefinition.Get())); + } + } + + hr = targetIterator->MoveNext(&hasCurrent); + } + + for (auto parentPanel : parentPanels) + { + XamlHelpers::SetSeparatorVisibility(parentPanel); + } + + return S_OK; + } + HRESULT RenderedAdaptiveCard::SendActionEvent(_In_ IAdaptiveActionElement* actionElement) { // get the inputElements in Json form. @@ -167,7 +260,9 @@ namespace AdaptiveNamespace switch (actionType) { case ABI::AdaptiveCards::Rendering::Uwp::ActionType_ToggleVisibility: - return XamlBuilder::HandleToggleVisibilityClick(m_frameworkElement.Get(), actionElement); + { + return HandleToggleVisibilityClick(m_frameworkElement.Get(), actionElement); + } case ABI::AdaptiveCards::Rendering::Uwp::ActionType_ShowCard: { @@ -191,8 +286,10 @@ namespace AdaptiveNamespace case ABI::AdaptiveCards::Rendering::Uwp::ActionType_Submit: case ABI::AdaptiveCards::Rendering::Uwp::ActionType_Custom: default: + { return m_actionEvents->InvokeAll(this, eventArgs.Get()); } + } } HRESULT RenderedAdaptiveCard::SendMediaClickedEvent(_In_ IAdaptiveMedia* mediaElement) @@ -220,7 +317,8 @@ namespace AdaptiveNamespace HRESULT RenderedAdaptiveCard::AddInlineShowCard(_In_ IAdaptiveActionSet* actionSet, _In_ IAdaptiveShowCardAction* showCardAction, - _In_ ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) try + _In_ ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) + try { InternalId actionSetId; ComPtr actionSetImpl = PeekInnards(actionSet); @@ -234,7 +332,8 @@ namespace AdaptiveNamespace HRESULT RenderedAdaptiveCard::AddInlineShowCard(ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, ABI::AdaptiveNamespace::IAdaptiveShowCardAction* showCardAction, - ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) try + ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) + try { InternalId actionSetId; ComPtr adaptiveCardImpl = PeekInnards(adaptiveCard); @@ -248,7 +347,8 @@ namespace AdaptiveNamespace HRESULT RenderedAdaptiveCard::AddInlineShowCardHelper(AdaptiveCards::InternalId& actionSetId, ABI::AdaptiveNamespace::IAdaptiveShowCardAction* showCardAction, - ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) try + ABI::Windows::UI::Xaml::IUIElement* showCardFrameworkElement) + try { ComPtr showCardImpl = PeekInnards(showCardAction); diff --git a/source/uwp/Renderer/lib/TileControl.cpp b/source/uwp/Renderer/lib/TileControl.cpp index 96a73a844d..624438d859 100644 --- a/source/uwp/Renderer/lib/TileControl.cpp +++ b/source/uwp/Renderer/lib/TileControl.cpp @@ -2,16 +2,10 @@ // Licensed under the MIT License. #include "pch.h" -#include "enums.h" #include #include "AdaptiveBackgroundImage.h" #include "TileControl.h" #include "XamlHelpers.h" -#include "XamlBuilder.h" -#include -#include -#include -#include using namespace Microsoft::WRL; using namespace ABI::AdaptiveNamespace; diff --git a/source/uwp/Renderer/lib/TileControl.h b/source/uwp/Renderer/lib/TileControl.h index 61f4b97987..2046909275 100644 --- a/source/uwp/Renderer/lib/TileControl.h +++ b/source/uwp/Renderer/lib/TileControl.h @@ -3,9 +3,6 @@ #pragma once #include "pch.h" -#include -#include "AdaptiveCards.Rendering.Uwp.h" -#include "Enums.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; diff --git a/source/uwp/Renderer/lib/Util.cpp b/source/uwp/Renderer/lib/Util.cpp index f2fbe629f6..900018349a 100644 --- a/source/uwp/Renderer/lib/Util.cpp +++ b/source/uwp/Renderer/lib/Util.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" -#include + #include #include "AdaptiveActionParserRegistration.h" @@ -39,11 +39,7 @@ #include "AdaptiveWarning.h" #include "CustomActionWrapper.h" #include "CustomElementWrapper.h" -#include "enums.h" -#include "util.h" -#include #include "XamlHelpers.h" -#include "XamlBuilder.h" using namespace AdaptiveCards; using namespace Microsoft::WRL; diff --git a/source/uwp/Renderer/lib/XamlBuilder.cpp b/source/uwp/Renderer/lib/XamlBuilder.cpp index 4eecd31191..7707ff4cf8 100644 --- a/source/uwp/Renderer/lib/XamlBuilder.cpp +++ b/source/uwp/Renderer/lib/XamlBuilder.cpp @@ -2,62 +2,21 @@ // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveBase64Util.h" -#include "AdaptiveCardGetResourceStreamArgs.h" -#include "AdaptiveCardRendererComponent.h" -#include "AdaptiveCardResourceResolvers.h" -#include "AdaptiveColorsConfig.h" -#include "AdaptiveColorConfig.h" +#include "XamlBuilder.h" + #include "AdaptiveFeatureRegistration.h" -#include "AdaptiveHostConfig.h" -#include "AdaptiveImage.h" #include "AdaptiveRenderArgs.h" -#include "AdaptiveShowCardAction.h" -#include "AdaptiveTextRun.h" -#include "DateTimeParser.h" -#include "ElementTagContent.h" -#include "FeatureRegistration.h" -#include "TextHelpers.h" -#include "json/json.h" -#include "MarkDownParser.h" -#include "MediaHelpers.h" -#include -#include "TileControl.h" -#include "WholeItemsPanel.h" -#include -#include -#include -#include -#include -#include -#include "XamlBuilder.h" +#include "ActionHelpers.h" #include "XamlHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::AdaptiveNamespace; -using namespace ABI::Windows::Data::Json; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; -using namespace ABI::Windows::Storage; -using namespace ABI::Windows::Storage::Streams; -using namespace ABI::Windows::UI; -using namespace ABI::Windows::UI::Text; using namespace ABI::Windows::UI::Xaml; -using namespace ABI::Windows::UI::Xaml::Data; -using namespace ABI::Windows::UI::Xaml::Documents; using namespace ABI::Windows::UI::Xaml::Controls; -using namespace ABI::Windows::UI::Xaml::Controls::Primitives; -using namespace ABI::Windows::UI::Xaml::Markup; using namespace ABI::Windows::UI::Xaml::Media; -using namespace ABI::Windows::UI::Xaml::Media::Imaging; -using namespace ABI::Windows::UI::Xaml::Shapes; -using namespace ABI::Windows::UI::Xaml::Input; -using namespace ABI::Windows::UI::Xaml::Automation; -using namespace ABI::Windows::Web::Http; -using namespace ABI::Windows::Web::Http::Filters; - -const PCWSTR c_BackgroundImageOverlayBrushKey = L"AdaptiveCard.BackgroundOverlayBrush"; namespace AdaptiveNamespace { @@ -69,62 +28,25 @@ namespace AdaptiveNamespace &m_randomAccessStreamStatics)); } - ComPtr XamlBuilder::CreateSeparator(_In_ IAdaptiveRenderContext* renderContext, - UINT spacing, - UINT separatorThickness, - ABI::Windows::UI::Color separatorColor, - bool isHorizontal) - { - ComPtr separator = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr separatorAsFrameworkElement; - THROW_IF_FAILED(separator.As(&separatorAsFrameworkElement)); - - ComPtr lineColorBrush = XamlHelpers::GetSolidColorBrush(separatorColor); - ComPtr separatorAsPanel; - THROW_IF_FAILED(separator.As(&separatorAsPanel)); - separatorAsPanel->put_Background(lineColorBrush.Get()); - - UINT32 separatorMarginValue = spacing > separatorThickness ? (spacing - separatorThickness) / 2 : 0; - Thickness margin = {0, 0, 0, 0}; - - if (isHorizontal) - { - margin.Top = margin.Bottom = separatorMarginValue; - separatorAsFrameworkElement->put_Height(separatorThickness); - } - else - { - margin.Left = margin.Right = separatorMarginValue; - separatorAsFrameworkElement->put_Width(separatorThickness); - } - - THROW_IF_FAILED(separatorAsFrameworkElement->put_Margin(margin)); - - THROW_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Separator", separatorAsFrameworkElement.Get())); - - ComPtr result; - THROW_IF_FAILED(separator.As(&result)); - return result; - } - - HRESULT XamlBuilder::AllImagesLoaded() + HRESULT XamlBuilder::AllImagesLoaded() noexcept try { FireAllImagesLoaded(); return S_OK; } + CATCH_RETURN; - HRESULT XamlBuilder::ImagesLoadingHadError() + HRESULT XamlBuilder::ImagesLoadingHadError() noexcept try { FireImagesLoadingHadError(); return S_OK; } + CATCH_RETURN; HRESULT XamlBuilder::BuildXamlTreeFromAdaptiveCard(_In_ IAdaptiveCard* adaptiveCard, _Outptr_ IFrameworkElement** xamlTreeRoot, _In_ IAdaptiveRenderContext* renderContext, ComPtr xamlBuilder, - ABI::AdaptiveNamespace::ContainerStyle defaultContainerStyle) + ABI::AdaptiveNamespace::ContainerStyle defaultContainerStyle) noexcept try { *xamlTreeRoot = nullptr; if (adaptiveCard != nullptr) @@ -152,8 +74,8 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(MakeAndInitialize(&renderArgs, containerStyle, nullptr, nullptr)); ComPtr bodyElementContainer; - ComPtr rootElement = - CreateRootCardElement(adaptiveCard, renderContext, renderArgs.Get(), xamlBuilder, &bodyElementContainer); + ComPtr rootElement; + RETURN_IF_FAILED(CreateRootCardElement(adaptiveCard, renderContext, renderArgs.Get(), xamlBuilder, &bodyElementContainer, &rootElement)); ComPtr rootAsFrameworkElement; RETURN_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); @@ -169,13 +91,13 @@ namespace AdaptiveNamespace // Create a new IUIElement pointer to house the root element decorated with select action ComPtr rootSelectActionElement; - HandleSelectAction(nullptr, - selectAction.Get(), - renderContext, - rootElement.Get(), - SupportsInteractivity(hostConfig.Get()), - true, - &rootSelectActionElement); + XamlHelpers::HandleSelectAction(nullptr, + selectAction.Get(), + renderContext, + rootElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + &rootSelectActionElement); RETURN_IF_FAILED(rootSelectActionElement.As(&rootAsFrameworkElement)); // Enumerate the child items of the card and build xaml for them @@ -189,7 +111,7 @@ namespace AdaptiveNamespace ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment; RETURN_IF_FAILED(adaptiveCard->get_VerticalContentAlignment(&verticalContentAlignment)); - XamlBuilder::SetVerticalContentAlignmentToChildren(bodyElementContainer.Get(), verticalContentAlignment); + XamlHelpers::SetVerticalContentAlignmentToChildren(bodyElementContainer.Get(), verticalContentAlignment); ComPtr> actions; RETURN_IF_FAILED(adaptiveCard->get_Actions(&actions)); @@ -197,16 +119,16 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(actions->get_Size(&actionsSize)); if (actionsSize > 0) { - if (SupportsInteractivity(hostConfig.Get())) + if (XamlHelpers::SupportsInteractivity(hostConfig.Get())) { unsigned int bodyCount; RETURN_IF_FAILED(body->get_Size(&bodyCount)); - BuildActions(adaptiveCard, - actions.Get(), - bodyElementContainer.Get(), - bodyCount > 0, - renderContext, - renderArgs.Get()); + XamlHelpers::BuildActions(adaptiveCard, + actions.Get(), + bodyElementContainer.Get(), + bodyCount > 0, + renderContext, + renderArgs.Get()); } else { @@ -221,12 +143,14 @@ namespace AdaptiveNamespace if (!isInShowCard) { - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Card", rootAsFrameworkElement.Get())); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Card", rootAsFrameworkElement.Get())); } else { - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.ShowCard.Card", rootAsFrameworkElement.Get())); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.ShowCard.Card", + rootAsFrameworkElement.Get())); } RETURN_IF_FAILED(rootAsFrameworkElement.CopyTo(xamlTreeRoot)); @@ -249,6 +173,7 @@ namespace AdaptiveNamespace } return S_OK; } + CATCH_RETURN; HRESULT XamlBuilder::AddListener(_In_ IXamlBuilderListener* listener) noexcept try { @@ -278,119 +203,38 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT XamlBuilder::SetFixedDimensions(UINT width, UINT height) noexcept + void XamlBuilder::SetFixedDimensions(UINT width, UINT height) noexcept { m_fixedDimensions = true; m_fixedWidth = width; m_fixedHeight = height; - return S_OK; } - HRESULT XamlBuilder::SetEnableXamlImageHandling(bool enableXamlImageHandling) noexcept + void XamlBuilder::SetEnableXamlImageHandling(bool enableXamlImageHandling) noexcept { m_enableXamlImageHandling = enableXamlImageHandling; - return S_OK; - } - - template - HRESULT XamlBuilder::TryGetResourceFromResourceDictionaries(_In_ IResourceDictionary* resourceDictionary, - std::wstring resourceName, - _COM_Outptr_ T** style) - { - if (resourceDictionary == nullptr) - { - return E_INVALIDARG; - } - - *style = nullptr; - try - { - // Get a resource key for the requested style that we can use for ResourceDistionary Lookups - ComPtr propertyValueStatics; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), - &propertyValueStatics)); - ComPtr resourceKey; - THROW_IF_FAILED(propertyValueStatics->CreateString(HStringReference(resourceName.c_str()).Get(), - resourceKey.GetAddressOf())); - - // Search for the named resource - ComPtr strongDictionary = resourceDictionary; - ComPtr dictionaryValue; - ComPtr> resourceDictionaryMap; - - boolean hasKey{}; - if (SUCCEEDED(strongDictionary.As(&resourceDictionaryMap)) && - SUCCEEDED(resourceDictionaryMap->HasKey(resourceKey.Get(), &hasKey)) && hasKey && - SUCCEEDED(resourceDictionaryMap->Lookup(resourceKey.Get(), dictionaryValue.GetAddressOf()))) - { - ComPtr resourceToReturn; - if (SUCCEEDED(dictionaryValue.As(&resourceToReturn))) - { - THROW_IF_FAILED(resourceToReturn.CopyTo(style)); - return S_OK; - } - } - } - catch (...) - { - } - return E_FAIL; - } - - HRESULT XamlBuilder::TryInsertResourceToResourceDictionaries(_In_ IResourceDictionary* resourceDictionary, - std::wstring resourceName, - _In_ IInspectable* value) - { - if (resourceDictionary == nullptr) - { - return E_INVALIDARG; - } - - try - { - ComPtr propertyValueStatics; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), - &propertyValueStatics)); - - ComPtr resourceKey; - THROW_IF_FAILED(propertyValueStatics->CreateString(HStringReference(resourceName.c_str()).Get(), - resourceKey.GetAddressOf())); - - ComPtr strongDictionary = resourceDictionary; - ComPtr> resourceDictionaryMap; - THROW_IF_FAILED(strongDictionary.As(&resourceDictionaryMap)); - - boolean replaced{}; - THROW_IF_FAILED(resourceDictionaryMap->Insert(resourceKey.Get(), value, &replaced)); - return S_OK; - } - catch (...) - { - } - return E_FAIL; } - HRESULT XamlBuilder::SetStyleFromResourceDictionary(_In_ IAdaptiveRenderContext* renderContext, - std::wstring resourceName, - _In_ IFrameworkElement* frameworkElement) + static HRESULT ApplyMarginToXamlElement(_In_ IAdaptiveHostConfig* hostConfig, _In_ IFrameworkElement* element) noexcept { - ComPtr resourceDictionary; - RETURN_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); + ComPtr localElement(element); + ComPtr spacingConfig; + RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - ComPtr style; - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), resourceName, &style))) - { - RETURN_IF_FAILED(frameworkElement->put_Style(style.Get())); - } + UINT32 padding; + spacingConfig->get_Padding(&padding); + Thickness margin = {(double)padding, (double)padding, (double)padding, (double)padding}; + RETURN_IF_FAILED(localElement->put_Margin(margin)); return S_OK; } - ComPtr XamlBuilder::CreateRootCardElement(_In_ IAdaptiveCard* adaptiveCard, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - ComPtr xamlBuilder, - _Outptr_ IPanel** bodyElementContainer) + HRESULT XamlBuilder::CreateRootCardElement(_In_ IAdaptiveCard* adaptiveCard, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + ComPtr xamlBuilder, + _COM_Outptr_ IPanel** bodyElementContainer, + _COM_Outptr_ IUIElement** rootElementResult) noexcept try { // The root of an adaptive card is a composite of several elements, depending on the card // properties. From back to front these are: @@ -401,36 +245,36 @@ namespace AdaptiveNamespace ComPtr rootElement = XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); ComPtr hostConfig; - THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); ComPtr adaptiveCardConfig; - THROW_IF_FAILED(hostConfig->get_AdaptiveCard(&adaptiveCardConfig)); + RETURN_IF_FAILED(hostConfig->get_AdaptiveCard(&adaptiveCardConfig)); ComPtr rootAsPanel; - THROW_IF_FAILED(rootElement.As(&rootAsPanel)); + RETURN_IF_FAILED(rootElement.As(&rootAsPanel)); ABI::AdaptiveNamespace::ContainerStyle containerStyle; - THROW_IF_FAILED(renderArgs->get_ContainerStyle(&containerStyle)); + RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&containerStyle)); ABI::Windows::UI::Color backgroundColor; if (SUCCEEDED(GetBackgroundColorFromStyle(containerStyle, hostConfig.Get(), &backgroundColor))) { ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(backgroundColor); - THROW_IF_FAILED(rootAsPanel->put_Background(backgroundColorBrush.Get())); + RETURN_IF_FAILED(rootAsPanel->put_Background(backgroundColorBrush.Get())); } ComPtr backgroundImage; BOOL backgroundImageIsValid; - THROW_IF_FAILED(adaptiveCard->get_BackgroundImage(&backgroundImage)); - THROW_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); + RETURN_IF_FAILED(adaptiveCard->get_BackgroundImage(&backgroundImage)); + RETURN_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); if (backgroundImageIsValid) { - ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, renderArgs); + XamlHelpers::ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, renderArgs); } ComPtr spacingConfig; - THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); UINT32 padding; - THROW_IF_FAILED(spacingConfig->get_Padding(&padding)); + RETURN_IF_FAILED(spacingConfig->get_Padding(&padding)); // Configure WholeItemsPanel to not clip bleeding containers WholeItemsPanel::SetBleedMargin(padding); @@ -438,24 +282,24 @@ namespace AdaptiveNamespace // Now create the inner stack panel to serve as the root host for all the // body elements and apply padding from host configuration ComPtr bodyElementHost; - THROW_IF_FAILED(MakeAndInitialize(&bodyElementHost)); + RETURN_IF_FAILED(MakeAndInitialize(&bodyElementHost)); bodyElementHost->SetMainPanel(TRUE); bodyElementHost->SetAdaptiveHeight(TRUE); ComPtr bodyElementHostAsElement; - THROW_IF_FAILED(bodyElementHost.As(&bodyElementHostAsElement)); - ApplyMarginToXamlElement(hostConfig.Get(), bodyElementHostAsElement.Get()); + RETURN_IF_FAILED(bodyElementHost.As(&bodyElementHostAsElement)); + RETURN_IF_FAILED(ApplyMarginToXamlElement(hostConfig.Get(), bodyElementHostAsElement.Get())); ABI::AdaptiveNamespace::HeightType adaptiveCardHeightType; - THROW_IF_FAILED(adaptiveCard->get_Height(&adaptiveCardHeightType)); + RETURN_IF_FAILED(adaptiveCard->get_Height(&adaptiveCardHeightType)); XamlHelpers::AppendXamlElementToPanel(bodyElementHost.Get(), rootAsPanel.Get(), adaptiveCardHeightType); - THROW_IF_FAILED(bodyElementHost.CopyTo(bodyElementContainer)); + RETURN_IF_FAILED(bodyElementHost.CopyTo(bodyElementContainer)); if (xamlBuilder && xamlBuilder->m_fixedDimensions) { ComPtr rootAsFrameworkElement; - THROW_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); + RETURN_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); rootAsFrameworkElement->put_Width(xamlBuilder->m_fixedWidth); rootAsFrameworkElement->put_Height(xamlBuilder->m_fixedHeight); rootAsFrameworkElement->put_MaxHeight(xamlBuilder->m_fixedHeight); @@ -464,373 +308,16 @@ namespace AdaptiveNamespace if (adaptiveCardHeightType == ABI::AdaptiveNamespace::HeightType::Stretch) { ComPtr rootAsFrameworkElement; - THROW_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); + RETURN_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); rootAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment::VerticalAlignment_Stretch); } - ComPtr rootAsUIElement; - THROW_IF_FAILED(rootElement.As(&rootAsUIElement)); - return rootAsUIElement; - } - - void XamlBuilder::ApplyBackgroundToRoot(_In_ ABI::Windows::UI::Xaml::Controls::IPanel* rootPanel, - _In_ IAdaptiveBackgroundImage* backgroundImage, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs) - { - // In order to reuse the image creation code paths, we simply create an adaptive card - // image element and then build that into xaml and apply to the root. - ComPtr adaptiveImage; - HSTRING url; - THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - THROW_IF_FAILED(backgroundImage->get_Url(&url)); - THROW_IF_FAILED(adaptiveImage->put_Url(url)); - - ComPtr adaptiveCardElement; - THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); - - ComPtr elementRenderers; - THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - - ComPtr elementRenderer; - THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &elementRenderer)); - - ComPtr background; - if (elementRenderer != nullptr) - { - elementRenderer->Render(adaptiveCardElement.Get(), renderContext, renderArgs, &background); - if (background == nullptr) - { - return; - } - } - - ComPtr xamlImage; - THROW_IF_FAILED(background.As(&xamlImage)); - - ABI::AdaptiveNamespace::BackgroundImageFillMode fillMode; - THROW_IF_FAILED(backgroundImage->get_FillMode(&fillMode)); - - // Creates the background image for all fill modes - ComPtr tileControl; - THROW_IF_FAILED(MakeAndInitialize(&tileControl)); - THROW_IF_FAILED(tileControl->put_BackgroundImage(backgroundImage)); - - ComPtr rootElement; - THROW_IF_FAILED(rootPanel->QueryInterface(rootElement.GetAddressOf())); - THROW_IF_FAILED(tileControl->put_RootElement(rootElement.Get())); - - THROW_IF_FAILED(tileControl->LoadImageBrush(background.Get())); - - ComPtr backgroundAsFrameworkElement; - THROW_IF_FAILED(tileControl.As(&backgroundAsFrameworkElement)); - - XamlHelpers::AppendXamlElementToPanel(backgroundAsFrameworkElement.Get(), rootPanel); - - // The overlay applied to the background image is determined by a resouce, so create - // the overlay if that resources exists - ComPtr resourceDictionary; - THROW_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); - ComPtr backgroundOverlayBrush; - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), c_BackgroundImageOverlayBrushKey, &backgroundOverlayBrush))) - { - ComPtr overlayRectangle = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Rectangle)); - THROW_IF_FAILED(overlayRectangle->put_Fill(backgroundOverlayBrush.Get())); - - ComPtr overlayRectangleAsUIElement; - THROW_IF_FAILED(overlayRectangle.As(&overlayRectangleAsUIElement)); - XamlHelpers::AppendXamlElementToPanel(overlayRectangle.Get(), rootPanel); - } - } - - template - void XamlBuilder::SetImageSource(_In_ T* destination, _In_ IImageSource* imageSource, ABI::Windows::UI::Xaml::Media::Stretch /*stretch*/) - { - THROW_IF_FAILED(destination->put_Source(imageSource)); - }; - - template<> - void XamlBuilder::SetImageSource(_In_ IEllipse* destination, - _In_ IImageSource* imageSource, - ABI::Windows::UI::Xaml::Media::Stretch stretch) - { - ComPtr imageBrush = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Media_ImageBrush)); - THROW_IF_FAILED(imageBrush->put_ImageSource(imageSource)); - - ComPtr tileBrush; - THROW_IF_FAILED(imageBrush.As(&tileBrush)); - THROW_IF_FAILED(tileBrush->put_Stretch(stretch)); - - ComPtr brush; - THROW_IF_FAILED(imageBrush.As(&brush)); - - ComPtr ellipseAsShape; - ComPtr ellipse(destination); - THROW_IF_FAILED(ellipse.As(&ellipseAsShape)); - - THROW_IF_FAILED(ellipseAsShape->put_Fill(brush.Get())); - }; - - template - void XamlBuilder::SetImageOnUIElement(_In_ ABI::Windows::Foundation::IUriRuntimeClass* imageUrl, - _In_ T* uiElement, - _In_opt_ IAdaptiveCardResourceResolvers* resolvers, - bool isAutoSize, - IInspectable* parentElement, - IInspectable* imageContainer, - bool isVisible, - _Out_ bool* mustHideElement, - ABI::Windows::UI::Xaml::Media::Stretch stretch) - { - *mustHideElement = true; - - // Get the image url scheme - HString schemeName; - THROW_IF_FAILED(imageUrl->get_SchemeName(schemeName.GetAddressOf())); - - // Get the resolver for the image - ComPtr resolver; - if (resolvers != nullptr) - { - THROW_IF_FAILED(resolvers->Get(schemeName.Get(), &resolver)); - // If we have a resolver - if (resolver != nullptr) - { - // Create a BitmapImage to hold the image data. We use BitmapImage in order to allow - // the tracker to subscribe to the ImageLoaded/Failed events - ComPtr bitmapImage = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); - - if (!m_enableXamlImageHandling && (m_listeners.size() != 0)) - { - m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); - } - - THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_None)); - ComPtr bitmapSource; - bitmapImage.As(&bitmapSource); - - // Create the arguments to pass to the resolver - ComPtr args; - THROW_IF_FAILED(MakeAndInitialize(&args, imageUrl)); - - // And call the resolver to get the image stream - ComPtr> getResourceStreamOperation; - THROW_IF_FAILED(resolver->GetResourceStreamAsync(args.Get(), &getResourceStreamOperation)); - - ComPtr strongImageControl(uiElement); - ComPtr strongThis(this); - THROW_IF_FAILED(getResourceStreamOperation->put_Completed( - Callback, IAsyncOperationCompletedHandler>>( - [strongThis, this, bitmapSource, strongImageControl, bitmapImage, stretch, isAutoSize, parentElement, imageContainer, isVisible]( - IAsyncOperation* operation, AsyncStatus status) -> HRESULT { - if (status == AsyncStatus::Completed) - { - // Get the random access stream - ComPtr randomAccessStream; - RETURN_IF_FAILED(operation->GetResults(&randomAccessStream)); - - if (randomAccessStream == nullptr) - { - m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); - return S_OK; - } - - RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); - - ComPtr imageSource; - RETURN_IF_FAILED(bitmapSource.As(&imageSource)); - - SetImageSource(strongImageControl.Get(), imageSource.Get(), stretch); - - // Here should be the auto resizing, at this time we already have the image and everything set - if (isAutoSize) - { - SetAutoSize(strongImageControl.Get(), parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */); - } - - return S_OK; - } - else - { - m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); - return S_OK; - } - }) - .Get())); - - return; - } - } - - INT32 isDataUriImage{}; - THROW_IF_FAILED(WindowsCompareStringOrdinal(schemeName.Get(), HStringReference(L"data").Get(), &isDataUriImage)); - if (isDataUriImage == 0) - { - // Decode base 64 string - HString dataPath; - THROW_IF_FAILED(imageUrl->get_Path(dataPath.GetAddressOf())); - - std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath.Get())); - std::vector decodedData = AdaptiveBase64Util::Decode(data); - - ComPtr bufferFactory; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - bufferFactory.GetAddressOf())); - - ComPtr buffer; - THROW_IF_FAILED(bufferFactory->Create(static_cast(decodedData.size()), buffer.GetAddressOf())); - - ComPtr<::Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess; - THROW_IF_FAILED(buffer.As(&bufferByteAccess)); - - BYTE* dataInternal{}; - THROW_IF_FAILED(bufferByteAccess->Buffer(&dataInternal)); - - memcpy_s(dataInternal, decodedData.size(), decodedData.data(), decodedData.size()); - - THROW_IF_FAILED(buffer->put_Length(static_cast(decodedData.size()))); - - ComPtr bitmapImage = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); - m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); - THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_IgnoreImageCache)); - ComPtr bitmapSource; - THROW_IF_FAILED(bitmapImage.As(&bitmapSource)); - - ComPtr randomAccessStream = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream)); - - ComPtr outputStream; - THROW_IF_FAILED(randomAccessStream.As(&outputStream)); - - ComPtr> bufferWriteOperation; - THROW_IF_FAILED(outputStream->WriteAsync(buffer.Get(), &bufferWriteOperation)); - - ComPtr strongImageControl(uiElement); - ComPtr strongThis(this); - THROW_IF_FAILED(bufferWriteOperation->put_Completed( - Callback, IAsyncOperationWithProgressCompletedHandler>>( - [strongThis, this, bitmapSource, randomAccessStream, strongImageControl, isAutoSize, parentElement, imageContainer, isVisible]( - IAsyncOperationWithProgress* /*operation*/, AsyncStatus /*status*/) -> HRESULT { - randomAccessStream->Seek(0); - RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); - - ComPtr imageSource; - RETURN_IF_FAILED(bitmapSource.As(&imageSource)); - - SetImageSource(strongImageControl.Get(), imageSource.Get()); - - if (isAutoSize) - { - SetAutoSize(strongImageControl.Get(), parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */); - } - - return S_OK; - }) - .Get())); - - m_writeAsyncOperations.push_back(bufferWriteOperation); - *mustHideElement = false; - return; - } - - // Otherwise, no resolver... - if ((m_enableXamlImageHandling) || (m_listeners.size() == 0)) - { - // If we've been explicitly told to let Xaml handle the image loading, or there are - // no listeners waiting on the image load callbacks, use Xaml to load the images - ComPtr bitmapImage = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); - THROW_IF_FAILED(bitmapImage->put_UriSource(imageUrl)); - - ComPtr bitmapImageSource; - THROW_IF_FAILED(bitmapImage.As(&bitmapImageSource)); - SetImageSource(uiElement, bitmapImageSource.Get(), stretch); - - if (isAutoSize) - { - SetAutoSize(uiElement, parentElement, imageContainer, isVisible, true /* imageFiresOpenEvent */); - } - } - else - { - PopulateImageFromUrlAsync(imageUrl, uiElement); - } - } - - template - void XamlBuilder::PopulateImageFromUrlAsync(_In_ IUriRuntimeClass* imageUrl, _In_ T* imageControl) - { - // Create the HttpClient to load the image stream - ComPtr httpBaseProtocolFilter = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_Web_Http_Filters_HttpBaseProtocolFilter)); - THROW_IF_FAILED(httpBaseProtocolFilter->put_AllowUI(false)); - ComPtr httpFilter; - THROW_IF_FAILED(httpBaseProtocolFilter.As(&httpFilter)); - ComPtr httpClient; - ComPtr httpClientFactory; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Web_Http_HttpClient).Get(), - httpClientFactory.ReleaseAndGetAddressOf())); - THROW_IF_FAILED(httpClientFactory->Create(httpFilter.Get(), httpClient.ReleaseAndGetAddressOf())); - - // Create a BitmapImage to hold the image data. We use BitmapImage in order to allow - // the tracker to subscribe to the ImageLoaded/Failed events - ComPtr bitmapImage = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage)); - m_imageLoadTracker.TrackBitmapImage(bitmapImage.Get()); - THROW_IF_FAILED(bitmapImage->put_CreateOptions(BitmapCreateOptions::BitmapCreateOptions_None)); - ComPtr bitmapSource; - bitmapImage.As(&bitmapSource); - ComPtr> getStreamOperation; - THROW_IF_FAILED(httpClient->GetInputStreamAsync(imageUrl, &getStreamOperation)); - - ComPtr strongImageControl(imageControl); - ComPtr strongThis(this); - THROW_IF_FAILED(getStreamOperation->put_Completed( - Callback, IAsyncOperationWithProgressCompletedHandler>>( - [strongThis, this, bitmapSource, strongImageControl, bitmapImage]( - IAsyncOperationWithProgress* operation, AsyncStatus status) -> HRESULT { - if (status == AsyncStatus::Completed) - { - // Load the image stream into an in memory random access stream, which is what - // SetSource needs - ComPtr imageStream; - RETURN_IF_FAILED(operation->GetResults(&imageStream)); - ComPtr randomAccessStream = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream)); - ComPtr outputStream; - RETURN_IF_FAILED(randomAccessStream.As(&outputStream)); - ComPtr> copyStreamOperation; - RETURN_IF_FAILED(m_randomAccessStreamStatics->CopyAsync(imageStream.Get(), outputStream.Get(), ©StreamOperation)); - - m_copyStreamOperations.push_back(copyStreamOperation); - return copyStreamOperation->put_Completed( - Callback, IAsyncOperationWithProgressCompletedHandler>>( - [strongThis, this, bitmapSource, randomAccessStream, strongImageControl]( - IAsyncOperationWithProgress* /*operation*/, AsyncStatus /*status*/) -> HRESULT { - randomAccessStream->Seek(0); - RETURN_IF_FAILED(bitmapSource->SetSource(randomAccessStream.Get())); - - ComPtr imageSource; - RETURN_IF_FAILED(bitmapSource.As(&imageSource)); - - SetImageSource(strongImageControl.Get(), imageSource.Get()); - return S_OK; - }) - .Get()); - } - else - { - m_imageLoadTracker.MarkFailedLoadBitmapImage(bitmapImage.Get()); - return S_OK; - } - }) - .Get())); - m_getStreamOperations.push_back(getStreamOperation); + ComPtr rootUIElement; + RETURN_IF_FAILED(rootElement.As(&rootUIElement)); + *rootElementResult = rootUIElement.Detach(); + return S_OK; } + CATCH_RETURN; void XamlBuilder::FireAllImagesLoaded() { @@ -848,3704 +335,76 @@ namespace AdaptiveNamespace } } - static HRESULT AddRenderedControl(_In_ IUIElement* newControl, - _In_ IAdaptiveCardElement* element, - _In_ IPanel* parentPanel, - _In_ IUIElement* separator, - _In_ IColumnDefinition* columnDefinition, - std::function childCreatedCallback) + HRESULT XamlBuilder::BuildPanelChildren(_In_ IVector* children, + _In_ IPanel* parentPanel, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + std::function childCreatedCallback) noexcept { - if (newControl != nullptr) - { - boolean isVisible; - RETURN_IF_FAILED(element->get_IsVisible(&isVisible)); - - if (!isVisible) - { - RETURN_IF_FAILED(newControl->put_Visibility(Visibility_Collapsed)); - } + int iElement = 0; + unsigned int childrenSize; + RETURN_IF_FAILED(children->get_Size(&childrenSize)); + boolean ancestorHasFallback; + RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); - ComPtr localControl(newControl); - ComPtr newControlAsFrameworkElement; - RETURN_IF_FAILED(localControl.As(&newControlAsFrameworkElement)); + ComPtr featureRegistration; + RETURN_IF_FAILED(renderContext->get_FeatureRegistration(&featureRegistration)); + ComPtr featureRegistrationImpl = PeekInnards(featureRegistration); + std::shared_ptr sharedFeatureRegistration = featureRegistrationImpl->GetSharedFeatureRegistration(); - HString id; - RETURN_IF_FAILED(element->get_Id(id.GetAddressOf())); + HRESULT hr = XamlHelpers::IterateOverVectorWithFailure(children, ancestorHasFallback, [&](IAdaptiveCardElement* element) { + HRESULT hr = S_OK; - if (id.IsValid()) - { - RETURN_IF_FAILED(newControlAsFrameworkElement->put_Name(id.Get())); - } + // Get fallback state + ABI::AdaptiveNamespace::FallbackType elementFallback; + RETURN_IF_FAILED(element->get_FallbackType(&elementFallback)); + const bool elementHasFallback = (elementFallback != FallbackType_None); + RETURN_IF_FAILED(renderArgs->put_AncestorHasFallback(elementHasFallback || ancestorHasFallback)); - ComPtr tagContent; - RETURN_IF_FAILED(MakeAndInitialize(&tagContent, element, parentPanel, separator, columnDefinition, isVisible)); - RETURN_IF_FAILED(newControlAsFrameworkElement->put_Tag(tagContent.Get())); + // Check to see if element's requirements are being met + bool requirementsMet; + RETURN_IF_FAILED(MeetsRequirements(element, featureRegistration.Get(), &requirementsMet)); + hr = requirementsMet ? S_OK : E_PERFORM_FALLBACK; - ABI::AdaptiveNamespace::HeightType heightType{}; - RETURN_IF_FAILED(element->get_Height(&heightType)); - XamlHelpers::AppendXamlElementToPanel(newControl, parentPanel, heightType); + // Get element renderer + ComPtr elementRenderers; + RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + ComPtr elementRenderer; + HString elementType; + RETURN_IF_FAILED(element->get_ElementTypeString(elementType.GetAddressOf())); + RETURN_IF_FAILED(elementRenderers->Get(elementType.Get(), &elementRenderer)); - childCreatedCallback(newControl); - } - return S_OK; - } + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - void XamlBuilder::AddSeparatorIfNeeded(int& currentElement, - _In_ IAdaptiveCardElement* element, - _In_ IAdaptiveHostConfig* hostConfig, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IPanel* parentPanel, - _Outptr_ IUIElement** addedSeparator) - { - // First element does not need a separator added - if (currentElement++ > 0) - { - bool needsSeparator; - UINT spacing; - UINT separatorThickness; - ABI::Windows::UI::Color separatorColor; - GetSeparationConfigForElement(element, hostConfig, &spacing, &separatorThickness, &separatorColor, &needsSeparator); - if (needsSeparator) + // If we have a renderer, render the element + ComPtr newControl; + if (SUCCEEDED(hr) && elementRenderer != nullptr) { - auto separator = CreateSeparator(renderContext, spacing, separatorThickness, separatorColor); - XamlHelpers::AppendXamlElementToPanel(separator.Get(), parentPanel); - THROW_IF_FAILED(separator.CopyTo(addedSeparator)); + hr = elementRenderer->Render(element, renderContext, renderArgs, newControl.GetAddressOf()); } - } - } - - static inline HRESULT WarnFallbackString(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - const std::string& warning) - { - HString warningMsg; - RETURN_IF_FAILED(UTF8ToHString(warning, warningMsg.GetAddressOf())); - - RETURN_IF_FAILED( - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::PerformingFallback, warningMsg.Get())); - return S_OK; - } - - static inline HRESULT WarnForFallbackContentElement(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ HSTRING parentElementType, - _In_ HSTRING fallbackElementType) try - { - std::string warning = "Performing fallback for element of type \""; - warning.append(HStringToUTF8(parentElementType)); - warning.append("\" (fallback element type \""); - warning.append(HStringToUTF8(fallbackElementType)); - warning.append("\")"); - - return WarnFallbackString(renderContext, warning); - } - CATCH_RETURN; - static inline HRESULT WarnForFallbackDrop(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ HSTRING elementType) try - { - std::string warning = "Dropping element of type \""; - warning.append(HStringToUTF8(elementType)); - warning.append("\" for fallback"); - - return WarnFallbackString(renderContext, warning); - } - CATCH_RETURN; - - HRESULT SetSeparatorVisibility(_In_ IPanel* parentPanel) - { - // Iterate over the elements in a container and ensure that the correct separators are marked as visible - ComPtr> children; - RETURN_IF_FAILED(parentPanel->get_Children(&children)); - - bool foundPreviousVisibleElement = false; - XamlHelpers::IterateOverVector(children.Get(), [&](IUIElement* child) { - ComPtr localChild(child); - - ComPtr childAsFrameworkElement; - RETURN_IF_FAILED(localChild.As(&childAsFrameworkElement)); - - // Get the tag for the element. The separators themselves will not have tags. - ComPtr tag; - RETURN_IF_FAILED(childAsFrameworkElement->get_Tag(&tag)); - - if (tag) + // If we don't have a renderer, or if the renderer told us to perform fallback, try falling back + if (elementRenderer == nullptr || hr == E_PERFORM_FALLBACK) { - ComPtr elementTagContent; - RETURN_IF_FAILED(tag.As(&elementTagContent)); + RETURN_IF_FAILED(XamlHelpers::RenderFallback(element, renderContext, renderArgs, &newControl)); + } + // If we got a control, add a separator if needed and the control to the parent panel + if (newControl != nullptr) + { ComPtr separator; - RETURN_IF_FAILED(elementTagContent->get_Separator(&separator)); + XamlHelpers::AddSeparatorIfNeeded(iElement, element, hostConfig.Get(), renderContext, parentPanel, &separator); - Visibility visibility; - RETURN_IF_FAILED(child->get_Visibility(&visibility)); - - boolean expectedVisibility{}; - RETURN_IF_FAILED(elementTagContent->get_ExpectedVisibility(&expectedVisibility)); - - if (separator) - { - if (!expectedVisibility || !foundPreviousVisibleElement) - { - // If the element is collapsed, or if it's the first visible element, collapse the separator - // Images are hidden while they are retrieved, we shouldn't hide the separator - RETURN_IF_FAILED(separator->put_Visibility(Visibility_Collapsed)); - } - else - { - // Otherwise show the separator - RETURN_IF_FAILED(separator->put_Visibility(Visibility_Visible)); - } - } - - foundPreviousVisibleElement |= (visibility == Visibility_Visible); + RETURN_IF_FAILED(XamlHelpers::AddRenderedControl(newControl.Get(), element, parentPanel, separator.Get(), nullptr, childCreatedCallback)); } - return S_OK; + // Revert the ancestorHasFallback value + renderArgs->put_AncestorHasFallback(ancestorHasFallback); + return hr; }); - return S_OK; - } - - HRESULT XamlBuilder::RenderFallback(_In_ IAdaptiveCardElement* currentElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) - { - ComPtr elementRenderers; - RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - - ABI::AdaptiveNamespace::FallbackType elementFallback; - RETURN_IF_FAILED(currentElement->get_FallbackType(&elementFallback)); - - HString elementType; - RETURN_IF_FAILED(currentElement->get_ElementTypeString(elementType.GetAddressOf())); - - bool fallbackHandled = false; - ComPtr fallbackControl; - switch (elementFallback) - { - case ABI::AdaptiveNamespace::FallbackType::Content: - { - // We have content, get the type of the fallback element - ComPtr fallbackElement; - RETURN_IF_FAILED(currentElement->get_FallbackContent(&fallbackElement)); - - HString fallbackElementType; - RETURN_IF_FAILED(fallbackElement->get_ElementTypeString(fallbackElementType.GetAddressOf())); - - RETURN_IF_FAILED(WarnForFallbackContentElement(renderContext, elementType.Get(), fallbackElementType.Get())); - - // Try to render the fallback element - ComPtr fallbackElementRenderer; - RETURN_IF_FAILED(elementRenderers->Get(fallbackElementType.Get(), &fallbackElementRenderer)); - HRESULT hr = E_PERFORM_FALLBACK; - - if (fallbackElementRenderer) - { - // perform this element's fallback - hr = fallbackElementRenderer->Render(fallbackElement.Get(), renderContext, renderArgs, &fallbackControl); - } - - if (hr == E_PERFORM_FALLBACK) - { - // The fallback content told us to fallback, make a recursive call to this method - RETURN_IF_FAILED(RenderFallback(fallbackElement.Get(), renderContext, renderArgs, &fallbackControl)); - } - else - { - // Check the non-fallback return value from the render call - RETURN_IF_FAILED(hr); - } - - // We handled the fallback content - fallbackHandled = true; - break; - } - case ABI::AdaptiveNamespace::FallbackType::Drop: - { - // If the fallback is drop, nothing to do but warn - RETURN_IF_FAILED(WarnForFallbackDrop(renderContext, elementType.Get())); - fallbackHandled = true; - break; - } - case ABI::AdaptiveNamespace::FallbackType::None: - default: - { - break; - } - } - - if (fallbackHandled) - { - // We did it, copy out the result if any - RETURN_IF_FAILED(fallbackControl.CopyTo(result)); - return S_OK; - } - else - { - // We didn't do it, can our ancestor? - boolean ancestorHasFallback; - RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); - - if (!ancestorHasFallback) - { - // standard unknown element handling - std::wstring errorString = L"No Renderer found for type: "; - errorString += elementType.GetRawBuffer(nullptr); - RETURN_IF_FAILED(renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, - HStringReference(errorString.c_str()).Get())); - return S_OK; - } - else - { - return E_PERFORM_FALLBACK; - } - } - } - - HRESULT XamlBuilder::BuildPanelChildren(_In_ IVector* children, - _In_ IPanel* parentPanel, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - std::function childCreatedCallback) - { - int iElement = 0; - unsigned int childrenSize; - RETURN_IF_FAILED(children->get_Size(&childrenSize)); - boolean ancestorHasFallback; - RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); - - ComPtr featureRegistration; - RETURN_IF_FAILED(renderContext->get_FeatureRegistration(&featureRegistration)); - ComPtr featureRegistrationImpl = PeekInnards(featureRegistration); - std::shared_ptr sharedFeatureRegistration = featureRegistrationImpl->GetSharedFeatureRegistration(); - - HRESULT hr = XamlHelpers::IterateOverVectorWithFailure(children, ancestorHasFallback, [&](IAdaptiveCardElement* element) { - HRESULT hr = S_OK; - - // Get fallback state - ABI::AdaptiveNamespace::FallbackType elementFallback; - RETURN_IF_FAILED(element->get_FallbackType(&elementFallback)); - const bool elementHasFallback = (elementFallback != FallbackType_None); - RETURN_IF_FAILED(renderArgs->put_AncestorHasFallback(elementHasFallback || ancestorHasFallback)); - - // Check to see if element's requirements are being met - bool requirementsMet; - RETURN_IF_FAILED(MeetsRequirements(element, featureRegistration.Get(), &requirementsMet)); - hr = requirementsMet ? S_OK : E_PERFORM_FALLBACK; - - // Get element renderer - ComPtr elementRenderers; - RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - ComPtr elementRenderer; - HString elementType; - RETURN_IF_FAILED(element->get_ElementTypeString(elementType.GetAddressOf())); - RETURN_IF_FAILED(elementRenderers->Get(elementType.Get(), &elementRenderer)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - // If we have a renderer, render the element - ComPtr newControl; - if (SUCCEEDED(hr) && elementRenderer != nullptr) - { - hr = elementRenderer->Render(element, renderContext, renderArgs, newControl.GetAddressOf()); - } - - // If we don't have a renderer, or if the renderer told us to perform fallback, try falling back - if (elementRenderer == nullptr || hr == E_PERFORM_FALLBACK) - { - RETURN_IF_FAILED(RenderFallback(element, renderContext, renderArgs, &newControl)); - } - - // If we got a control, add a separator if needed and the control to the parent panel - if (newControl != nullptr) - { - ComPtr separator; - AddSeparatorIfNeeded(iElement, element, hostConfig.Get(), renderContext, parentPanel, &separator); - - RETURN_IF_FAILED(AddRenderedControl(newControl.Get(), element, parentPanel, separator.Get(), nullptr, childCreatedCallback)); - } - - // Revert the ancestorHasFallback value - renderArgs->put_AncestorHasFallback(ancestorHasFallback); - return hr; - }); - - RETURN_IF_FAILED(SetSeparatorVisibility(parentPanel)); + RETURN_IF_FAILED(XamlHelpers::SetSeparatorVisibility(parentPanel)); return hr; } - - HRESULT XamlBuilder::BuildShowCard(_In_ IAdaptiveCard* showCard, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - bool isBottomActionBar, - _Outptr_ IUIElement** uiShowCard) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(&actionsConfig)); - - ComPtr showCardActionConfig; - RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); - - ABI::AdaptiveNamespace::ContainerStyle showCardConfigStyle; - RETURN_IF_FAILED(showCardActionConfig->get_Style(&showCardConfigStyle)); - - boolean wasInShowCard; - RETURN_IF_FAILED(renderArgs->get_IsInShowCard(&wasInShowCard)); - RETURN_IF_FAILED(renderArgs->put_IsInShowCard(true)); - - ComPtr localUiShowCard; - RETURN_IF_FAILED(BuildXamlTreeFromAdaptiveCard(showCard, localUiShowCard.GetAddressOf(), renderContext, nullptr, showCardConfigStyle)); - - RETURN_IF_FAILED(renderArgs->put_IsInShowCard(wasInShowCard)); - - ComPtr showCardGrid; - RETURN_IF_FAILED(localUiShowCard.As(&showCardGrid)); - - // Set the padding - ComPtr spacingConfig; - RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 padding; - RETURN_IF_FAILED(spacingConfig->get_Padding(&padding)); - - ABI::AdaptiveNamespace::ActionMode showCardActionMode; - RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); - - // Set the top margin - ComPtr showCardFrameworkElement; - RETURN_IF_FAILED(localUiShowCard.As(&showCardFrameworkElement)); - - UINT32 inlineTopMargin; - RETURN_IF_FAILED(showCardActionConfig->get_InlineTopMargin(&inlineTopMargin)); - - double sideMargin = (double)padding * -1; - double topMargin = isBottomActionBar ? inlineTopMargin + padding : inlineTopMargin; - double bottomMargin = isBottomActionBar ? (double)padding * -1 : 0; - - Thickness margin = {sideMargin, topMargin, sideMargin, bottomMargin}; - RETURN_IF_FAILED(showCardFrameworkElement->put_Margin(margin)); - - ComPtr showCardUIElement; - RETURN_IF_FAILED(localUiShowCard.As(&showCardUIElement)); - - // Set the visibility as Collapsed until the action is triggered - RETURN_IF_FAILED(showCardUIElement->put_Visibility(Visibility_Collapsed)); - - *uiShowCard = showCardUIElement.Detach(); - return S_OK; - } - - void XamlBuilder::ArrangeButtonContent(_In_ IAdaptiveActionElement* action, - _In_ IAdaptiveActionsConfig* actionsConfig, - _In_ IAdaptiveRenderContext* renderContext, - ABI::AdaptiveNamespace::ContainerStyle containerStyle, - _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, - bool allActionsHaveIcons, - _In_ IButton* button) - { - HString title; - THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); - - HSTRING iconUrl; - THROW_IF_FAILED(action->get_IconUrl(&iconUrl)); - - ComPtr localButton(button); - - // Check if the button has an iconUrl - if (iconUrl != nullptr) - { - // Get icon configs - ABI::AdaptiveNamespace::IconPlacement iconPlacement; - UINT32 iconSize; - - THROW_IF_FAILED(actionsConfig->get_IconPlacement(&iconPlacement)); - THROW_IF_FAILED(actionsConfig->get_IconSize(&iconSize)); - - // Define the alignment for the button contents - ComPtr buttonContentsStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - - // Create image and add it to the button - ComPtr adaptiveImage; - THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - - adaptiveImage->put_Url(iconUrl); - adaptiveImage->put_HorizontalAlignment(ABI::AdaptiveNamespace::HAlignment::Center); - - ComPtr adaptiveCardElement; - THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); - ComPtr childRenderArgs; - THROW_IF_FAILED( - MakeAndInitialize(&childRenderArgs, containerStyle, buttonContentsStackPanel.Get(), nullptr)); - - ComPtr elementRenderers; - THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - - ComPtr buttonIcon; - ComPtr elementRenderer; - THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &elementRenderer)); - if (elementRenderer != nullptr) - { - elementRenderer->Render(adaptiveCardElement.Get(), renderContext, childRenderArgs.Get(), &buttonIcon); - if (buttonIcon == nullptr) - { - XamlHelpers::SetContent(localButton.Get(), title.Get()); - return; - } - } - - // Create title text block - ComPtr buttonText = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); - THROW_IF_FAILED(buttonText->put_Text(title.Get())); - THROW_IF_FAILED(buttonText->put_TextAlignment(TextAlignment::TextAlignment_Center)); - - // Handle different arrangements inside button - ComPtr buttonIconAsFrameworkElement; - THROW_IF_FAILED(buttonIcon.As(&buttonIconAsFrameworkElement)); - ComPtr separator; - if (iconPlacement == ABI::AdaptiveNamespace::IconPlacement::AboveTitle && allActionsHaveIcons) - { - THROW_IF_FAILED(buttonContentsStackPanel->put_Orientation(Orientation::Orientation_Vertical)); - - // Set icon height to iconSize (aspect ratio is automatically maintained) - THROW_IF_FAILED(buttonIconAsFrameworkElement->put_Height(iconSize)); - } - else - { - THROW_IF_FAILED(buttonContentsStackPanel->put_Orientation(Orientation::Orientation_Horizontal)); - - // Add event to the image to resize itself when the textblock is rendered - ComPtr buttonIconAsImage; - THROW_IF_FAILED(buttonIcon.As(&buttonIconAsImage)); - - EventRegistrationToken eventToken; - THROW_IF_FAILED(buttonIconAsImage->add_ImageOpened( - Callback([buttonIconAsFrameworkElement, - buttonText](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - ComPtr buttonTextAsFrameworkElement; - RETURN_IF_FAILED(buttonText.As(&buttonTextAsFrameworkElement)); - - return SetMatchingHeight(buttonIconAsFrameworkElement.Get(), buttonTextAsFrameworkElement.Get()); - }) - .Get(), - &eventToken)); - - // Only add spacing when the icon must be located at the left of the title - UINT spacingSize; - THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig, ABI::AdaptiveNamespace::Spacing::Default, &spacingSize)); - - ABI::Windows::UI::Color color = {0}; - separator = CreateSeparator(renderContext, spacingSize, spacingSize, color, false); - } - - ComPtr buttonContentsPanel; - THROW_IF_FAILED(buttonContentsStackPanel.As(&buttonContentsPanel)); - - // Add image to stack panel - XamlHelpers::AppendXamlElementToPanel(buttonIcon.Get(), buttonContentsPanel.Get()); - - // Add separator to stack panel - if (separator != nullptr) - { - XamlHelpers::AppendXamlElementToPanel(separator.Get(), buttonContentsPanel.Get()); - } - - // Add text to stack panel - XamlHelpers::AppendXamlElementToPanel(buttonText.Get(), buttonContentsPanel.Get()); - - // Finally, put the stack panel inside the final button - ComPtr buttonContentControl; - THROW_IF_FAILED(localButton.As(&buttonContentControl)); - THROW_IF_FAILED(buttonContentControl->put_Content(buttonContentsPanel.Get())); - } - else - { - XamlHelpers::SetContent(localButton.Get(), title.Get()); - } - } - - HRESULT HandleColumnWidth(_In_ IAdaptiveColumn* column, boolean isVisible, _In_ IColumnDefinition* columnDefinition) - { - HString adaptiveColumnWidth; - RETURN_IF_FAILED(column->get_Width(adaptiveColumnWidth.GetAddressOf())); - - INT32 isStretchResult; - RETURN_IF_FAILED(WindowsCompareStringOrdinal(adaptiveColumnWidth.Get(), HStringReference(L"stretch").Get(), &isStretchResult)); - const boolean isStretch = (isStretchResult == 0); - - INT32 isAutoResult; - RETURN_IF_FAILED(WindowsCompareStringOrdinal(adaptiveColumnWidth.Get(), HStringReference(L"auto").Get(), &isAutoResult)); - const boolean isAuto = (isAutoResult == 0); - - double widthAsDouble = _wtof(adaptiveColumnWidth.GetRawBuffer(nullptr)); - UINT32 pixelWidth = 0; - RETURN_IF_FAILED(column->get_PixelWidth(&pixelWidth)); - - // Valid widths are "auto", "stretch", a pixel width ("50px"), unset, or a value greater than 0 to use as a star value ("2") - const boolean isValidWidth = isAuto || isStretch || pixelWidth || !adaptiveColumnWidth.IsValid() || (widthAsDouble > 0); - - GridLength columnWidth; - if (!isVisible || isAuto || !isValidWidth) - { - // If the column isn't visible, or is set to "auto" or an invalid value ("-1", "foo"), set it to Auto - columnWidth.GridUnitType = GridUnitType::GridUnitType_Auto; - columnWidth.Value = 0; - } - else if (pixelWidth) - { - // If it's visible and pixel width is specified, use pixel width - columnWidth.GridUnitType = GridUnitType::GridUnitType_Pixel; - columnWidth.Value = pixelWidth; - } - else if (isStretch || !adaptiveColumnWidth.IsValid()) - { - // If it's visible and stretch is specified, or width is unset, use stretch with default of 1 - columnWidth.GridUnitType = GridUnitType::GridUnitType_Star; - columnWidth.Value = 1; - } - else - { - // If it's visible and the user specified a valid non-pixel width, use that as a star width - columnWidth.GridUnitType = GridUnitType::GridUnitType_Star; - columnWidth.Value = _wtof(adaptiveColumnWidth.GetRawBuffer(nullptr)); - } - - RETURN_IF_FAILED(columnDefinition->put_Width(columnWidth)); - - return S_OK; - } - - HRESULT XamlBuilder::HandleToggleVisibilityClick(_In_ IFrameworkElement* cardFrameworkElement, _In_ IAdaptiveActionElement* action) - { - ComPtr localAction(action); - ComPtr toggleAction; - RETURN_IF_FAILED(localAction.As(&toggleAction)); - - ComPtr> targets; - RETURN_IF_FAILED(toggleAction->get_TargetElements(&targets)); - - ComPtr> targetsIterable; - RETURN_IF_FAILED(targets.As>(&targetsIterable)); - - boolean hasCurrent; - ComPtr> targetIterator; - HRESULT hr = targetsIterable->First(&targetIterator); - RETURN_IF_FAILED(targetIterator->get_HasCurrent(&hasCurrent)); - - std::unordered_set parentPanels; - while (SUCCEEDED(hr) && hasCurrent) - { - ComPtr currentTarget; - RETURN_IF_FAILED(targetIterator->get_Current(¤tTarget)); - - HString toggleId; - RETURN_IF_FAILED(currentTarget->get_ElementId(toggleId.GetAddressOf())); - - ABI::AdaptiveNamespace::IsVisible toggle; - RETURN_IF_FAILED(currentTarget->get_IsVisible(&toggle)); - - ComPtr toggleElement; - RETURN_IF_FAILED(cardFrameworkElement->FindName(toggleId.Get(), &toggleElement)); - - if (toggleElement != nullptr) - { - ComPtr toggleElementAsUIElement; - RETURN_IF_FAILED(toggleElement.As(&toggleElementAsUIElement)); - - ComPtr toggleElementAsFrameworkElement; - RETURN_IF_FAILED(toggleElement.As(&toggleElementAsFrameworkElement)); - - ComPtr tag; - RETURN_IF_FAILED(toggleElementAsFrameworkElement->get_Tag(&tag)); - - ComPtr elementTagContent; - RETURN_IF_FAILED(tag.As(&elementTagContent)); - - Visibility visibilityToSet = Visibility_Visible; - if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleTrue) - { - visibilityToSet = Visibility_Visible; - } - else if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleFalse) - { - visibilityToSet = Visibility_Collapsed; - } - else if (toggle == ABI::AdaptiveNamespace::IsVisible_IsVisibleToggle) - { - boolean currentVisibility{}; - RETURN_IF_FAILED(elementTagContent->get_ExpectedVisibility(¤tVisibility)); - visibilityToSet = (currentVisibility) ? Visibility_Collapsed : Visibility_Visible; - } - - RETURN_IF_FAILED(toggleElementAsUIElement->put_Visibility(visibilityToSet)); - RETURN_IF_FAILED(elementTagContent->set_ExpectedVisibility(visibilityToSet == Visibility_Visible)); - - ComPtr parentPanel; - RETURN_IF_FAILED(elementTagContent->get_ParentPanel(&parentPanel)); - parentPanels.insert(parentPanel.Get()); - - ComPtr cardElement; - RETURN_IF_FAILED(elementTagContent->get_AdaptiveCardElement(&cardElement)); - - // If the element we're toggling is a column, we'll need to change the width on the column definition - ComPtr cardElementAsColumn; - if (SUCCEEDED(cardElement.As(&cardElementAsColumn))) - { - ComPtr columnDefinition; - RETURN_IF_FAILED(elementTagContent->get_ColumnDefinition(&columnDefinition)); - RETURN_IF_FAILED(HandleColumnWidth(cardElementAsColumn.Get(), - (visibilityToSet == Visibility_Visible), - columnDefinition.Get())); - } - } - - hr = targetIterator->MoveNext(&hasCurrent); - } - - for (auto parentPanel : parentPanels) - { - SetSeparatorVisibility(parentPanel); - } - - return S_OK; - } - - HRESULT XamlBuilder::BuildActionSet(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** actionSetControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"ActionSet was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveActionSet; - RETURN_IF_FAILED(cardElement.As(&adaptiveActionSet)); - - ComPtr> actions; - RETURN_IF_FAILED(adaptiveActionSet->get_Actions(&actions)); - - return BuildActionSetHelper(nullptr, adaptiveActionSet.Get(), actions.Get(), renderContext, renderArgs, actionSetControl); - } - - HRESULT XamlBuilder::BuildActions(_In_ IAdaptiveCard* adaptiveCard, - _In_ IVector* children, - _In_ IPanel* bodyPanel, - bool insertSeparator, - _In_ IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); - - // Create a separator between the body and the actions - if (insertSeparator) - { - ABI::AdaptiveNamespace::Spacing spacing; - RETURN_IF_FAILED(actionsConfig->get_Spacing(&spacing)); - - UINT spacingSize; - RETURN_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), spacing, &spacingSize)); - - ABI::Windows::UI::Color color = {0}; - auto separator = CreateSeparator(renderContext, spacingSize, 0, color); - XamlHelpers::AppendXamlElementToPanel(separator.Get(), bodyPanel); - } - - ComPtr actionSetControl; - RETURN_IF_FAILED(BuildActionSetHelper(adaptiveCard, nullptr, children, renderContext, renderArgs, &actionSetControl)); - - XamlHelpers::AppendXamlElementToPanel(actionSetControl.Get(), bodyPanel); - return S_OK; - } - - Thickness XamlBuilder::GetButtonMargin(_In_ IAdaptiveActionsConfig* actionsConfig) - { - UINT32 buttonSpacing; - THROW_IF_FAILED(actionsConfig->get_ButtonSpacing(&buttonSpacing)); - - ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; - THROW_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); - - Thickness buttonMargin = {0, 0, 0, 0}; - if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - buttonMargin.Left = buttonMargin.Right = buttonSpacing / 2; - } - else - { - buttonMargin.Top = buttonMargin.Bottom = buttonSpacing / 2; - } - - return buttonMargin; - } - - HRESULT XamlBuilder::BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_opt_ IAdaptiveActionSet* adaptiveActionSet, - _In_ IVector* children, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _Outptr_ IUIElement** actionSetControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); - - ABI::AdaptiveNamespace::ActionAlignment actionAlignment; - RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); - - ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; - RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); - - // Declare the panel that will host the buttons - ComPtr actionsPanel; - ComPtr> columnDefinitions; - - if (actionAlignment == ABI::AdaptiveNamespace::ActionAlignment::Stretch && - actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - // If stretch alignment and orientation is horizontal, we use a grid with equal column widths to achieve - // stretch behavior. For vertical orientation, we'll still just use a stack panel since the concept of - // stretching buttons height isn't really valid, especially when the height of cards are typically dynamic. - ComPtr actionsGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - RETURN_IF_FAILED(actionsGrid->get_ColumnDefinitions(&columnDefinitions)); - RETURN_IF_FAILED(actionsGrid.As(&actionsPanel)); - } - else - { - // Create a stack panel for the action buttons - ComPtr actionStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - - auto uiOrientation = (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) ? - Orientation::Orientation_Horizontal : - Orientation::Orientation_Vertical; - - RETURN_IF_FAILED(actionStackPanel->put_Orientation(uiOrientation)); - - ComPtr actionsFrameworkElement; - RETURN_IF_FAILED(actionStackPanel.As(&actionsFrameworkElement)); - - switch (actionAlignment) - { - case ABI::AdaptiveNamespace::ActionAlignment::Center: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Left: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Right: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Stretch: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); - break; - } - - // Add the action buttons to the stack panel - RETURN_IF_FAILED(actionStackPanel.As(&actionsPanel)); - } - - Thickness buttonMargin = GetButtonMargin(actionsConfig.Get()); - if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - // Negate the spacing on the sides so the left and right buttons are flush on the side. - // We do NOT remove the margin from the individual button itself, since that would cause - // the equal columns stretch behavior to not have equal columns (since the first and last - // button would be narrower without the same margins as its peers). - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({buttonMargin.Left * -1, 0, buttonMargin.Right * -1, 0})); - } - else - { - // Negate the spacing on the top and bottom so the first and last buttons don't have extra padding - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({0, buttonMargin.Top * -1, 0, buttonMargin.Bottom * -1})); - } - - UINT32 maxActions; - RETURN_IF_FAILED(actionsConfig->get_MaxActions(&maxActions)); - - bool allActionsHaveIcons{true}; - XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { - HSTRING iconUrl; - RETURN_IF_FAILED(child->get_IconUrl(&iconUrl)); - - bool iconUrlIsEmpty = WindowsIsStringEmpty(iconUrl); - if (iconUrlIsEmpty) - { - allActionsHaveIcons = false; - } - return S_OK; - }); - - UINT currentAction = 0; - - RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(allActionsHaveIcons)); - - std::shared_ptr>> allShowCards = std::make_shared>>(); - ComPtr showCardsStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - ComPtr gridStatics; - RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); - XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { - if (currentAction < maxActions) - { - // Render each action using the registered renderer - ComPtr action(child); - ComPtr actionRegistration; - RETURN_IF_FAILED(renderContext->get_ActionRenderers(&actionRegistration)); - - ComPtr renderer; - while (!renderer) - { - HString actionTypeString; - RETURN_IF_FAILED(action->get_ActionTypeString(actionTypeString.GetAddressOf())); - RETURN_IF_FAILED(actionRegistration->Get(actionTypeString.Get(), &renderer)); - if (!renderer) - { - ABI::AdaptiveNamespace::FallbackType actionFallbackType; - action->get_FallbackType(&actionFallbackType); - switch (actionFallbackType) - { - case ABI::AdaptiveNamespace::FallbackType::Drop: - { - RETURN_IF_FAILED(WarnForFallbackDrop(renderContext, actionTypeString.Get())); - return S_OK; - } - - case ABI::AdaptiveNamespace::FallbackType::Content: - { - ComPtr actionFallback; - RETURN_IF_FAILED(action->get_FallbackContent(&actionFallback)); - - HString fallbackTypeString; - RETURN_IF_FAILED(actionFallback->get_ActionTypeString(fallbackTypeString.GetAddressOf())); - RETURN_IF_FAILED( - WarnForFallbackContentElement(renderContext, actionTypeString.Get(), fallbackTypeString.Get())); - - action = actionFallback; - break; - } - - case ABI::AdaptiveNamespace::FallbackType::None: - default: - return E_FAIL; - } - } - } - - ComPtr actionControl; - RETURN_IF_FAILED(renderer->Render(action.Get(), renderContext, renderArgs, &actionControl)); - - XamlHelpers::AppendXamlElementToPanel(actionControl.Get(), actionsPanel.Get()); - - ABI::AdaptiveNamespace::ActionType actionType; - RETURN_IF_FAILED(action->get_ActionType(&actionType)); - - // Build inline show cards if needed - if (actionType == ABI::AdaptiveNamespace::ActionType_ShowCard) - { - ComPtr uiShowCard; - - ComPtr showCardActionConfig; - RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); - - ABI::AdaptiveNamespace::ActionMode showCardActionMode; - RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); - - if (showCardActionMode == ABI::AdaptiveNamespace::ActionMode::Inline) - { - ComPtr showCardAction; - RETURN_IF_FAILED(action.As(&showCardAction)); - - ComPtr showCard; - RETURN_IF_FAILED(showCardAction->get_Card(&showCard)); - - RETURN_IF_FAILED(BuildShowCard( - showCard.Get(), renderContext, renderArgs, (adaptiveActionSet == nullptr), uiShowCard.GetAddressOf())); - - ComPtr showCardsPanel; - RETURN_IF_FAILED(showCardsStackPanel.As(&showCardsPanel)); - XamlHelpers::AppendXamlElementToPanel(uiShowCard.Get(), showCardsPanel.Get()); - - if (adaptiveActionSet) - { - RETURN_IF_FAILED( - renderContext->AddInlineShowCard(adaptiveActionSet, showCardAction.Get(), uiShowCard.Get())); - } - else - { - ComPtr contextImpl = - PeekInnards(renderContext); - - RETURN_IF_FAILED( - contextImpl->AddInlineShowCard(adaptiveCard, showCardAction.Get(), uiShowCard.Get())); - } - } - } - - if (columnDefinitions != nullptr) - { - // If using the equal width columns, we'll add a column and assign the column - ComPtr columnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - RETURN_IF_FAILED(columnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Star})); - RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); - - ComPtr actionFrameworkElement; - THROW_IF_FAILED(actionControl.As(&actionFrameworkElement)); - THROW_IF_FAILED(gridStatics->SetColumn(actionFrameworkElement.Get(), currentAction)); - } - } - else - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::MaxActionsExceeded, - HStringReference(L"Some actions were not rendered due to exceeding the maximum number of actions allowed") - .Get()); - } - currentAction++; - return S_OK; - }); - - // Reset icon placement value - RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(false)); - - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Actions", actionsPanelAsFrameworkElement.Get())); - - ComPtr actionSet = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - ComPtr actionSetAsPanel; - actionSet.As(&actionSetAsPanel); - - // Add buttons and show cards to panel - XamlHelpers::AppendXamlElementToPanel(actionsPanel.Get(), actionSetAsPanel.Get()); - XamlHelpers::AppendXamlElementToPanel(showCardsStackPanel.Get(), actionSetAsPanel.Get()); - - return actionSetAsPanel.CopyTo(actionSetControl); - } - - HRESULT XamlBuilder::BuildAction(_In_ IAdaptiveActionElement* adaptiveActionElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _Outptr_ IUIElement** actionControl) - { - // Render a button for the action - ComPtr action(adaptiveActionElement); - ComPtr button = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); - - ComPtr buttonFrameworkElement; - RETURN_IF_FAILED(button.As(&buttonFrameworkElement)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); - - Thickness buttonMargin = GetButtonMargin(actionsConfig.Get()); - RETURN_IF_FAILED(buttonFrameworkElement->put_Margin(buttonMargin)); - - ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; - RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); - - ABI::AdaptiveNamespace::ActionAlignment actionAlignment; - RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); - - if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - // For horizontal alignment, we always use stretch - RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment( - ABI::Windows::UI::Xaml::HorizontalAlignment::HorizontalAlignment_Stretch)); - } - else - { - switch (actionAlignment) - { - case ABI::AdaptiveNamespace::ActionAlignment::Center: - RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Left: - RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Right: - RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Stretch: - RETURN_IF_FAILED(buttonFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); - break; - } - } - - ABI::AdaptiveNamespace::ContainerStyle containerStyle; - renderArgs->get_ContainerStyle(&containerStyle); - - boolean allowAboveTitleIconPlacement; - RETURN_IF_FAILED(renderArgs->get_AllowAboveTitleIconPlacement(&allowAboveTitleIconPlacement)); - - ArrangeButtonContent(action.Get(), - actionsConfig.Get(), - renderContext, - containerStyle, - hostConfig.Get(), - allowAboveTitleIconPlacement, - button.Get()); - - ABI::AdaptiveNamespace::ActionType actionType; - RETURN_IF_FAILED(action->get_ActionType(&actionType)); - - ComPtr showCardActionConfig; - RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); - ABI::AdaptiveNamespace::ActionMode showCardActionMode; - RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); - std::shared_ptr>> allShowCards = std::make_shared>>(); - - // Add click handler which calls IAdaptiveActionInvoker::SendActionEvent - ComPtr buttonBase; - RETURN_IF_FAILED(button.As(&buttonBase)); - - ComPtr actionInvoker; - RETURN_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); - EventRegistrationToken clickToken; - RETURN_IF_FAILED(buttonBase->add_Click(Callback( - [action, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - return actionInvoker->SendActionEvent(action.Get()); - }) - .Get(), - &clickToken)); - - RETURN_IF_FAILED(HandleActionStyling(adaptiveActionElement, buttonFrameworkElement.Get(), renderContext)); - - ComPtr buttonAsUIElement; - RETURN_IF_FAILED(button.As(&buttonAsUIElement)); - *actionControl = buttonAsUIElement.Detach(); - return S_OK; - } - - HRESULT XamlBuilder::HandleActionStyling(_In_ IAdaptiveActionElement* adaptiveActionElement, - _In_ IFrameworkElement* buttonFrameworkElement, - _In_ IAdaptiveRenderContext* renderContext) - { - HString actionSentiment; - RETURN_IF_FAILED(adaptiveActionElement->get_Style(actionSentiment.GetAddressOf())); - - INT32 isSentimentPositive{}, isSentimentDestructive{}, isSentimentDefault{}; - - ComPtr resourceDictionary; - RETURN_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); - ComPtr styleToApply; - - ComPtr contextImpl = - PeekInnards(renderContext); - - if ((SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"default").Get(), &isSentimentDefault)) && - (isSentimentDefault == 0)) || - WindowsIsStringEmpty(actionSentiment.Get())) - { - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Action", buttonFrameworkElement)); - } - else if (SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"positive").Get(), &isSentimentPositive)) && - (isSentimentPositive == 0)) - { - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), L"Adaptive.Action.Positive", &styleToApply))) - { - RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); - } - else - { - // By default, set the action background color to accent color - ComPtr actionSentimentDictionary = contextImpl->GetDefaultActionSentimentDictionary(); - - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(actionSentimentDictionary.Get(), - L"PositiveActionDefaultStyle", - styleToApply.GetAddressOf()))) - { - RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); - } - } - } - else if (SUCCEEDED(WindowsCompareStringOrdinal(actionSentiment.Get(), HStringReference(L"destructive").Get(), &isSentimentDestructive)) && - (isSentimentDestructive == 0)) - { - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), L"Adaptive.Action.Destructive", &styleToApply))) - { - RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); - } - else - { - // By default, set the action text color to attention color - ComPtr actionSentimentDictionary = contextImpl->GetDefaultActionSentimentDictionary(); - - if (SUCCEEDED(TryGetResourceFromResourceDictionaries(actionSentimentDictionary.Get(), - L"DestructiveActionDefaultStyle", - styleToApply.GetAddressOf()))) - { - RETURN_IF_FAILED(buttonFrameworkElement->put_Style(styleToApply.Get())); - } - } - } - else - { - HString actionSentimentStyle; - RETURN_IF_FAILED(WindowsConcatString(HStringReference(L"Adaptive.Action.").Get(), - actionSentiment.Get(), - actionSentimentStyle.GetAddressOf())); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, - StringToWstring(HStringToUTF8(actionSentimentStyle.Get())), - buttonFrameworkElement)); - } - return S_OK; - } - - void XamlBuilder::ApplyMarginToXamlElement(_In_ IAdaptiveHostConfig* hostConfig, _In_ IFrameworkElement* element) - { - ComPtr localElement(element); - ComPtr spacingConfig; - THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 padding; - spacingConfig->get_Padding(&padding); - Thickness margin = {(double)padding, (double)padding, (double)padding, (double)padding}; - - THROW_IF_FAILED(localElement->put_Margin(margin)); - } - - void XamlBuilder::GetSeparationConfigForElement(_In_ IAdaptiveCardElement* cardElement, - _In_ IAdaptiveHostConfig* hostConfig, - _Out_ UINT* spacing, - _Out_ UINT* separatorThickness, - _Out_ ABI::Windows::UI::Color* separatorColor, - _Out_ bool* needsSeparator) - { - ABI::AdaptiveNamespace::Spacing elementSpacing; - THROW_IF_FAILED(cardElement->get_Spacing(&elementSpacing)); - - UINT localSpacing; - THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig, elementSpacing, &localSpacing)); - - boolean hasSeparator; - THROW_IF_FAILED(cardElement->get_Separator(&hasSeparator)); - - ABI::Windows::UI::Color localColor = {0}; - UINT localThickness = 0; - if (hasSeparator) - { - ComPtr separatorConfig; - THROW_IF_FAILED(hostConfig->get_Separator(&separatorConfig)); - - THROW_IF_FAILED(separatorConfig->get_LineColor(&localColor)); - THROW_IF_FAILED(separatorConfig->get_LineThickness(&localThickness)); - } - - *needsSeparator = hasSeparator || (elementSpacing != ABI::AdaptiveNamespace::Spacing::None); - - *spacing = localSpacing; - *separatorThickness = localThickness; - *separatorColor = localColor; - } - - HRESULT XamlBuilder::BuildRichTextBlock(ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - ABI::Windows::UI::Xaml::IUIElement** textBlockControl) - { - // Create the top level rich text block and set it's properties - ComPtr xamlRichTextBlock = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RichTextBlock)); - - ComPtr localAdaptiveCardElement(adaptiveCardElement); - ComPtr adaptiveRichTextBlock; - RETURN_IF_FAILED(localAdaptiveCardElement.As(&adaptiveRichTextBlock)); - - // Set the horizontal Alingment - RETURN_IF_FAILED(SetHorizontalAlignment(adaptiveRichTextBlock.Get(), xamlRichTextBlock.Get())); - - // Get the highlighters - ComPtr xamlRichTextBlock5; - RETURN_IF_FAILED(xamlRichTextBlock.As(&xamlRichTextBlock5)); - - ComPtr> textHighlighters; - RETURN_IF_FAILED(xamlRichTextBlock5->get_TextHighlighters(&textHighlighters)); - - // Add a paragraph for the inlines - ComPtr> xamlBlocks; - RETURN_IF_FAILED(xamlRichTextBlock->get_Blocks(&xamlBlocks)); - - ComPtr xamlParagraph = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Documents_Paragraph)); - - ComPtr paragraphAsBlock; - RETURN_IF_FAILED(xamlParagraph.As(¶graphAsBlock)); - RETURN_IF_FAILED(xamlBlocks->Append(paragraphAsBlock.Get())); - - // Add the Inlines - ComPtr> xamlInlines; - RETURN_IF_FAILED(xamlParagraph->get_Inlines(&xamlInlines)); - - ComPtr> adaptiveInlines; - RETURN_IF_FAILED(adaptiveRichTextBlock->get_Inlines(&adaptiveInlines)); - - UINT currentOffset = 0; - XamlHelpers::IterateOverVector(adaptiveInlines.Get(), [&](IAdaptiveInline* adaptiveInline) { - // We only support TextRun inlines for now - ComPtr localInline(adaptiveInline); - ComPtr adaptiveTextRun; - RETURN_IF_FAILED(localInline.As(&adaptiveTextRun)); - - ComPtr selectAction; - RETURN_IF_FAILED(adaptiveTextRun->get_SelectAction(&selectAction)); - - ComPtr adaptiveTextElement; - RETURN_IF_FAILED(localInline.As(&adaptiveTextElement)); - - HString text; - RETURN_IF_FAILED(adaptiveTextElement->get_Text(text.GetAddressOf())); - - boolean isStrikethrough{false}; - RETURN_IF_FAILED(adaptiveTextRun->get_Strikethrough(&isStrikethrough)); - - boolean isItalic{false}; - RETURN_IF_FAILED(adaptiveTextRun->get_Italic(&isItalic)); - - boolean isUnderline{}; - RETURN_IF_FAILED(adaptiveTextRun->get_Underline(&isUnderline)); - - UINT inlineLength; - if (selectAction != nullptr) - { - // If there's a select action, create a hyperlink that triggers the action - ComPtr hyperlink = - XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Documents_Hyperlink)); - - ComPtr actionInvoker; - renderContext->get_ActionInvoker(&actionInvoker); - - EventRegistrationToken clickToken; - RETURN_IF_FAILED( - hyperlink->add_Click(Callback>( - [selectAction, actionInvoker](IInspectable*, IHyperlinkClickEventArgs*) -> HRESULT { - return actionInvoker->SendActionEvent(selectAction.Get()); - }) - .Get(), - &clickToken)); - - // Add the run text to the hyperlink's inlines - ComPtr hyperlinkAsSpan; - RETURN_IF_FAILED(hyperlink.As(&hyperlinkAsSpan)); - - ComPtr> hyperlinkInlines; - RETURN_IF_FAILED(hyperlinkAsSpan->get_Inlines(hyperlinkInlines.GetAddressOf())); - RETURN_IF_FAILED(AddSingleTextInline(adaptiveTextElement.Get(), - renderContext, - renderArgs, - text.Get(), - TextRunStyleParameters(isStrikethrough, isItalic, isUnderline, true), - hyperlinkInlines.Get(), - &inlineLength)); - - ComPtr hyperlinkAsInline; - RETURN_IF_FAILED(hyperlink.As(&hyperlinkAsInline)); - - // Add the hyperlink to the paragraph's inlines - RETURN_IF_FAILED(xamlInlines->Append(hyperlinkAsInline.Get())); - } - else - { - // Add the text to the paragraph's inlines - RETURN_IF_FAILED(AddSingleTextInline(adaptiveTextElement.Get(), - renderContext, - renderArgs, - text.Get(), - TextRunStyleParameters(isStrikethrough, isItalic, isUnderline, false), - xamlInlines.Get(), - &inlineLength)); - } - - boolean highlight; - RETURN_IF_FAILED(adaptiveTextRun->get_Highlight(&highlight)); - - if (highlight) - { - ComPtr textHighlighter; - RETURN_IF_FAILED(GetHighlighter(adaptiveTextElement.Get(), renderContext, renderArgs, &textHighlighter)); - - ComPtr> ranges; - RETURN_IF_FAILED(textHighlighter->get_Ranges(&ranges)); - - TextRange textRange = {(INT32)currentOffset, (INT32)inlineLength}; - RETURN_IF_FAILED(ranges->Append(textRange)); - - RETURN_IF_FAILED(textHighlighters->Append(textHighlighter.Get())); - } - - currentOffset += inlineLength; - return S_OK; - }); - - return xamlRichTextBlock.CopyTo(textBlockControl); - } - - HRESULT XamlBuilder::BuildTextBlock(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** textBlockControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveTextBlock; - RETURN_IF_FAILED(cardElement.As(&adaptiveTextBlock)); - - ComPtr xamlTextBlock = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); - - ComPtr adaptiveTextElement; - RETURN_IF_FAILED(adaptiveTextBlock.As(&adaptiveTextElement)); - - RETURN_IF_FAILED(StyleXamlTextBlockProperties(adaptiveTextBlock.Get(), renderContext, renderArgs, xamlTextBlock.Get())); - - ComPtr> inlines; - RETURN_IF_FAILED(xamlTextBlock->get_Inlines(&inlines)); - - RETURN_IF_FAILED(SetXamlInlines(adaptiveTextElement.Get(), renderContext, renderArgs, false, inlines.Get())); - - // Ensure left edge of text is consistent regardless of font size, so both small and large fonts - // are flush on the left edge of the card by enabling TrimSideBearings - ComPtr xamlTextBlock2; - RETURN_IF_FAILED(xamlTextBlock.As(&xamlTextBlock2)); - RETURN_IF_FAILED(xamlTextBlock2->put_OpticalMarginAlignment(OpticalMarginAlignment_TrimSideBearings)); - - ComPtr frameworkElement; - RETURN_IF_FAILED(xamlTextBlock.As(&frameworkElement)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.TextBlock", frameworkElement.Get())); - - return xamlTextBlock.CopyTo(textBlockControl); - } - - HRESULT XamlBuilder::SetAutoImageSize(_In_ IFrameworkElement* imageControl, - _In_ IInspectable* parentElement, - _In_ IBitmapSource* imageSource, - bool setVisible) - { - INT32 pixelHeight; - RETURN_IF_FAILED(imageSource->get_PixelHeight(&pixelHeight)); - INT32 pixelWidth; - RETURN_IF_FAILED(imageSource->get_PixelWidth(&pixelWidth)); - DOUBLE maxHeight; - DOUBLE maxWidth; - ComPtr localParentElement(parentElement); - ComPtr localElement(imageControl); - ComPtr parentAsColumnDefinition; - - RETURN_IF_FAILED(localElement->get_MaxHeight(&maxHeight)); - RETURN_IF_FAILED(localElement->get_MaxWidth(&maxWidth)); - - if (SUCCEEDED(localParentElement.As(&parentAsColumnDefinition))) - { - DOUBLE parentWidth; - RETURN_IF_FAILED(parentAsColumnDefinition->get_ActualWidth(&parentWidth)); - if (parentWidth >= pixelWidth) - { - // Make sure to keep the aspect ratio of the image - maxWidth = min(maxWidth, parentWidth); - double aspectRatio = (double)pixelHeight / pixelWidth; - maxHeight = maxWidth * aspectRatio; - } - } - - // Prevent an image from being stretched out if it is smaller than the - // space allocated for it (when in auto mode). - ComPtr localElementAsEllipse; - if (SUCCEEDED(localElement.As(&localElementAsEllipse))) - { - // don't need to set both width and height when image size is auto since - // we want a circle as shape. - // max value for width should be set since adaptive cards is constrained horizontally - RETURN_IF_FAILED(localElement->put_MaxWidth(min(maxWidth, pixelWidth))); - } - else - { - RETURN_IF_FAILED(localElement->put_MaxHeight(min(maxHeight, pixelHeight))); - RETURN_IF_FAILED(localElement->put_MaxWidth(min(maxWidth, pixelWidth))); - } - - if (setVisible) - { - ComPtr frameworkElementAsUIElement; - RETURN_IF_FAILED(localElement.As(&frameworkElementAsUIElement)); - RETURN_IF_FAILED(frameworkElementAsUIElement->put_Visibility(Visibility::Visibility_Visible)); - } - - return S_OK; - } - - HRESULT XamlBuilder::SetMatchingHeight(_In_ IFrameworkElement* elementToChange, _In_ IFrameworkElement* elementToMatch) - { - DOUBLE actualHeight; - RETURN_IF_FAILED(elementToMatch->get_ActualHeight(&actualHeight)); - - ComPtr localElement(elementToChange); - RETURN_IF_FAILED(localElement->put_Height(actualHeight)); - - ComPtr frameworkElementAsUIElement; - RETURN_IF_FAILED(localElement.As(&frameworkElementAsUIElement)); - RETURN_IF_FAILED(frameworkElementAsUIElement->put_Visibility(Visibility::Visibility_Visible)); - return S_OK; - } - - template<> - void XamlBuilder::SetAutoSize(IEllipse* destination, IInspectable* parentElement, IInspectable* imageContainer, bool isVisible, bool imageFiresOpenEvent) - { - // Check if the image source fits in the parent container, if so, set the framework element's size to match the original image. - if (parentElement != nullptr && m_enableXamlImageHandling) - { - ComPtr ellipseShape(imageContainer); - ComPtr ellipseAsShape; - THROW_IF_FAILED(ellipseShape.As(&ellipseAsShape)); - - ComPtr ellipseBrush; - THROW_IF_FAILED(ellipseAsShape->get_Fill(&ellipseBrush)); - ComPtr brushAsImageBrush; - THROW_IF_FAILED(ellipseBrush.As(&brushAsImageBrush)); - - ComPtr ellipse(destination); - - ComPtr ellipseAsUIElement; - THROW_IF_FAILED(ellipse.As(&ellipseAsUIElement)); - - ComPtr ellipsAsFrameworkElement; - THROW_IF_FAILED(ellipse.As(&ellipsAsFrameworkElement)); - - ComPtr imageSource; - THROW_IF_FAILED(brushAsImageBrush->get_ImageSource(&imageSource)); - ComPtr imageSourceAsBitmap; - THROW_IF_FAILED(imageSource.As(&imageSourceAsBitmap)); - - // If the image hasn't loaded yet - if (imageFiresOpenEvent) - { - // Collapse the Ellipse while the image loads, so that resizing is not noticeable - THROW_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); - // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent - EventRegistrationToken eventToken; - ComPtr strongParentElement(parentElement); - THROW_IF_FAILED(brushAsImageBrush->add_ImageOpened( - Callback([ellipseAsUIElement, ellipsAsFrameworkElement, imageSourceAsBitmap, strongParentElement, isVisible]( - IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - if (isVisible) - { - RETURN_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Visible)); - RETURN_IF_FAILED(SetAutoImageSize(ellipsAsFrameworkElement.Get(), - strongParentElement.Get(), - imageSourceAsBitmap.Get(), - isVisible)); - } - return S_OK; - }) - .Get(), - &eventToken)); - } - else - { - SetAutoImageSize(ellipsAsFrameworkElement.Get(), parentElement, imageSourceAsBitmap.Get(), isVisible); - } - } - } - - template - void XamlBuilder::SetAutoSize(T* destination, IInspectable* parentElement, IInspectable* /* imageContainer */, bool isVisible, bool imageFiresOpenEvent) - { - if (parentElement != nullptr && m_enableXamlImageHandling) - { - ComPtr xamlImage(destination); - ComPtr imageAsFrameworkElement; - THROW_IF_FAILED(xamlImage.As(&imageAsFrameworkElement)); - ComPtr imageSource; - THROW_IF_FAILED(xamlImage->get_Source(&imageSource)); - ComPtr imageSourceAsBitmap; - THROW_IF_FAILED(imageSource.As(&imageSourceAsBitmap)); - - ComPtr imageAsUIElement; - THROW_IF_FAILED(xamlImage.As(&imageAsUIElement)); - - // If the image hasn't loaded yet - if (imageFiresOpenEvent) - { - // Collapse the Image control while the image loads, so that resizing is not noticeable - THROW_IF_FAILED(imageAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); - - // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent - ComPtr strongParentElement(parentElement); - EventRegistrationToken eventToken; - THROW_IF_FAILED(xamlImage->add_ImageOpened( - Callback( - [imageAsFrameworkElement, strongParentElement, imageSourceAsBitmap, isVisible](IInspectable* /*sender*/, IRoutedEventArgs * - /*args*/) -> HRESULT { - return SetAutoImageSize(imageAsFrameworkElement.Get(), - strongParentElement.Get(), - imageSourceAsBitmap.Get(), - isVisible); - }) - .Get(), - &eventToken)); - } - else - { - SetAutoImageSize(imageAsFrameworkElement.Get(), parentElement, imageSourceAsBitmap.Get(), isVisible); - } - } - } - - HRESULT XamlBuilder::BuildImage(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** imageControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveImage; - RETURN_IF_FAILED(cardElement.As(&adaptiveImage)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - HSTRING url; - RETURN_IF_FAILED(adaptiveImage->get_Url(&url)); - - ComPtr imageUrl; - GetUrlFromString(hostConfig.Get(), url, imageUrl.GetAddressOf()); - - if (imageUrl == nullptr) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::AssetLoadFailed, - HStringReference(L"Image not found").Get()); - *imageControl = nullptr; - return S_OK; - } - - UINT32 pixelWidth = 0, pixelHeight = 0; - RETURN_IF_FAILED(adaptiveImage->get_PixelWidth(&pixelWidth)); - RETURN_IF_FAILED(adaptiveImage->get_PixelHeight(&pixelHeight)); - bool hasExplicitMeasurements = (pixelWidth || pixelHeight); - bool isAspectRatioNeeded = (pixelWidth && pixelHeight); - - // Get the image's size and style - ABI::AdaptiveNamespace::ImageSize size = ABI::AdaptiveNamespace::ImageSize::None; - if (!hasExplicitMeasurements) - { - RETURN_IF_FAILED(adaptiveImage->get_Size(&size)); - } - - if (size == ABI::AdaptiveNamespace::ImageSize::None && !hasExplicitMeasurements) - { - ComPtr imageConfig; - RETURN_IF_FAILED(hostConfig->get_Image(&imageConfig)); - RETURN_IF_FAILED(imageConfig->get_ImageSize(&size)); - } - - ABI::AdaptiveNamespace::ImageStyle imageStyle; - RETURN_IF_FAILED(adaptiveImage->get_Style(&imageStyle)); - ComPtr resourceResolvers; - RETURN_IF_FAILED(renderContext->get_ResourceResolvers(&resourceResolvers)); - - HSTRING backgroundColor; - RETURN_IF_FAILED(adaptiveImage->get_BackgroundColor(&backgroundColor)); - - boolean isVisible; - RETURN_IF_FAILED(adaptiveCardElement->get_IsVisible(&isVisible)); - - ComPtr frameworkElement; - if (imageStyle == ImageStyle_Person) - { - ComPtr ellipse = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Ellipse)); - ComPtr backgroundEllipse = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Ellipse)); - - Stretch imageStretch = (isAspectRatioNeeded) ? Stretch::Stretch_Fill : Stretch::Stretch_UniformToFill; - bool mustHideElement{true}; - - ComPtr parentElement; - RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); - - ComPtr ellipseAsShape; - RETURN_IF_FAILED(ellipse.As(&ellipseAsShape)); - - SetImageOnUIElement(imageUrl.Get(), - ellipse.Get(), - resourceResolvers.Get(), - (size == ABI::AdaptiveNamespace::ImageSize_Auto), - parentElement.Get(), - ellipseAsShape.Get(), - isVisible, - &mustHideElement, - imageStretch); - - ComPtr backgroundEllipseAsShape; - RETURN_IF_FAILED(backgroundEllipse.As(&backgroundEllipseAsShape)); - - if (size == ABI::AdaptiveNamespace::ImageSize::None || size == ABI::AdaptiveNamespace::ImageSize::Stretch || - size == ABI::AdaptiveNamespace::ImageSize::Auto || hasExplicitMeasurements) - { - RETURN_IF_FAILED(ellipseAsShape->put_Stretch(imageStretch)); - RETURN_IF_FAILED(backgroundEllipseAsShape->put_Stretch(imageStretch)); - } - else - { - // Set the stretch for the ellipse - this is different to the stretch used for the image brush - // above. This will force the ellipse to conform to fit within the confines of its parent. - Stretch ellipseStretch = Stretch::Stretch_UniformToFill; - RETURN_IF_FAILED(ellipseAsShape->put_Stretch(ellipseStretch)); - RETURN_IF_FAILED(backgroundEllipseAsShape->put_Stretch(ellipseStretch)); - } - - if (backgroundColor != nullptr) - { - // Fill the background ellipse with solid color brush - ABI::Windows::UI::Color color; - RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); - ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); - RETURN_IF_FAILED(backgroundEllipseAsShape->put_Fill(backgroundColorBrush.Get())); - - // Create a grid to contain the background color ellipse and the image ellipse - ComPtr imageGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - - ComPtr panel; - RETURN_IF_FAILED(imageGrid.As(&panel)); - - XamlHelpers::AppendXamlElementToPanel(backgroundEllipse.Get(), panel.Get()); - XamlHelpers::AppendXamlElementToPanel(ellipse.Get(), panel.Get()); - - RETURN_IF_FAILED(imageGrid.As(&frameworkElement)); - } - else - { - RETURN_IF_FAILED(ellipse.As(&frameworkElement)); - } - } - else - { - ComPtr xamlImage = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Image)); - - if (backgroundColor != nullptr) - { - // Create a surrounding border with solid color background to contain the image - ComPtr border = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); - - ABI::Windows::UI::Color color; - RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); - ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); - RETURN_IF_FAILED(border->put_Background(backgroundColorBrush.Get())); - - ComPtr imageAsUiElement; - RETURN_IF_FAILED(xamlImage.CopyTo(imageAsUiElement.GetAddressOf())); - RETURN_IF_FAILED(border->put_Child(imageAsUiElement.Get())); - - RETURN_IF_FAILED(border.As(&frameworkElement)); - } - else - { - RETURN_IF_FAILED(xamlImage.As(&frameworkElement)); - } - - if (isAspectRatioNeeded) - { - xamlImage->put_Stretch(Stretch::Stretch_Fill); - } - - ComPtr parentElement; - RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); - - bool mustHideElement{true}; - SetImageOnUIElement(imageUrl.Get(), - xamlImage.Get(), - resourceResolvers.Get(), - (size == ABI::AdaptiveNamespace::ImageSize_Auto), - parentElement.Get(), - frameworkElement.Get(), - isVisible, - &mustHideElement); - } - - ComPtr sizeOptions; - RETURN_IF_FAILED(hostConfig->get_ImageSizes(sizeOptions.GetAddressOf())); - - if (hasExplicitMeasurements) - { - if (pixelWidth) - { - if (imageStyle == ImageStyle_Person) - { - RETURN_IF_FAILED(frameworkElement->put_Width(pixelWidth)); - } - else - { - RETURN_IF_FAILED(frameworkElement->put_MaxWidth(pixelWidth)); - } - } - - if (pixelHeight) - { - if (imageStyle == ImageStyle_Person) - { - RETURN_IF_FAILED(frameworkElement->put_Height(pixelHeight)); - } - else - { - RETURN_IF_FAILED(frameworkElement->put_MaxHeight(pixelHeight)); - } - } - } - else - { - if (size == ABI::AdaptiveNamespace::ImageSize::Small || size == ABI::AdaptiveNamespace::ImageSize::Medium || - size == ABI::AdaptiveNamespace::ImageSize::Large) - { - UINT32 imageSize; - switch (size) - { - case ABI::AdaptiveNamespace::ImageSize::Small: - { - RETURN_IF_FAILED(sizeOptions->get_Small(&imageSize)); - break; - } - - case ABI::AdaptiveNamespace::ImageSize::Medium: - { - RETURN_IF_FAILED(sizeOptions->get_Medium(&imageSize)); - break; - } - - case ABI::AdaptiveNamespace::ImageSize::Large: - { - RETURN_IF_FAILED(sizeOptions->get_Large(&imageSize)); - - break; - } - default: - { - return E_UNEXPECTED; - } - } - - RETURN_IF_FAILED(frameworkElement->put_MaxWidth(imageSize)); - - // We don't want to set a max height on the person ellipse as ellipses do not understand preserving - // aspect ratio when constrained on both axes. - if (imageStyle != ImageStyle_Person) - { - RETURN_IF_FAILED(frameworkElement->put_MaxHeight(imageSize)); - } - } - } - - ABI::AdaptiveNamespace::HAlignment adaptiveHorizontalAlignment; - RETURN_IF_FAILED(adaptiveImage->get_HorizontalAlignment(&adaptiveHorizontalAlignment)); - - switch (adaptiveHorizontalAlignment) - { - case ABI::AdaptiveNamespace::HAlignment::Left: - RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); - break; - case ABI::AdaptiveNamespace::HAlignment::Right: - RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); - break; - case ABI::AdaptiveNamespace::HAlignment::Center: - RETURN_IF_FAILED(frameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); - break; - } - - RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Image", frameworkElement.Get())); - - ComPtr selectAction; - RETURN_IF_FAILED(adaptiveImage->get_SelectAction(&selectAction)); - - ComPtr imageAsUIElement; - RETURN_IF_FAILED(frameworkElement.As(&imageAsUIElement)); - - HString altText; - RETURN_IF_FAILED(adaptiveImage->get_AltText(altText.GetAddressOf())); - - ComPtr imageAsDependencyObject; - RETURN_IF_FAILED(imageAsUIElement.As(&imageAsDependencyObject)); - - ComPtr automationPropertiesStatics; - RETURN_IF_FAILED( - GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), - &automationPropertiesStatics)); - - RETURN_IF_FAILED(automationPropertiesStatics->SetName(imageAsDependencyObject.Get(), altText.Get())); - - HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - imageAsUIElement.Get(), - SupportsInteractivity(hostConfig.Get()), - true, - imageControl); - - return S_OK; - } - - HRESULT HandleStylingAndPadding(_In_ IAdaptiveContainerBase* adaptiveContainer, - _In_ IBorder* containerBorder, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _Out_ ABI::AdaptiveNamespace::ContainerStyle* containerStyle) - { - ABI::AdaptiveNamespace::ContainerStyle localContainerStyle; - RETURN_IF_FAILED(adaptiveContainer->get_Style(&localContainerStyle)); - - ABI::AdaptiveNamespace::ContainerStyle parentContainerStyle; - RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&parentContainerStyle)); - - bool hasExplicitContainerStyle{true}; - if (localContainerStyle == ABI::AdaptiveNamespace::ContainerStyle::None) - { - hasExplicitContainerStyle = false; - localContainerStyle = parentContainerStyle; - } - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - ComPtr spacingConfig; - RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 padding; - RETURN_IF_FAILED(spacingConfig->get_Padding(&padding)); - DOUBLE paddingAsDouble = static_cast(padding); - - // If container style was explicitly assigned, apply background color and padding - if (hasExplicitContainerStyle) - { - ABI::Windows::UI::Color backgroundColor; - RETURN_IF_FAILED(GetBackgroundColorFromStyle(localContainerStyle, hostConfig.Get(), &backgroundColor)); - ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(backgroundColor); - RETURN_IF_FAILED(containerBorder->put_Background(backgroundColorBrush.Get())); - - // If the container style doesn't match its parent apply padding. - if (localContainerStyle != parentContainerStyle) - { - Thickness paddingThickness = {paddingAsDouble, paddingAsDouble, paddingAsDouble, paddingAsDouble}; - RETURN_IF_FAILED(containerBorder->put_Padding(paddingThickness)); - } - } - - // Find out which direction(s) we bleed in, and apply a negative margin to cause the - // container to bleed - ABI::AdaptiveNamespace::BleedDirection bleedDirection; - RETURN_IF_FAILED(adaptiveContainer->get_BleedDirection(&bleedDirection)); - - Thickness marginThickness = {0}; - if (bleedDirection != ABI::AdaptiveNamespace::BleedDirection::None) - { - if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Left) != ABI::AdaptiveNamespace::BleedDirection::None) - { - marginThickness.Left = -paddingAsDouble; - } - - if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Right) != ABI::AdaptiveNamespace::BleedDirection::None) - { - marginThickness.Right = -paddingAsDouble; - } - - if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Up) != ABI::AdaptiveNamespace::BleedDirection::None) - { - marginThickness.Top = -paddingAsDouble; - } - - if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Down) != ABI::AdaptiveNamespace::BleedDirection::None) - { - marginThickness.Bottom = -paddingAsDouble; - } - - ComPtr localContainerBorder(containerBorder); - ComPtr containerBorderAsFrameworkElement; - RETURN_IF_FAILED(localContainerBorder.As(&containerBorderAsFrameworkElement)); - RETURN_IF_FAILED(containerBorderAsFrameworkElement->put_Margin(marginThickness)); - } - - *containerStyle = localContainerStyle; - - return S_OK; - } - - HRESULT XamlBuilder::BuildContainer(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** containerControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveContainer; - RETURN_IF_FAILED(cardElement.As(&adaptiveContainer)); - - ComPtr containerPanel; - RETURN_IF_FAILED(MakeAndInitialize(&containerPanel)); - - ComPtr containerPanelAsFrameWorkElement; - RETURN_IF_FAILED(containerPanel.As(&containerPanelAsFrameWorkElement)); - - // Assign vertical alignment to the top so that on fixed height cards, the content - // still renders at the top even if the content is shorter than the full card - ABI::AdaptiveNamespace::HeightType containerHeightType{}; - RETURN_IF_FAILED(cardElement->get_Height(&containerHeightType)); - if (containerHeightType == ABI::AdaptiveNamespace::HeightType::Auto) - { - RETURN_IF_FAILED(containerPanelAsFrameWorkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - } - - ComPtr containerAsContainerBase; - RETURN_IF_FAILED(adaptiveContainer.As(&containerAsContainerBase)); - - UINT32 containerMinHeight{}; - RETURN_IF_FAILED(containerAsContainerBase->get_MinHeight(&containerMinHeight)); - if (containerMinHeight > 0) - { - RETURN_IF_FAILED(containerPanelAsFrameWorkElement->put_MinHeight(containerMinHeight)); - } - - ComPtr containerBorder = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); - - ABI::AdaptiveNamespace::ContainerStyle containerStyle; - RETURN_IF_FAILED( - HandleStylingAndPadding(containerAsContainerBase.Get(), containerBorder.Get(), renderContext, renderArgs, &containerStyle)); - - ComPtr parentElement; - RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); - ComPtr newRenderArgs; - RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); - - ComPtr containerPanelAsPanel; - RETURN_IF_FAILED(containerPanel.As(&containerPanelAsPanel)); - ComPtr> childItems; - RETURN_IF_FAILED(adaptiveContainer->get_Items(&childItems)); - RETURN_IF_FAILED( - BuildPanelChildren(childItems.Get(), containerPanelAsPanel.Get(), renderContext, newRenderArgs.Get(), [](IUIElement*) {})); - - ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment; - RETURN_IF_FAILED(adaptiveContainer->get_VerticalContentAlignment(&verticalContentAlignment)); - - XamlBuilder::SetVerticalContentAlignmentToChildren(containerPanel.Get(), verticalContentAlignment); - - // Check if backgroundImage defined - ComPtr backgroundImage; - BOOL backgroundImageIsValid; - RETURN_IF_FAILED(adaptiveContainer->get_BackgroundImage(&backgroundImage)); - RETURN_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); - if (backgroundImageIsValid) - { - ComPtr rootElement = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr rootAsPanel; - RETURN_IF_FAILED(rootElement.As(&rootAsPanel)); - - ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, newRenderArgs.Get()); - - // Add rootElement to containerBorder - ComPtr rootAsUIElement; - RETURN_IF_FAILED(rootElement.As(&rootAsUIElement)); - RETURN_IF_FAILED(containerBorder->put_Child(rootAsUIElement.Get())); - - // Add containerPanel to rootElement - ComPtr containerPanelAsFElement; - RETURN_IF_FAILED(containerPanel.As(&containerPanelAsFElement)); - XamlHelpers::AppendXamlElementToPanel(containerPanelAsFElement.Get(), rootAsPanel.Get(), containerHeightType); - } - else - { - // instead, directly add containerPanel to containerBorder - ComPtr containerPanelAsUIElement; - RETURN_IF_FAILED(containerPanel.As(&containerPanelAsUIElement)); - RETURN_IF_FAILED(containerBorder->put_Child(containerPanelAsUIElement.Get())); - } - - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Container", containerPanelAsFrameWorkElement.Get())); - - ComPtr selectAction; - RETURN_IF_FAILED(containerAsContainerBase->get_SelectAction(&selectAction)); - - ComPtr containerBorderAsUIElement; - RETURN_IF_FAILED(containerBorder.As(&containerBorderAsUIElement)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - containerBorderAsUIElement.Get(), - SupportsInteractivity(hostConfig.Get()), - true, - containerControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildColumn(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** ColumnControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveColumn; - RETURN_IF_FAILED(cardElement.As(&adaptiveColumn)); - - ComPtr columnBorder = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); - - ComPtr columnPanel; - RETURN_IF_FAILED(MakeAndInitialize(&columnPanel)); - - ComPtr columnPanelAsUIElement; - RETURN_IF_FAILED(columnPanel.As(&columnPanelAsUIElement)); - - RETURN_IF_FAILED(columnBorder->put_Child(columnPanelAsUIElement.Get())); - - ComPtr columnAsContainerBase; - RETURN_IF_FAILED(adaptiveColumn.As(&columnAsContainerBase)); - - ABI::AdaptiveNamespace::ContainerStyle containerStyle; - RETURN_IF_FAILED(HandleStylingAndPadding(columnAsContainerBase.Get(), columnBorder.Get(), renderContext, renderArgs, &containerStyle)); - - ComPtr parentElement; - RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); - ComPtr newRenderArgs; - RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); - - ComPtr columnAsPanel; - THROW_IF_FAILED(columnPanel.As(&columnAsPanel)); - - ComPtr> childItems; - RETURN_IF_FAILED(adaptiveColumn->get_Items(&childItems)); - RETURN_IF_FAILED( - BuildPanelChildren(childItems.Get(), columnAsPanel.Get(), renderContext, newRenderArgs.Get(), [](IUIElement*) {})); - - ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment; - RETURN_IF_FAILED(adaptiveColumn->get_VerticalContentAlignment(&verticalContentAlignment)); - - XamlBuilder::SetVerticalContentAlignmentToChildren(columnPanel.Get(), verticalContentAlignment); - - // Assign vertical alignment to the top so that on fixed height cards, the content - // still renders at the top even if the content is shorter than the full card - ComPtr columnPanelAsFrameworkElement; - RETURN_IF_FAILED(columnPanel.As(&columnPanelAsFrameworkElement)); - RETURN_IF_FAILED(columnPanelAsFrameworkElement->put_VerticalAlignment(VerticalAlignment_Stretch)); - - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Column", columnPanelAsFrameworkElement.Get())); - - UINT32 columnMinHeight{}; - RETURN_IF_FAILED(columnAsContainerBase->get_MinHeight(&columnMinHeight)); - if (columnMinHeight > 0) - { - RETURN_IF_FAILED(columnPanelAsFrameworkElement->put_MinHeight(columnMinHeight)); - } - - ComPtr selectAction; - RETURN_IF_FAILED(columnAsContainerBase->get_SelectAction(&selectAction)); - - // Define columnAsUIElement based on the existence of a backgroundImage - ComPtr columnAsUIElement; - ComPtr backgroundImage; - BOOL backgroundImageIsValid; - RETURN_IF_FAILED(adaptiveColumn->get_BackgroundImage(&backgroundImage)); - RETURN_IF_FAILED(IsBackgroundImageValid(backgroundImage.Get(), &backgroundImageIsValid)); - if (backgroundImageIsValid) - { - ComPtr rootElement = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr rootAsPanel; - RETURN_IF_FAILED(rootElement.As(&rootAsPanel)); - - ApplyBackgroundToRoot(rootAsPanel.Get(), backgroundImage.Get(), renderContext, newRenderArgs.Get()); - - // get HeightType for column - ABI::AdaptiveNamespace::HeightType columnHeightType{}; - RETURN_IF_FAILED(cardElement->get_Height(&columnHeightType)); - - // Add columnBorder to rootElement - ComPtr columnBorderAsFElement; - RETURN_IF_FAILED(columnBorder.As(&columnBorderAsFElement)); - XamlHelpers::AppendXamlElementToPanel(columnBorderAsFElement.Get(), rootAsPanel.Get(), columnHeightType); - - RETURN_IF_FAILED(rootElement.As(&columnAsUIElement)); - } - else - { - RETURN_IF_FAILED(columnBorder.As(&columnAsUIElement)); - } - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - columnAsUIElement.Get(), - SupportsInteractivity(hostConfig.Get()), - false, - ColumnControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildColumnSet(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** columnSetControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveColumnSet; - RETURN_IF_FAILED(cardElement.As(&adaptiveColumnSet)); - - ComPtr columnSetBorder = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); - - ComPtr gridContainer; - RETURN_IF_FAILED(MakeAndInitialize(&gridContainer)); - - ComPtr gridContainerAsUIElement; - RETURN_IF_FAILED(gridContainer.As(&gridContainerAsUIElement)); - - RETURN_IF_FAILED(columnSetBorder->put_Child(gridContainerAsUIElement.Get())); - - ComPtr columnSetAsContainerBase; - RETURN_IF_FAILED(adaptiveColumnSet.As(&columnSetAsContainerBase)); - - ABI::AdaptiveNamespace::ContainerStyle containerStyle; - RETURN_IF_FAILED( - HandleStylingAndPadding(columnSetAsContainerBase.Get(), columnSetBorder.Get(), renderContext, renderArgs, &containerStyle)); - - ComPtr parentElement; - RETURN_IF_FAILED(renderArgs->get_ParentElement(&parentElement)); - ComPtr newRenderArgs; - RETURN_IF_FAILED(MakeAndInitialize(&newRenderArgs, containerStyle, parentElement.Get(), renderArgs)); - - ComPtr xamlGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr gridStatics; - RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); - - ComPtr> columns; - RETURN_IF_FAILED(adaptiveColumnSet->get_Columns(&columns)); - int currentColumn{}; - ComPtr elementRenderers; - RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - ComPtr columnRenderer; - RETURN_IF_FAILED(elementRenderers->Get(HStringReference(L"Column").Get(), &columnRenderer)); - - if (columnRenderer == nullptr) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, - HStringReference(L"No renderer found for type: Column").Get()); - *columnSetControl = nullptr; - return S_OK; - } - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - boolean ancestorHasFallback; - RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); - - ComPtr gridAsPanel; - RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); - - HRESULT hrColumns = XamlHelpers::IterateOverVectorWithFailure(columns.Get(), ancestorHasFallback, [&](IAdaptiveColumn* column) { - ComPtr columnAsCardElement; - ComPtr localColumn(column); - RETURN_IF_FAILED(localColumn.As(&columnAsCardElement)); - - ComPtr testColumn; - columnAsCardElement.As(&testColumn); - - ComPtr> columnDefinitions; - RETURN_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); - - ABI::AdaptiveNamespace::FallbackType fallbackType; - RETURN_IF_FAILED(columnAsCardElement->get_FallbackType(&fallbackType)); - - // Build the Column - RETURN_IF_FAILED(newRenderArgs->put_AncestorHasFallback( - ancestorHasFallback || fallbackType != ABI::AdaptiveNamespace::FallbackType::None)); - - ComPtr xamlColumn; - HRESULT hr = columnRenderer->Render(columnAsCardElement.Get(), renderContext, newRenderArgs.Get(), &xamlColumn); - if (hr == E_PERFORM_FALLBACK) - { - RETURN_IF_FAILED(RenderFallback(columnAsCardElement.Get(), renderContext, newRenderArgs.Get(), &xamlColumn)); - } - - RETURN_IF_FAILED(newRenderArgs->put_AncestorHasFallback(ancestorHasFallback)); - - // Check the column for nullptr as it may have been dropped due to fallback - if (xamlColumn != nullptr) - { - // If not the first column - ComPtr separator; - if (currentColumn > 0) - { - // Add Separator to the columnSet - bool needsSeparator; - UINT spacing; - UINT separatorThickness; - ABI::Windows::UI::Color separatorColor; - GetSeparationConfigForElement( - columnAsCardElement.Get(), hostConfig.Get(), &spacing, &separatorThickness, &separatorColor, &needsSeparator); - - if (needsSeparator) - { - // Create a new ColumnDefinition for the separator - ComPtr separatorColumnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - RETURN_IF_FAILED(separatorColumnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Auto})); - RETURN_IF_FAILED(columnDefinitions->Append(separatorColumnDefinition.Get())); - - separator = CreateSeparator(renderContext, spacing, separatorThickness, separatorColor, false); - ComPtr separatorAsFrameworkElement; - RETURN_IF_FAILED(separator.As(&separatorAsFrameworkElement)); - gridStatics->SetColumn(separatorAsFrameworkElement.Get(), currentColumn++); - XamlHelpers::AppendXamlElementToPanel(separator.Get(), gridAsPanel.Get()); - } - } - - // Determine if the column is auto, stretch, or percentage width, and set the column width appropriately - ComPtr columnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - - boolean isVisible; - RETURN_IF_FAILED(columnAsCardElement->get_IsVisible(&isVisible)); - - RETURN_IF_FAILED(HandleColumnWidth(column, isVisible, columnDefinition.Get())); - - RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); - - // Mark the column container with the current column - ComPtr columnAsFrameworkElement; - RETURN_IF_FAILED(xamlColumn.As(&columnAsFrameworkElement)); - gridStatics->SetColumn(columnAsFrameworkElement.Get(), currentColumn++); - - // Finally add the column container to the grid - RETURN_IF_FAILED(AddRenderedControl(xamlColumn.Get(), - columnAsCardElement.Get(), - gridAsPanel.Get(), - separator.Get(), - columnDefinition.Get(), - [](IUIElement*) {})); - } - return S_OK; - }); - RETURN_IF_FAILED(hrColumns); - - RETURN_IF_FAILED(SetSeparatorVisibility(gridAsPanel.Get())); - - ComPtr columnSetAsFrameworkElement; - RETURN_IF_FAILED(xamlGrid.As(&columnSetAsFrameworkElement)); - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.ColumnSet", columnSetAsFrameworkElement.Get())); - RETURN_IF_FAILED(columnSetAsFrameworkElement->put_VerticalAlignment(VerticalAlignment_Stretch)); - - ComPtr selectAction; - RETURN_IF_FAILED(columnSetAsContainerBase->get_SelectAction(&selectAction)); - - ComPtr gridContainerAsPanel; - RETURN_IF_FAILED(gridContainer.As(&gridContainerAsPanel)); - - ComPtr gridContainerAsFrameworkElement; - RETURN_IF_FAILED(gridContainer.As(&gridContainerAsFrameworkElement)); - - ComPtr gridAsUIElement; - RETURN_IF_FAILED(xamlGrid.As(&gridAsUIElement)); - - ComPtr columnSetAsCardElement; - RETURN_IF_FAILED(adaptiveColumnSet.As(&columnSetAsCardElement)); - - ABI::AdaptiveNamespace::HeightType columnSetHeightType; - RETURN_IF_FAILED(columnSetAsCardElement->get_Height(&columnSetHeightType)); - - ComPtr columnAsContainerBase; - RETURN_IF_FAILED(adaptiveColumnSet.As(&columnAsContainerBase)); - - UINT32 columnSetMinHeight{}; - RETURN_IF_FAILED(columnAsContainerBase->get_MinHeight(&columnSetMinHeight)); - if (columnSetMinHeight > 0) - { - RETURN_IF_FAILED(gridContainerAsFrameworkElement->put_MinHeight(columnSetMinHeight)); - } - - XamlHelpers::AppendXamlElementToPanel(xamlGrid.Get(), gridContainerAsPanel.Get(), columnSetHeightType); - - ComPtr columnSetBorderAsUIElement; - RETURN_IF_FAILED(columnSetBorder.As(&columnSetBorderAsUIElement)); - - HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - columnSetBorderAsUIElement.Get(), - SupportsInteractivity(hostConfig.Get()), - true, - columnSetControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildFactSet(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** factSetControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveFactSet; - - RETURN_IF_FAILED(cardElement.As(&adaptiveFactSet)); - - ComPtr xamlGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr gridStatics; - RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); - - ComPtr titleColumn = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - ComPtr valueColumn = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - GridLength factSetGridTitleLength = {0, GridUnitType::GridUnitType_Auto}; - GridLength factSetGridValueLength = {1, GridUnitType::GridUnitType_Star}; - - RETURN_IF_FAILED(titleColumn->put_Width(factSetGridTitleLength)); - RETURN_IF_FAILED(valueColumn->put_Width(factSetGridValueLength)); - ComPtr> columnDefinitions; - RETURN_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); - RETURN_IF_FAILED(columnDefinitions->Append(titleColumn.Get())); - RETURN_IF_FAILED(columnDefinitions->Append(valueColumn.Get())); - - GridLength factSetGridHeight = {0, GridUnitType::GridUnitType_Auto}; - ABI::AdaptiveNamespace::HeightType heightType; - RETURN_IF_FAILED(cardElement->get_Height(&heightType)); - if (heightType == ABI::AdaptiveNamespace::HeightType::Stretch) - { - factSetGridHeight = {1, GridUnitType::GridUnitType_Star}; - } - - ComPtr> facts; - RETURN_IF_FAILED(adaptiveFactSet->get_Facts(&facts)); - int currentFact = 0; - XamlHelpers::IterateOverVector( - facts.Get(), [xamlGrid, gridStatics, factSetGridHeight, ¤tFact, renderContext, renderArgs](IAdaptiveFact* fact) { - ComPtr factRow = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RowDefinition)); - RETURN_IF_FAILED(factRow->put_Height(factSetGridHeight)); - - ComPtr> rowDefinitions; - RETURN_IF_FAILED(xamlGrid->get_RowDefinitions(&rowDefinitions)); - RETURN_IF_FAILED(rowDefinitions->Append(factRow.Get())); - - ComPtr localFact(fact); - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr factSetConfig; - RETURN_IF_FAILED(hostConfig->get_FactSet(&factSetConfig)); - - // Get Language - HString language; - RETURN_IF_FAILED(localFact->get_Language(language.GetAddressOf())); - - // Create the title xaml textblock and style it from Host options - ComPtr titleTextConfig; - RETURN_IF_FAILED(factSetConfig->get_Title(&titleTextConfig)); - - ComPtr titleTextBlock = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); - - HString factTitle; - RETURN_IF_FAILED(localFact->get_Title(factTitle.GetAddressOf())); - - RETURN_IF_FAILED(SetXamlInlinesWithTextConfig( - renderContext, renderArgs, titleTextConfig.Get(), language.Get(), factTitle.Get(), titleTextBlock.Get())); - - // Create the value xaml textblock and style it from Host options - ComPtr valueTextConfig; - RETURN_IF_FAILED(factSetConfig->get_Value(&valueTextConfig)); - - ComPtr valueTextBlock = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); - - HString factValue; - RETURN_IF_FAILED(localFact->get_Value(factValue.GetAddressOf())); - - RETURN_IF_FAILED(SetXamlInlinesWithTextConfig( - renderContext, renderArgs, valueTextConfig.Get(), language.Get(), factValue.Get(), valueTextBlock.Get())); - - // Mark the column container with the current column - ComPtr titleTextBlockAsFrameWorkElement; - RETURN_IF_FAILED(titleTextBlock.As(&titleTextBlockAsFrameWorkElement)); - ComPtr valueTextBlockAsFrameWorkElement; - RETURN_IF_FAILED(valueTextBlock.As(&valueTextBlockAsFrameWorkElement)); - - UINT32 spacing; - RETURN_IF_FAILED(factSetConfig->get_Spacing(&spacing)); - // Add spacing from hostconfig to right margin of title. - titleTextBlockAsFrameWorkElement->put_Margin({0, 0, (double)spacing, 0}); - - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, - L"Adaptive.Fact.Title", - titleTextBlockAsFrameWorkElement.Get())); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, - L"Adaptive.Fact.Value", - valueTextBlockAsFrameWorkElement.Get())); - - RETURN_IF_FAILED(gridStatics->SetColumn(titleTextBlockAsFrameWorkElement.Get(), 0)); - RETURN_IF_FAILED(gridStatics->SetRow(titleTextBlockAsFrameWorkElement.Get(), currentFact)); - - RETURN_IF_FAILED(gridStatics->SetColumn(valueTextBlockAsFrameWorkElement.Get(), 1)); - RETURN_IF_FAILED(gridStatics->SetRow(valueTextBlockAsFrameWorkElement.Get(), currentFact)); - - // Finally add the column container to the grid, and increment the column count - ComPtr gridAsPanel; - RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); - ComPtr titleUIElement; - RETURN_IF_FAILED(titleTextBlockAsFrameWorkElement.As(&titleUIElement)); - ComPtr valueUIElement; - RETURN_IF_FAILED(valueTextBlockAsFrameWorkElement.As(&valueUIElement)); - - XamlHelpers::AppendXamlElementToPanel(titleUIElement.Get(), gridAsPanel.Get()); - XamlHelpers::AppendXamlElementToPanel(valueUIElement.Get(), gridAsPanel.Get()); - ++currentFact; - return S_OK; - }); - - ComPtr factSetAsFrameworkElement; - RETURN_IF_FAILED(xamlGrid.As(&factSetAsFrameworkElement)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.FactSet", factSetAsFrameworkElement.Get())); - - return xamlGrid.CopyTo(factSetControl); - } - - HRESULT XamlBuilder::BuildImageSet(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** imageSetControl) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveImageSet; - RETURN_IF_FAILED(cardElement.As(&adaptiveImageSet)); - - ComPtr xamlGrid = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_VariableSizedWrapGrid)); - - RETURN_IF_FAILED(xamlGrid->put_Orientation(Orientation_Horizontal)); - - ComPtr> images; - RETURN_IF_FAILED(adaptiveImageSet->get_Images(&images)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr imageSetConfig; - RETURN_IF_FAILED(hostConfig->get_ImageSet(&imageSetConfig)); - - ABI::AdaptiveNamespace::ImageSize imageSize; - RETURN_IF_FAILED(adaptiveImageSet->get_ImageSize(&imageSize)); - - if (imageSize == ABI::AdaptiveNamespace::ImageSize::None) - { - RETURN_IF_FAILED(imageSetConfig->get_ImageSize(&imageSize)); - } - - ComPtr elementRenderers; - RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - ComPtr imageRenderer; - RETURN_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &imageRenderer)); - if (imageRenderer != nullptr) - { - ABI::AdaptiveNamespace::ContainerStyle containerStyle; - RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&containerStyle)); - - ComPtr childRenderArgs; - RETURN_IF_FAILED(MakeAndInitialize(&childRenderArgs, containerStyle, xamlGrid.Get(), renderArgs)); - - XamlHelpers::IterateOverVector( - images.Get(), - [imageSize, xamlGrid, renderContext, childRenderArgs, imageRenderer, imageSetConfig](IAdaptiveImage* adaptiveImage) { - ComPtr uiImage; - ComPtr localAdaptiveImage(adaptiveImage); - RETURN_IF_FAILED(localAdaptiveImage->put_Size(imageSize)); - - ComPtr adaptiveElementImage; - localAdaptiveImage.As(&adaptiveElementImage); - RETURN_IF_FAILED(imageRenderer->Render(adaptiveElementImage.Get(), renderContext, childRenderArgs.Get(), &uiImage)); - - ComPtr imageAsFrameworkElement; - RETURN_IF_FAILED(uiImage.As(&imageAsFrameworkElement)); - - UINT32 maxImageHeight; - RETURN_IF_FAILED(imageSetConfig->get_MaxImageHeight(&maxImageHeight)); - RETURN_IF_FAILED(imageAsFrameworkElement->put_MaxHeight(maxImageHeight)); - - ComPtr gridAsPanel; - RETURN_IF_FAILED(xamlGrid.As(&gridAsPanel)); - - XamlHelpers::AppendXamlElementToPanel(uiImage.Get(), gridAsPanel.Get()); - return S_OK; - }); - } - else - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, - HStringReference(L"No renderer found for type: Image").Get()); - *imageSetControl = nullptr; - return S_OK; - } - - ComPtr imageSetAsFrameworkElement; - RETURN_IF_FAILED(xamlGrid.As(&imageSetAsFrameworkElement)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.ImageSet", imageSetAsFrameworkElement.Get())); - - return xamlGrid.CopyTo(imageSetControl); - } - - static std::vector GetChoiceSetValueVector(_In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput) - { - HString value; - THROW_IF_FAILED(adaptiveChoiceSetInput->get_Value(value.GetAddressOf())); - - std::vector values; - std::string stdValue = HStringToUTF8(value.Get()); - std::stringstream streamValue(stdValue); - - while (streamValue.good()) - { - std::string subString; - std::getline(streamValue, subString, ','); - values.push_back(subString); - } - - return values; - } - - static bool IsChoiceSelected(std::vector selectedValues, _In_ IAdaptiveChoiceInput* choice) - { - HString value; - THROW_IF_FAILED(choice->get_Value(value.GetAddressOf())); - std::string stdValue = HStringToUTF8(value.Get()); - return std::find(selectedValues.begin(), selectedValues.end(), stdValue) != selectedValues.end(); - } - - HRESULT XamlBuilder::BuildCompactChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - _COM_Outptr_ IUIElement** choiceInputSet) - { - ComPtr comboBox = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ComboBox)); - - // Set HorizontalAlignment to Stretch (defaults to Left for combo boxes) - ComPtr comboBoxAsFrameworkElement; - RETURN_IF_FAILED(comboBox.As(&comboBoxAsFrameworkElement)); - RETURN_IF_FAILED(comboBoxAsFrameworkElement->put_HorizontalAlignment(HorizontalAlignment_Stretch)); - - ComPtr itemsControl; - RETURN_IF_FAILED(comboBox.As(&itemsControl)); - - ComPtr> items; - RETURN_IF_FAILED(itemsControl->get_Items(items.GetAddressOf())); - - ComPtr> itemsVector; - RETURN_IF_FAILED(items.As(&itemsVector)); - - ComPtr> choices; - RETURN_IF_FAILED(adaptiveChoiceSetInput->get_Choices(&choices)); - - std::vector values = GetChoiceSetValueVector(adaptiveChoiceSetInput); - boolean wrap; - adaptiveChoiceSetInput->get_Wrap(&wrap); - - int currentIndex = 0; - int selectedIndex = -1; - XamlHelpers::IterateOverVector( - choices.Get(), [¤tIndex, &selectedIndex, itemsVector, values, wrap](IAdaptiveChoiceInput* adaptiveChoiceInput) { - HString title; - RETURN_IF_FAILED(adaptiveChoiceInput->get_Title(title.GetAddressOf())); - - ComPtr comboBoxItem = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ComboBoxItem)); - - XamlHelpers::SetContent(comboBoxItem.Get(), title.Get(), wrap); - - // If multiple values are specified, no option is selected - if (values.size() == 1 && IsChoiceSelected(values, adaptiveChoiceInput)) - { - selectedIndex = currentIndex; - } - - ComPtr inspectable; - RETURN_IF_FAILED(comboBoxItem.As(&inspectable)); - - RETURN_IF_FAILED(itemsVector->Append(inspectable.Get())); - currentIndex++; - return S_OK; - }); - - ComPtr selector; - RETURN_IF_FAILED(comboBox.As(&selector)); - RETURN_IF_FAILED(selector->put_SelectedIndex(selectedIndex)); - - ComPtr comboBoxAsUIElement; - RETURN_IF_FAILED(comboBox.As(&comboBoxAsUIElement)); - RETURN_IF_FAILED(AddHandledTappedEvent(comboBoxAsUIElement.Get())); - - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.ChoiceSet.Compact", comboBoxAsFrameworkElement.Get()); - - return comboBoxAsUIElement.CopyTo(choiceInputSet); - } - - HRESULT XamlBuilder::BuildExpandedChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - boolean isMultiSelect, - _COM_Outptr_ IUIElement** choiceInputSet) - { - ComPtr> choices; - RETURN_IF_FAILED(adaptiveChoiceSetInput->get_Choices(&choices)); - - ComPtr stackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - stackPanel->put_Orientation(Orientation::Orientation_Vertical); - - ComPtr panel; - RETURN_IF_FAILED(stackPanel.As(&panel)); - - std::vector values = GetChoiceSetValueVector(adaptiveChoiceSetInput); - - boolean wrap; - adaptiveChoiceSetInput->get_Wrap(&wrap); - - XamlHelpers::IterateOverVector( - choices.Get(), [panel, isMultiSelect, renderContext, values, wrap](IAdaptiveChoiceInput* adaptiveChoiceInput) { - ComPtr choiceItem; - if (isMultiSelect) - { - ComPtr checkBox = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CheckBox)); - RETURN_IF_FAILED(checkBox.As(&choiceItem)); - - ComPtr frameworkElement; - RETURN_IF_FAILED(checkBox.As(&frameworkElement)); - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Choice.Multiselect", frameworkElement.Get()); - - XamlHelpers::SetToggleValue(choiceItem.Get(), IsChoiceSelected(values, adaptiveChoiceInput)); - } - else - { - ComPtr radioButton = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_RadioButton)); - RETURN_IF_FAILED(radioButton.As(&choiceItem)); - - ComPtr frameworkElement; - RETURN_IF_FAILED(radioButton.As(&frameworkElement)); - SetStyleFromResourceDictionary(renderContext, - L"Adaptive.Input.Choice.SingleSelect", - frameworkElement.Get()); - - if (values.size() == 1) - { - // When isMultiSelect is false, only 1 specified value is accepted. - // Otherwise, leave all options unset - XamlHelpers::SetToggleValue(choiceItem.Get(), IsChoiceSelected(values, adaptiveChoiceInput)); - } - } - - HString title; - RETURN_IF_FAILED(adaptiveChoiceInput->get_Title(title.GetAddressOf())); - XamlHelpers::SetContent(choiceItem.Get(), title.Get(), wrap); - - RETURN_IF_FAILED(AddHandledTappedEvent(choiceItem.Get())); - - XamlHelpers::AppendXamlElementToPanel(choiceItem.Get(), panel.Get()); - return S_OK; - }); - - ComPtr choiceSetAsFrameworkElement; - RETURN_IF_FAILED(stackPanel.As(&choiceSetAsFrameworkElement)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, - L"Adaptive.Input.ChoiceSet.Expanded", - choiceSetAsFrameworkElement.Get())); - - return stackPanel.CopyTo(choiceInputSet); - } - - static void AddInputValueToContext(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IUIElement* inputUiElement) - { - ComPtr cardElement(adaptiveCardElement); - ComPtr inputElement; - THROW_IF_FAILED(cardElement.As(&inputElement)); - - ComPtr input; - THROW_IF_FAILED(MakeAndInitialize(&input, inputElement.Get(), inputUiElement)); - THROW_IF_FAILED(renderContext->AddInputValue(input.Get())); - } - - HRESULT XamlBuilder::BuildChoiceSetInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** choiceInputSet) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"ChoiceSet was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveChoiceSetInput; - RETURN_IF_FAILED(cardElement.As(&adaptiveChoiceSetInput)); - - ABI::AdaptiveNamespace::ChoiceSetStyle choiceSetStyle; - RETURN_IF_FAILED(adaptiveChoiceSetInput->get_ChoiceSetStyle(&choiceSetStyle)); - - boolean isMultiSelect; - RETURN_IF_FAILED(adaptiveChoiceSetInput->get_IsMultiSelect(&isMultiSelect)); - - if (choiceSetStyle == ABI::AdaptiveNamespace::ChoiceSetStyle_Compact && !isMultiSelect) - { - BuildCompactChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), choiceInputSet); - } - else - { - BuildExpandedChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), isMultiSelect, choiceInputSet); - } - - AddInputValueToContext(renderContext, adaptiveCardElement, *choiceInputSet); - return S_OK; - } - - HRESULT XamlBuilder::BuildDateInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** dateInputControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Date input was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveDateInput; - RETURN_IF_FAILED(cardElement.As(&adaptiveDateInput)); - - ComPtr datePicker = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CalendarDatePicker)); - - HString placeHolderText; - RETURN_IF_FAILED(adaptiveDateInput->get_Placeholder(placeHolderText.GetAddressOf())); - RETURN_IF_FAILED(datePicker->put_PlaceholderText(placeHolderText.Get())); - - // Make the picker stretch full width - ComPtr datePickerAsFrameworkElement; - RETURN_IF_FAILED(datePicker.As(&datePickerAsFrameworkElement)); - RETURN_IF_FAILED(datePickerAsFrameworkElement->put_HorizontalAlignment(HorizontalAlignment_Stretch)); - RETURN_IF_FAILED(datePickerAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - - RETURN_IF_FAILED(datePicker.CopyTo(dateInputControl)); - - // Value - HString hstringValue; - RETURN_IF_FAILED(adaptiveDateInput->get_Value(hstringValue.GetAddressOf())); - std::string value = HStringToUTF8(hstringValue.Get()); - unsigned int year, month, day; - if (DateTimePreparser::TryParseSimpleDate(value, year, month, day)) - { - ComPtr> initialDateTimeReference; - RETURN_IF_FAILED(GetDateTimeReference(year, month, day, &initialDateTimeReference)); - RETURN_IF_FAILED(datePicker->put_Date(initialDateTimeReference.Get())); - } - - // Min date - HString hstringMin; - RETURN_IF_FAILED(adaptiveDateInput->get_Min(hstringMin.GetAddressOf())); - std::string min = HStringToUTF8(hstringMin.Get()); - DateTime minDate{}; - boolean isMinValid{DateTimePreparser::TryParseSimpleDate(min, year, month, day)}; - if (isMinValid) - { - minDate = GetDateTime(year, month, day); - RETURN_IF_FAILED(datePicker->put_MinDate(minDate)); - } - - // Max date - HString hstringMax; - RETURN_IF_FAILED(adaptiveDateInput->get_Max(hstringMax.GetAddressOf())); - std::string max = HStringToUTF8(hstringMax.Get()); - if (DateTimePreparser::TryParseSimpleDate(max, year, month, day)) - { - DateTime maxDate = GetDateTime(year, month, day); - if (isMinValid) - { - if (maxDate.UniversalTime > minDate.UniversalTime) - { - RETURN_IF_FAILED(datePicker->put_MaxDate(maxDate)); - } - else - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InvalidValue, - HStringReference(L"Min value must be less than max in Input.Date").Get()); - } - } - else - { - RETURN_IF_FAILED(datePicker->put_MaxDate(maxDate)); - } - } - - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Date", datePickerAsFrameworkElement.Get())); - - AddInputValueToContext(renderContext, adaptiveCardElement, *dateInputControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildNumberInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** numberInputControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Number input was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveNumberInput; - RETURN_IF_FAILED(cardElement.As(&adaptiveNumberInput)); - - ComPtr textBox = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBox)); - - ComPtr inputScopeName = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScopeName)); - RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_Number)); - - ComPtr inputScope = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScope)); - ComPtr> names; - RETURN_IF_FAILED(inputScope->get_Names(names.GetAddressOf())); - RETURN_IF_FAILED(names->Append(inputScopeName.Get())); - - RETURN_IF_FAILED(textBox->put_InputScope(inputScope.Get())); - - INT32 value; - RETURN_IF_FAILED(adaptiveNumberInput->get_Value(&value)); - - std::wstring stringValue = std::to_wstring(value); - RETURN_IF_FAILED(textBox->put_Text(HStringReference(stringValue.c_str()).Get())); - - ComPtr textBox2; - RETURN_IF_FAILED(textBox.As(&textBox2)); - - HString placeHolderText; - RETURN_IF_FAILED(adaptiveNumberInput->get_Placeholder(placeHolderText.GetAddressOf())); - RETURN_IF_FAILED(textBox2->put_PlaceholderText(placeHolderText.Get())); - - ComPtr frameworkElement; - RETURN_IF_FAILED(textBox.As(&frameworkElement)); - RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Number", frameworkElement.Get())); - - // TODO: Handle max and min? - RETURN_IF_FAILED(textBox.CopyTo(numberInputControl)); - AddInputValueToContext(renderContext, adaptiveCardElement, *numberInputControl); - - return S_OK; - } - - static HRESULT HandleKeydownForInlineAction(_In_ IKeyRoutedEventArgs* args, - _In_ IAdaptiveActionInvoker* actionInvoker, - _In_ IAdaptiveActionElement* inlineAction) - { - ABI::Windows::System::VirtualKey key; - RETURN_IF_FAILED(args->get_Key(&key)); - - if (key == ABI::Windows::System::VirtualKey::VirtualKey_Enter) - { - ComPtr coreWindowStatics; - RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Core_CoreWindow).Get(), &coreWindowStatics)); - - ComPtr coreWindow; - RETURN_IF_FAILED(coreWindowStatics->GetForCurrentThread(&coreWindow)); - - ABI::Windows::UI::Core::CoreVirtualKeyStates shiftKeyState; - RETURN_IF_FAILED(coreWindow->GetKeyState(ABI::Windows::System::VirtualKey_Shift, &shiftKeyState)); - - ABI::Windows::UI::Core::CoreVirtualKeyStates ctrlKeyState; - RETURN_IF_FAILED(coreWindow->GetKeyState(ABI::Windows::System::VirtualKey_Control, &ctrlKeyState)); - - if (shiftKeyState == ABI::Windows::UI::Core::CoreVirtualKeyStates_None && - ctrlKeyState == ABI::Windows::UI::Core::CoreVirtualKeyStates_None) - { - RETURN_IF_FAILED(actionInvoker->SendActionEvent(inlineAction)); - RETURN_IF_FAILED(args->put_Handled(true)); - } - } - - return S_OK; - } - - static bool WarnForInlineShowCard(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveActionElement* action, - const std::wstring& warning) - { - if (action != nullptr) - { - ABI::AdaptiveNamespace::ActionType actionType; - THROW_IF_FAILED(action->get_ActionType(&actionType)); - - if (actionType == ABI::AdaptiveNamespace::ActionType::ShowCard) - { - THROW_IF_FAILED(renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::UnsupportedValue, - HStringReference(warning.c_str()).Get())); - return true; - } - } - - return false; - } - - void XamlBuilder::HandleInlineAcion(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _In_ ITextBox* textBox, - _In_ IAdaptiveActionElement* inlineAction, - _COM_Outptr_ IUIElement** textBoxWithInlineAction) - { - ComPtr localTextBox(textBox); - ComPtr localInlineAction(inlineAction); - - ABI::AdaptiveNamespace::ActionType actionType; - THROW_IF_FAILED(localInlineAction->get_ActionType(&actionType)); - - ComPtr hostConfig; - THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - // Inline ShowCards are not supported for inline actions - if (WarnForInlineShowCard(renderContext, localInlineAction.Get(), L"Inline ShowCard not supported for InlineAction")) - { - THROW_IF_FAILED(localTextBox.CopyTo(textBoxWithInlineAction)); - return; - } - - // Create a grid to hold the text box and the action button - ComPtr gridStatics; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); - - ComPtr xamlGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr> columnDefinitions; - THROW_IF_FAILED(xamlGrid->get_ColumnDefinitions(&columnDefinitions)); - ComPtr gridAsPanel; - THROW_IF_FAILED(xamlGrid.As(&gridAsPanel)); - - // Create the first column and add the text box to it - ComPtr textBoxColumnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - THROW_IF_FAILED(textBoxColumnDefinition->put_Width({1, GridUnitType::GridUnitType_Star})); - THROW_IF_FAILED(columnDefinitions->Append(textBoxColumnDefinition.Get())); - - ComPtr textBoxAsFrameworkElement; - THROW_IF_FAILED(localTextBox.As(&textBoxAsFrameworkElement)); - - THROW_IF_FAILED(gridStatics->SetColumn(textBoxAsFrameworkElement.Get(), 0)); - XamlHelpers::AppendXamlElementToPanel(textBox, gridAsPanel.Get()); - - // Create a separator column - ComPtr separatorColumnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - THROW_IF_FAILED(separatorColumnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Auto})); - THROW_IF_FAILED(columnDefinitions->Append(separatorColumnDefinition.Get())); - - UINT spacingSize; - THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), ABI::AdaptiveNamespace::Spacing::Default, &spacingSize)); - - auto separator = CreateSeparator(renderContext, spacingSize, 0, {0}, false); - - ComPtr separatorAsFrameworkElement; - THROW_IF_FAILED(separator.As(&separatorAsFrameworkElement)); - - THROW_IF_FAILED(gridStatics->SetColumn(separatorAsFrameworkElement.Get(), 1)); - XamlHelpers::AppendXamlElementToPanel(separator.Get(), gridAsPanel.Get()); - - // Create a column for the button - ComPtr inlineActionColumnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - THROW_IF_FAILED(inlineActionColumnDefinition->put_Width({0, GridUnitType::GridUnitType_Auto})); - THROW_IF_FAILED(columnDefinitions->Append(inlineActionColumnDefinition.Get())); - - // Create a text box with the action title. This will be the tool tip if there's an icon - // or the content of the button otherwise - ComPtr titleTextBlock = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBlock)); - HString title; - THROW_IF_FAILED(localInlineAction->get_Title(title.GetAddressOf())); - THROW_IF_FAILED(titleTextBlock->put_Text(title.Get())); - - HString iconUrl; - THROW_IF_FAILED(localInlineAction->get_IconUrl(iconUrl.GetAddressOf())); - ComPtr actionUIElement; - if (iconUrl != nullptr) - { - // Render the icon using the adaptive image renderer - ComPtr elementRenderers; - THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); - ComPtr imageRenderer; - THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &imageRenderer)); - - ComPtr adaptiveImage; - THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - - THROW_IF_FAILED(adaptiveImage->put_Url(iconUrl.Get())); - - ComPtr adaptiveImageAsElement; - THROW_IF_FAILED(adaptiveImage.As(&adaptiveImageAsElement)); - - THROW_IF_FAILED(imageRenderer->Render(adaptiveImageAsElement.Get(), renderContext, renderArgs, &actionUIElement)); - - // Add the tool tip - ComPtr toolTip = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ToolTip)); - ComPtr toolTipAsContentControl; - THROW_IF_FAILED(toolTip.As(&toolTipAsContentControl)); - THROW_IF_FAILED(toolTipAsContentControl->put_Content(titleTextBlock.Get())); - - ComPtr toolTipService; - THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ToolTipService).Get(), - &toolTipService)); - - ComPtr actionAsDependencyObject; - THROW_IF_FAILED(actionUIElement.As(&actionAsDependencyObject)); - - THROW_IF_FAILED(toolTipService->SetToolTip(actionAsDependencyObject.Get(), toolTip.Get())); - } - else - { - // If there's no icon, just use the title text. Put it centered in a grid so it is - // centered relative to the text box. - ComPtr textBlockAsFrameworkElement; - THROW_IF_FAILED(titleTextBlock.As(&textBlockAsFrameworkElement)); - THROW_IF_FAILED(textBlockAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Center)); - - ComPtr titleGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - ComPtr panel; - THROW_IF_FAILED(titleGrid.As(&panel)); - XamlHelpers::AppendXamlElementToPanel(titleTextBlock.Get(), panel.Get()); - - THROW_IF_FAILED(panel.As(&actionUIElement)); - } - - // Make the action the same size as the text box - EventRegistrationToken eventToken; - THROW_IF_FAILED(textBoxAsFrameworkElement->add_Loaded( - Callback( - [actionUIElement, textBoxAsFrameworkElement](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - ComPtr actionFrameworkElement; - RETURN_IF_FAILED(actionUIElement.As(&actionFrameworkElement)); - - return SetMatchingHeight(actionFrameworkElement.Get(), textBoxAsFrameworkElement.Get()); - }) - .Get(), - &eventToken)); - - // Wrap the action in a button - ComPtr touchTargetUIElement; - WrapInTouchTarget(nullptr, actionUIElement.Get(), localInlineAction.Get(), renderContext, false, L"Adaptive.Input.Text.InlineAction", &touchTargetUIElement); - - ComPtr touchTargetFrameworkElement; - THROW_IF_FAILED(touchTargetUIElement.As(&touchTargetFrameworkElement)); - - // Align to bottom so the icon stays with the bottom of the text box as it grows in the multiline case - THROW_IF_FAILED(touchTargetFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Bottom)); - - // Add the action to the column - THROW_IF_FAILED(gridStatics->SetColumn(touchTargetFrameworkElement.Get(), 2)); - XamlHelpers::AppendXamlElementToPanel(touchTargetFrameworkElement.Get(), gridAsPanel.Get()); - - // If this isn't a multiline input, enter should invoke the action - ComPtr actionInvoker; - THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); - - boolean isMultiLine; - THROW_IF_FAILED(textBox->get_AcceptsReturn(&isMultiLine)); - - if (!isMultiLine) - { - ComPtr textBoxAsUIElement; - THROW_IF_FAILED(localTextBox.As(&textBoxAsUIElement)); - - EventRegistrationToken keyDownEventToken; - THROW_IF_FAILED(textBoxAsUIElement->add_KeyDown( - Callback([actionInvoker, localInlineAction](IInspectable* /*sender*/, IKeyRoutedEventArgs* args) -> HRESULT { - return HandleKeydownForInlineAction(args, actionInvoker.Get(), localInlineAction.Get()); - }) - .Get(), - &keyDownEventToken)); - } - - THROW_IF_FAILED(xamlGrid.CopyTo(textBoxWithInlineAction)); - } - - HRESULT XamlBuilder::BuildTextInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** textInputControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Text Input was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveTextInput; - RETURN_IF_FAILED(cardElement.As(&adaptiveTextInput)); - - ComPtr textBox = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TextBox)); - - boolean isMultiLine; - RETURN_IF_FAILED(adaptiveTextInput->get_IsMultiline(&isMultiLine)); - RETURN_IF_FAILED(textBox->put_AcceptsReturn(isMultiLine)); - - HString textValue; - RETURN_IF_FAILED(adaptiveTextInput->get_Value(textValue.GetAddressOf())); - RETURN_IF_FAILED(textBox->put_Text(textValue.Get())); - - UINT32 maxLength; - RETURN_IF_FAILED(adaptiveTextInput->get_MaxLength(&maxLength)); - RETURN_IF_FAILED(textBox->put_MaxLength(maxLength)); - - ComPtr textBox2; - RETURN_IF_FAILED(textBox.As(&textBox2)); - - HString placeHolderText; - RETURN_IF_FAILED(adaptiveTextInput->get_Placeholder(placeHolderText.GetAddressOf())); - RETURN_IF_FAILED(textBox2->put_PlaceholderText(placeHolderText.Get())); - - ABI::AdaptiveNamespace::TextInputStyle textInputStyle; - RETURN_IF_FAILED(adaptiveTextInput->get_TextInputStyle(&textInputStyle)); - - ComPtr inputScopeName = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScopeName)); - switch (textInputStyle) - { - case ABI::AdaptiveNamespace::TextInputStyle::Email: - RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_EmailSmtpAddress)); - break; - - case ABI::AdaptiveNamespace::TextInputStyle::Tel: - RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_TelephoneNumber)); - break; - - case ABI::AdaptiveNamespace::TextInputStyle::Url: - RETURN_IF_FAILED(inputScopeName->put_NameValue(InputScopeNameValue::InputScopeNameValue_Url)); - break; - } - - ComPtr inputScope = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Input_InputScope)); - ComPtr> names; - RETURN_IF_FAILED(inputScope->get_Names(names.GetAddressOf())); - RETURN_IF_FAILED(names->Append(inputScopeName.Get())); - - RETURN_IF_FAILED(textBox->put_InputScope(inputScope.Get())); - - ComPtr textBoxAsUIElement; - textBox.As(&textBoxAsUIElement); - AddInputValueToContext(renderContext, adaptiveCardElement, textBoxAsUIElement.Get()); - - ComPtr inlineAction; - RETURN_IF_FAILED(adaptiveTextInput->get_InlineAction(&inlineAction)); - - ComPtr textBoxAsFrameworkElement; - RETURN_IF_FAILED(textBox.As(&textBoxAsFrameworkElement)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Text", textBoxAsFrameworkElement.Get())); - - if (inlineAction != nullptr) - { - ComPtr textBoxWithInlineAction; - HandleInlineAcion(renderContext, renderArgs, textBox.Get(), inlineAction.Get(), &textBoxWithInlineAction); - if (!isMultiLine) - { - RETURN_IF_FAILED(textBoxWithInlineAction.As(&textBoxAsFrameworkElement)); - RETURN_IF_FAILED(textBoxAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - } - - RETURN_IF_FAILED(textBoxWithInlineAction.CopyTo(textInputControl)); - } - else - { - if (!isMultiLine) - { - RETURN_IF_FAILED(textBoxAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - } - - RETURN_IF_FAILED(textBox.CopyTo(textInputControl)); - } - return S_OK; - } - - HRESULT XamlBuilder::BuildTimeInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** timeInputControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Time Input was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr timePicker = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_TimePicker)); - - // Make the picker stretch full width - ComPtr timePickerAsFrameworkElement; - RETURN_IF_FAILED(timePicker.As(&timePickerAsFrameworkElement)); - RETURN_IF_FAILED(timePickerAsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); - RETURN_IF_FAILED(timePickerAsFrameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - - RETURN_IF_FAILED( - SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Time", timePickerAsFrameworkElement.Get())); - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveTimeInput; - THROW_IF_FAILED(cardElement.As(&adaptiveTimeInput)); - - // Set initial value - HString hstringValue; - THROW_IF_FAILED(adaptiveTimeInput->get_Value(hstringValue.GetAddressOf())); - std::string value = HStringToUTF8(hstringValue.Get()); - unsigned int hours, minutes; - if (DateTimePreparser::TryParseSimpleTime(value, hours, minutes)) - { - TimeSpan initialTime{(INT64)(hours * 60 + minutes) * 10000000 * 60}; - THROW_IF_FAILED(timePicker->put_Time(initialTime)); - } - - // Note: Placeholder text and min/max are not supported by ITimePicker - - RETURN_IF_FAILED(timePicker.CopyTo(timeInputControl)); - AddInputValueToContext(renderContext, adaptiveCardElement, *timeInputControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildToggleInput(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** toggleInputControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning( - ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Toggle Input was stripped from card because interactivity is not supported").Get()); - return S_OK; - } - - ComPtr cardElement(adaptiveCardElement); - ComPtr adaptiveToggleInput; - RETURN_IF_FAILED(cardElement.As(&adaptiveToggleInput)); - - ComPtr checkBox = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_CheckBox)); - - HString title; - RETURN_IF_FAILED(adaptiveToggleInput->get_Title(title.GetAddressOf())); - - boolean wrap; - adaptiveToggleInput->get_Wrap(&wrap); - - XamlHelpers::SetContent(checkBox.Get(), title.Get(), wrap); - - HString value; - RETURN_IF_FAILED(adaptiveToggleInput->get_Value(value.GetAddressOf())); - - HString valueOn; - RETURN_IF_FAILED(adaptiveToggleInput->get_ValueOn(valueOn.GetAddressOf())); - - INT32 compareValueOn; - RETURN_IF_FAILED(WindowsCompareStringOrdinal(value.Get(), valueOn.Get(), &compareValueOn)); - - XamlHelpers::SetToggleValue(checkBox.Get(), (compareValueOn == 0)); - - ComPtr checkboxAsUIElement; - RETURN_IF_FAILED(checkBox.As(&checkboxAsUIElement)); - RETURN_IF_FAILED(AddHandledTappedEvent(checkboxAsUIElement.Get())); - - ComPtr frameworkElement; - RETURN_IF_FAILED(checkBox.As(&frameworkElement)); - RETURN_IF_FAILED(frameworkElement->put_VerticalAlignment(ABI::Windows::UI::Xaml::VerticalAlignment_Top)); - RETURN_IF_FAILED(SetStyleFromResourceDictionary(renderContext, L"Adaptive.Input.Toggle", frameworkElement.Get())); - - RETURN_IF_FAILED(checkboxAsUIElement.CopyTo(toggleInputControl)); - AddInputValueToContext(renderContext, adaptiveCardElement, *toggleInputControl); - return S_OK; - } - - HRESULT XamlBuilder::BuildMedia(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** mediaControl) - { - ComPtr localCardElement{adaptiveCardElement}; - ComPtr adaptiveMedia; - RETURN_IF_FAILED(localCardElement.As(&adaptiveMedia)); - - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - // Get the poster image - ComPtr posterImage; - GetMediaPosterAsImage(renderContext, renderArgs, adaptiveMedia.Get(), &posterImage); - - // If the host doesn't support interactivity we're done here, just return the poster image - if (!SupportsInteractivity(hostConfig.Get())) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"Media was present in card, but interactivity is not supported").Get()); - - if (posterImage != nullptr) - { - RETURN_IF_FAILED(posterImage.CopyTo(mediaControl)); - } - - return S_OK; - } - - // Put the poster image in a container with a play button - ComPtr posterContainer; - CreatePosterContainerWithPlayButton(posterImage.Get(), renderContext, renderArgs, &posterContainer); - - ComPtr touchTargetUIElement; - WrapInTouchTarget(adaptiveCardElement, posterContainer.Get(), nullptr, renderContext, true, L"Adaptive.SelectAction", &touchTargetUIElement); - - // Create a panel to hold the poster and the media element - ComPtr mediaStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - ComPtr mediaPanel; - RETURN_IF_FAILED(mediaStackPanel.As(&mediaPanel)); - - XamlHelpers::AppendXamlElementToPanel(touchTargetUIElement.Get(), mediaPanel.Get()); - - // Check if this host allows inline playback - ComPtr mediaConfig; - RETURN_IF_FAILED(hostConfig->get_Media(&mediaConfig)); - - boolean allowInlinePlayback; - RETURN_IF_FAILED(mediaConfig->get_AllowInlinePlayback(&allowInlinePlayback)); - - ComPtr mediaInvoker; - RETURN_IF_FAILED(renderContext->get_MediaEventInvoker(&mediaInvoker)); - - HString mimeType; - ComPtr mediaElement; - ComPtr mediaSourceUrl; - if (allowInlinePlayback) - { - // Create a media element and set it's source - mediaElement = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_MediaElement)); - - GetMediaSource(hostConfig.Get(), adaptiveMedia.Get(), mediaSourceUrl.GetAddressOf(), mimeType.GetAddressOf()); - - if (mediaSourceUrl == nullptr) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::UnsupportedMediaType, - HStringReference(L"Unsupported media element dropped").Get()); - return S_OK; - } - - // Configure Auto Play and Controls - RETURN_IF_FAILED(mediaElement->put_AutoPlay(false)); - - ComPtr mediaElement2; - RETURN_IF_FAILED(mediaElement.As(&mediaElement2)); - RETURN_IF_FAILED(mediaElement2->put_AreTransportControlsEnabled(true)); - ComPtr mediaElement3; - RETURN_IF_FAILED(mediaElement.As(&mediaElement3)); - ComPtr mediaTransportControl; - RETURN_IF_FAILED(mediaElement3->get_TransportControls(&mediaTransportControl)); - RETURN_IF_FAILED(mediaTransportControl->put_IsCompact(true)); - RETURN_IF_FAILED(mediaTransportControl->put_IsZoomButtonVisible(false)); - - ComPtr mediaUIElement; - RETURN_IF_FAILED(mediaElement.As(&mediaUIElement)); - - if (posterImage != nullptr) - { - // Set the poster on the media element - ComPtr posterImageSource; - RETURN_IF_FAILED(posterImage->get_Source(&posterImageSource)); - RETURN_IF_FAILED(mediaElement->put_PosterSource(posterImageSource.Get())); - } - - // Make the media element collapsed until the user clicks - RETURN_IF_FAILED(mediaUIElement->put_Visibility(Visibility_Collapsed)); - - XamlHelpers::AppendXamlElementToPanel(mediaElement.Get(), mediaPanel.Get()); - } - - ComPtr mediaPanelAsUIElement; - RETURN_IF_FAILED(mediaPanel.As(&mediaPanelAsUIElement)); - - ComPtr touchTargetAsButtonBase; - RETURN_IF_FAILED(touchTargetUIElement.As(&touchTargetAsButtonBase)); - - // Take a reference to the mime type string for the lambda - HSTRING lambdaMimeType; - WindowsDuplicateString(mimeType.Get(), &lambdaMimeType); - ComPtr lambdaRenderContext{renderContext}; - - EventRegistrationToken clickToken; - RETURN_IF_FAILED(touchTargetAsButtonBase->add_Click( - Callback( - [touchTargetUIElement, lambdaRenderContext, adaptiveMedia, mediaElement, mediaSourceUrl, lambdaMimeType, mediaInvoker]( - IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - // Take ownership of the passed in HSTRING - HString localMimeType; - localMimeType.Attach(lambdaMimeType); - - // Turn off the button to prevent extra clicks - ComPtr buttonAsControl; - touchTargetUIElement.As(&buttonAsControl); - RETURN_IF_FAILED(buttonAsControl->put_IsEnabled(false)); - - // Handle the click - return HandleMediaClick(lambdaRenderContext.Get(), - adaptiveMedia.Get(), - mediaElement.Get(), - touchTargetUIElement.Get(), - mediaSourceUrl.Get(), - lambdaMimeType, - mediaInvoker.Get()); - }) - .Get(), - &clickToken)); - - RETURN_IF_FAILED(mediaPanelAsUIElement.CopyTo(mediaControl)); - return S_OK; - } - - bool XamlBuilder::SupportsInteractivity(_In_ IAdaptiveHostConfig* hostConfig) - { - boolean supportsInteractivity; - THROW_IF_FAILED(hostConfig->get_SupportsInteractivity(&supportsInteractivity)); - return Boolify(supportsInteractivity); - } - - void XamlBuilder::WrapInTouchTarget(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IUIElement* elementToWrap, - _In_ IAdaptiveActionElement* action, - _In_ IAdaptiveRenderContext* renderContext, - bool fullWidth, - const std::wstring& style, - _COM_Outptr_ IUIElement** finalElement) - { - ComPtr hostConfig; - THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - if (WarnForInlineShowCard(renderContext, action, L"Inline ShowCard not supported for SelectAction")) - { - // Was inline show card, so don't wrap the element and just return - ComPtr localElementToWrap(elementToWrap); - localElementToWrap.CopyTo(finalElement); - return; - } - - ComPtr button = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); - - ComPtr buttonAsContentControl; - THROW_IF_FAILED(button.As(&buttonAsContentControl)); - THROW_IF_FAILED(buttonAsContentControl->put_Content(elementToWrap)); - - ComPtr spacingConfig; - THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 cardPadding = 0; - if (fullWidth) - { - THROW_IF_FAILED(spacingConfig->get_Padding(&cardPadding)); - } - - ComPtr buttonAsFrameworkElement; - THROW_IF_FAILED(button.As(&buttonAsFrameworkElement)); - - // We want the hit target to equally split the vertical space above and below the current item. - // However, all we know is the spacing of the current item, which only applies to the spacing above. - // We don't know what the spacing of the NEXT element will be, so we can't calculate the correct spacing - // below. For now, we'll simply assume the bottom spacing is the same as the top. NOTE: Only apply spacings - // (padding, margin) for adaptive card elements to avoid adding spacings to card-level selectAction. - if (adaptiveCardElement != nullptr) - { - ABI::AdaptiveNamespace::Spacing elementSpacing; - THROW_IF_FAILED(adaptiveCardElement->get_Spacing(&elementSpacing)); - UINT spacingSize; - THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), elementSpacing, &spacingSize)); - double topBottomPadding = spacingSize / 2.0; - - // For button padding, we apply the cardPadding and topBottomPadding (and then we negate these in the margin) - ComPtr buttonAsControl; - THROW_IF_FAILED(button.As(&buttonAsControl)); - THROW_IF_FAILED(buttonAsControl->put_Padding({(double)cardPadding, topBottomPadding, (double)cardPadding, topBottomPadding})); - - double negativeCardMargin = cardPadding * -1.0; - double negativeTopBottomMargin = topBottomPadding * -1.0; - - THROW_IF_FAILED(buttonAsFrameworkElement->put_Margin( - {negativeCardMargin, negativeTopBottomMargin, negativeCardMargin, negativeTopBottomMargin})); - } - - // Style the hit target button - THROW_IF_FAILED(SetStyleFromResourceDictionary(renderContext, style.c_str(), buttonAsFrameworkElement.Get())); - - if (action != nullptr) - { - // If we have an action, use the title for the AutomationProperties.Name - HString title; - THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); - - ComPtr buttonAsDependencyObject; - THROW_IF_FAILED(button.As(&buttonAsDependencyObject)); - - ComPtr automationPropertiesStatics; - THROW_IF_FAILED( - GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), - &automationPropertiesStatics)); - - THROW_IF_FAILED(automationPropertiesStatics->SetName(buttonAsDependencyObject.Get(), title.Get())); - - WireButtonClickToAction(button.Get(), action, renderContext); - } - - THROW_IF_FAILED(button.CopyTo(finalElement)); - } - - void XamlBuilder::HandleSelectAction(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveActionElement* selectAction, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IUIElement* uiElement, - bool supportsInteractivity, - bool fullWidthTouchTarget, - _COM_Outptr_ IUIElement** outUiElement) - { - if (selectAction != nullptr && supportsInteractivity) - { - WrapInTouchTarget(adaptiveCardElement, uiElement, selectAction, renderContext, fullWidthTouchTarget, L"Adaptive.SelectAction", outUiElement); - } - else - { - if (selectAction != nullptr) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"SelectAction present, but Interactivity is not supported").Get()); - } - - ComPtr localUiElement(uiElement); - THROW_IF_FAILED(localUiElement.CopyTo(outUiElement)); - } - } - - void XamlBuilder::WireButtonClickToAction(_In_ IButton* button, _In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext) - { - // Note that this method currently doesn't support inline show card actions, it - // assumes the caller won't call this method if inline show card is specified. - ComPtr localButton(button); - ComPtr actionInvoker; - THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); - ComPtr strongAction(action); - - // Add click handler - ComPtr buttonBase; - THROW_IF_FAILED(localButton.As(&buttonBase)); - - EventRegistrationToken clickToken; - THROW_IF_FAILED(buttonBase->add_Click(Callback( - [strongAction, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - THROW_IF_FAILED(actionInvoker->SendActionEvent(strongAction.Get())); - return S_OK; - }) - .Get(), - &clickToken)); - } - - HRESULT XamlBuilder::AddHandledTappedEvent(_In_ IUIElement* uiElement) - { - if (uiElement == nullptr) - { - return E_INVALIDARG; - } - - EventRegistrationToken clickToken; - // Add Tap handler that sets the event as handled so that it doesn't propagate to the parent containers. - return uiElement->add_Tapped(Callback([](IInspectable* /*sender*/, ITappedRoutedEventArgs* args) -> HRESULT { - return args->put_Handled(TRUE); - }) - .Get(), - &clickToken); - } - - template - static void XamlBuilder::SetVerticalContentAlignmentToChildren(_In_ T* container, - _In_ ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment) - { - ComPtr localContainer(container); - ComPtr containerAsPanel; - THROW_IF_FAILED(localContainer.As(&containerAsPanel)); - - ComPtr panel = PeekInnards(containerAsPanel); - panel->SetVerticalContentAlignment(verticalContentAlignment); - } } diff --git a/source/uwp/Renderer/lib/XamlBuilder.h b/source/uwp/Renderer/lib/XamlBuilder.h index d3298c1ecb..9d706ceaf2 100644 --- a/source/uwp/Renderer/lib/XamlBuilder.h +++ b/source/uwp/Renderer/lib/XamlBuilder.h @@ -2,15 +2,12 @@ // Licensed under the MIT License. #pragma once -#include "AdaptiveCards.Rendering.Uwp.h" #include "ImageLoadTracker.h" #include "IXamlBuilderListener.h" #include "IImageLoadTrackerListener.h" -#include #include "InputValue.h" #include "RenderedAdaptiveCard.h" #include "AdaptiveRenderContext.h" -#include namespace AdaptiveNamespace { @@ -26,111 +23,32 @@ namespace AdaptiveNamespace public: // IImageLoadTrackerListener - STDMETHODIMP AllImagesLoaded(); - STDMETHODIMP ImagesLoadingHadError(); - - static HRESULT BuildXamlTreeFromAdaptiveCard( - _In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _COM_Outptr_ ABI::Windows::UI::Xaml::IFrameworkElement** xamlTreeRoot, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - Microsoft::WRL::ComPtr xamlBuilder, - ABI::AdaptiveNamespace::ContainerStyle defaultContainerStyle = ABI::AdaptiveNamespace::ContainerStyle::Default); + STDMETHODIMP AllImagesLoaded() noexcept; + STDMETHODIMP ImagesLoadingHadError() noexcept; + + static HRESULT BuildXamlTreeFromAdaptiveCard(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _COM_Outptr_ ABI::Windows::UI::Xaml::IFrameworkElement** xamlTreeRoot, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + Microsoft::WRL::ComPtr xamlBuilder, + ABI::AdaptiveNamespace::ContainerStyle defaultContainerStyle = + ABI::AdaptiveNamespace::ContainerStyle::Default) noexcept; HRESULT AddListener(_In_ IXamlBuilderListener* listener) noexcept; HRESULT RemoveListener(_In_ IXamlBuilderListener* listener) noexcept; - HRESULT SetFixedDimensions(UINT width, UINT height) noexcept; - HRESULT SetEnableXamlImageHandling(bool enableXamlImageHandling) noexcept; + void SetFixedDimensions(UINT width, UINT height) noexcept; + void SetEnableXamlImageHandling(bool enableXamlImageHandling) noexcept; + + static HRESULT BuildPanelChildren( + _In_ ABI::Windows::Foundation::Collections::IVector* children, + _In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* context, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + std::function childCreatedCallback) noexcept; HRESULT BuildImage(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** imageControl); - static HRESULT BuildRichTextBlock(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textBlockControl); - static HRESULT BuildTextBlock(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textBlockControl); - static HRESULT BuildContainer(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** containerControl); - static HRESULT BuildColumn(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** columnControl); - static HRESULT BuildColumnSet(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** columnSetControl); - static HRESULT BuildFactSet(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** factSetControl); - static HRESULT BuildImageSet(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** imageSetControl); - static HRESULT BuildChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceSetInputControl); - static HRESULT BuildDateInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** dateInputControl); - static HRESULT BuildNumberInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** numberInputControl); - static HRESULT BuildTextInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textInputControl); - static HRESULT BuildTimeInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** timeInputControl); - static HRESULT BuildToggleInput(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** toggleInputControl); - static HRESULT BuildMedia(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** mediaControl); - static HRESULT BuildActionSet(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** containerControl); - static HRESULT BuildShowCard(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* showCard, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - bool isBottomActionBar, - _Outptr_ ABI::Windows::UI::Xaml::IUIElement** uiShowCard); - static HRESULT BuildAction(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* adaptiveActionElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionControl); - - template - static HRESULT TryGetResourceFromResourceDictionaries(_In_ ABI::Windows::UI::Xaml::IResourceDictionary* resourceDictionary, - std::wstring resourceName, - _COM_Outptr_result_maybenull_ T** resource); - - static HRESULT TryInsertResourceToResourceDictionaries(_In_ ABI::Windows::UI::Xaml::IResourceDictionary* resourceDictionary, - std::wstring resourceName, - _In_ IInspectable* value); - - static HRESULT SetStyleFromResourceDictionary(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - std::wstring resourceName, - _In_ ABI::Windows::UI::Xaml::IFrameworkElement* frameworkElement); - - static HRESULT HandleToggleVisibilityClick(_In_ ABI::Windows::UI::Xaml::IFrameworkElement* cardFrameworkElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action); - private: XamlBuilder(); @@ -147,17 +65,12 @@ namespace AdaptiveNamespace bool m_enableXamlImageHandling = false; Microsoft::WRL::ComPtr m_resourceResolvers; - static Microsoft::WRL::ComPtr - CreateRootCardElement(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - Microsoft::WRL::ComPtr xamlBuilder, - _Outptr_ ABI::Windows::UI::Xaml::Controls::IPanel** bodyElementContainer); - - static void ApplyBackgroundToRoot(_In_ ABI::Windows::UI::Xaml::Controls::IPanel* rootPanel, - _In_ ABI::AdaptiveNamespace::IAdaptiveBackgroundImage* backgroundImage, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); + static HRESULT CreateRootCardElement(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + Microsoft::WRL::ComPtr xamlBuilder, + _COM_Outptr_ ABI::Windows::UI::Xaml::Controls::IPanel** bodyElementContainer, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** rootUIElement) noexcept; template void SetAutoSize(T* destination, IInspectable* parentElement, IInspectable* imageContainer, bool isVisible, bool imageFiresOpenEvent); @@ -179,115 +92,8 @@ namespace AdaptiveNamespace template void PopulateImageFromUrlAsync(_In_ ABI::Windows::Foundation::IUriRuntimeClass* imageUrl, _In_ T* imageControl); + void FireAllImagesLoaded(); void FireImagesLoadingHadError(); - - static void ArrangeButtonContent(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionsConfig* actionsConfig, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - ABI::AdaptiveNamespace::ContainerStyle containerStyle, - _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, - bool allActionsHaveIcons, - _In_ ABI::Windows::UI::Xaml::Controls::IButton* button); - - static HRESULT BuildActions(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_ ABI::Windows::Foundation::Collections::IVector* children, - _In_ ABI::Windows::UI::Xaml::Controls::IPanel* bodyPanel, - bool insertSeparator, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); - - static HRESULT BuildActionSetHelper( - _In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_opt_ ABI::AdaptiveNamespace::IAdaptiveActionSet* actionSet, - _In_ ABI::Windows::Foundation::Collections::IVector* children, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionSetControl); - - static void XamlBuilder::HandleInlineAcion(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _In_ ABI::Windows::UI::Xaml::Controls::ITextBox* textBox, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* inlineAction, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textBoxWithInlineAction); - - static Microsoft::WRL::ComPtr CreateSeparator(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - UINT spacing, - UINT separatorThickness, - ABI::Windows::UI::Color separatorColor, - bool isHorizontal = true); - static void ApplyMarginToXamlElement(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, - _In_ ABI::Windows::UI::Xaml::IFrameworkElement* element); - static void AddSeparatorIfNeeded(int& currentElement, - _In_ ABI::AdaptiveCards::Rendering::Uwp::IAdaptiveCardElement* element, - _In_ ABI::AdaptiveCards::Rendering::Uwp::IAdaptiveHostConfig* hostConfig, - _In_ ABI::AdaptiveCards::Rendering::Uwp::IAdaptiveRenderContext* renderContext, - _In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel, - _Outptr_ ABI::Windows::UI::Xaml::IUIElement** addedSeparator); - static HRESULT BuildPanelChildren( - _In_ ABI::Windows::Foundation::Collections::IVector* children, - _In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* context, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - std::function childCreatedCallback); - static void GetSeparationConfigForElement(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* element, - _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, - _Out_ UINT* spacing, - _Out_ UINT* separatorThickness, - _Out_ ABI::Windows::UI::Color* separatorColor, - _Out_ bool* needsSeparator); - static HRESULT BuildCompactChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSetControl); - static HRESULT BuildExpandedChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceInputSet, - boolean isMultiSelect, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceSetInputControl); - static bool SupportsInteractivity(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig); - - static void WrapInTouchTarget(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::Windows::UI::Xaml::IUIElement* elementToWrap, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - bool fullWidth, - const std::wstring& style, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** finalElement); - - void static HandleSelectAction(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* selectAction, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::Windows::UI::Xaml::IUIElement* uiElement, - bool supportsInteractivity, - bool fullWidthTouchTarget, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** outUiElement); - - static void WireButtonClickToAction(_In_ ABI::Windows::UI::Xaml::Controls::IButton* button, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); - - static HRESULT AddHandledTappedEvent(_In_ ABI::Windows::UI::Xaml::IUIElement* uiElement); - - static HRESULT SetAutoImageSize(_In_ ABI::Windows::UI::Xaml::IFrameworkElement* imageControl, - _In_ IInspectable* parentElement, - _In_ ABI::Windows::UI::Xaml::Media::Imaging::IBitmapSource* imageSource, - bool setVisible); - - static HRESULT SetMatchingHeight(_In_ ABI::Windows::UI::Xaml::IFrameworkElement* elementToChange, - _In_ ABI::Windows::UI::Xaml::IFrameworkElement* elementToMatch); - - template - static void SetVerticalContentAlignmentToChildren(_In_ T* container, - _In_ ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment); - - static ABI::Windows::UI::Xaml::Thickness GetButtonMargin(_In_ ABI::AdaptiveNamespace::IAdaptiveActionsConfig* actionsConfig); - - static HRESULT HandleActionStyling(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* adaptiveActionElement, - _In_ ABI::Windows::UI::Xaml::IFrameworkElement* buttonFrameworkElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); - - static HRESULT RenderFallback(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* currentElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result); }; } diff --git a/source/uwp/Renderer/lib/XamlHelpers.cpp b/source/uwp/Renderer/lib/XamlHelpers.cpp new file mode 100644 index 0000000000..f2c5f9038f --- /dev/null +++ b/source/uwp/Renderer/lib/XamlHelpers.cpp @@ -0,0 +1,1059 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "pch.h" + +#include "XamlHelpers.h" + +#include "ActionHelpers.h" +#include "ElementTagContent.h" +#include "TileControl.h" +#include "AdaptiveShowCardActionRenderer.h" +#include "AdaptiveImage.h" + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::AdaptiveNamespace; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Automation; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Controls::Primitives; +using namespace ABI::Windows::UI::Xaml::Input; +using namespace ABI::Windows::UI::Xaml::Media; +using namespace ABI::Windows::UI::Xaml::Media::Imaging; + +namespace AdaptiveNamespace::XamlHelpers +{ + constexpr PCWSTR c_BackgroundImageOverlayBrushKey = L"AdaptiveCard.BackgroundOverlayBrush"; + + ComPtr CreateSeparator(_In_ IAdaptiveRenderContext* renderContext, + UINT spacing, + UINT separatorThickness, + ABI::Windows::UI::Color separatorColor, + bool isHorizontal) + { + ComPtr separator = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + ComPtr separatorAsFrameworkElement; + THROW_IF_FAILED(separator.As(&separatorAsFrameworkElement)); + + ComPtr lineColorBrush = XamlHelpers::GetSolidColorBrush(separatorColor); + ComPtr separatorAsPanel; + THROW_IF_FAILED(separator.As(&separatorAsPanel)); + separatorAsPanel->put_Background(lineColorBrush.Get()); + + const UINT32 separatorMarginValue = spacing > separatorThickness ? (spacing - separatorThickness) / 2 : 0; + Thickness margin = {0, 0, 0, 0}; + + if (isHorizontal) + { + margin.Top = margin.Bottom = separatorMarginValue; + separatorAsFrameworkElement->put_Height(separatorThickness); + } + else + { + margin.Left = margin.Right = separatorMarginValue; + separatorAsFrameworkElement->put_Width(separatorThickness); + } + + THROW_IF_FAILED(separatorAsFrameworkElement->put_Margin(margin)); + + THROW_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Separator", + separatorAsFrameworkElement.Get())); + + ComPtr result; + THROW_IF_FAILED(separator.As(&result)); + return result; + } + + HRESULT SetStyleFromResourceDictionary(_In_ IAdaptiveRenderContext* renderContext, + const std::wstring& resourceName, + _In_ IFrameworkElement* frameworkElement) noexcept + { + ComPtr resourceDictionary; + RETURN_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); + + ComPtr style; + if (SUCCEEDED(TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), resourceName, &style))) + { + RETURN_IF_FAILED(frameworkElement->put_Style(style.Get())); + } + + return S_OK; + } + + void WrapInTouchTarget(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IUIElement* elementToWrap, + _In_ IAdaptiveActionElement* action, + _In_ IAdaptiveRenderContext* renderContext, + bool fullWidth, + const std::wstring& style, + _COM_Outptr_ IUIElement** finalElement) + { + ComPtr hostConfig; + THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + if (ActionHelpers::WarnForInlineShowCard(renderContext, action, L"Inline ShowCard not supported for SelectAction")) + { + // Was inline show card, so don't wrap the element and just return + ComPtr localElementToWrap(elementToWrap); + localElementToWrap.CopyTo(finalElement); + return; + } + + ComPtr button = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); + + ComPtr buttonAsContentControl; + THROW_IF_FAILED(button.As(&buttonAsContentControl)); + THROW_IF_FAILED(buttonAsContentControl->put_Content(elementToWrap)); + + ComPtr spacingConfig; + THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + + UINT32 cardPadding = 0; + if (fullWidth) + { + THROW_IF_FAILED(spacingConfig->get_Padding(&cardPadding)); + } + + ComPtr buttonAsFrameworkElement; + THROW_IF_FAILED(button.As(&buttonAsFrameworkElement)); + + // We want the hit target to equally split the vertical space above and below the current item. + // However, all we know is the spacing of the current item, which only applies to the spacing above. + // We don't know what the spacing of the NEXT element will be, so we can't calculate the correct spacing + // below. For now, we'll simply assume the bottom spacing is the same as the top. NOTE: Only apply spacings + // (padding, margin) for adaptive card elements to avoid adding spacings to card-level selectAction. + if (adaptiveCardElement != nullptr) + { + ABI::AdaptiveNamespace::Spacing elementSpacing; + THROW_IF_FAILED(adaptiveCardElement->get_Spacing(&elementSpacing)); + UINT spacingSize; + THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), elementSpacing, &spacingSize)); + double topBottomPadding = spacingSize / 2.0; + + // For button padding, we apply the cardPadding and topBottomPadding (and then we negate these in the margin) + ComPtr buttonAsControl; + THROW_IF_FAILED(button.As(&buttonAsControl)); + THROW_IF_FAILED(buttonAsControl->put_Padding({(double)cardPadding, topBottomPadding, (double)cardPadding, topBottomPadding})); + + double negativeCardMargin = cardPadding * -1.0; + double negativeTopBottomMargin = topBottomPadding * -1.0; + + THROW_IF_FAILED(buttonAsFrameworkElement->put_Margin( + {negativeCardMargin, negativeTopBottomMargin, negativeCardMargin, negativeTopBottomMargin})); + } + + // Style the hit target button + THROW_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, style.c_str(), buttonAsFrameworkElement.Get())); + + if (action != nullptr) + { + // If we have an action, use the title for the AutomationProperties.Name + HString title; + THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); + + ComPtr buttonAsDependencyObject; + THROW_IF_FAILED(button.As(&buttonAsDependencyObject)); + + ComPtr automationPropertiesStatics; + THROW_IF_FAILED( + GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), + &automationPropertiesStatics)); + + THROW_IF_FAILED(automationPropertiesStatics->SetName(buttonAsDependencyObject.Get(), title.Get())); + + WireButtonClickToAction(button.Get(), action, renderContext); + } + + THROW_IF_FAILED(button.CopyTo(finalElement)); + } + + void WireButtonClickToAction(_In_ IButton* button, _In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext) + { + // Note that this method currently doesn't support inline show card actions, it + // assumes the caller won't call this method if inline show card is specified. + ComPtr localButton(button); + ComPtr actionInvoker; + THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); + ComPtr strongAction(action); + + // Add click handler + ComPtr buttonBase; + THROW_IF_FAILED(localButton.As(&buttonBase)); + + EventRegistrationToken clickToken; + THROW_IF_FAILED(buttonBase->add_Click(Callback([strongAction, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + THROW_IF_FAILED(actionInvoker->SendActionEvent(strongAction.Get())); + return S_OK; + }).Get(), + &clickToken)); + } + + HRESULT XamlHelpers::SetSeparatorVisibility(_In_ IPanel* parentPanel) + { + // Iterate over the elements in a container and ensure that the correct separators are marked as visible + ComPtr> children; + RETURN_IF_FAILED(parentPanel->get_Children(&children)); + + bool foundPreviousVisibleElement = false; + XamlHelpers::IterateOverVector(children.Get(), [&](IUIElement* child) { + ComPtr localChild(child); + + ComPtr childAsFrameworkElement; + RETURN_IF_FAILED(localChild.As(&childAsFrameworkElement)); + + // Get the tag for the element. The separators themselves will not have tags. + ComPtr tag; + RETURN_IF_FAILED(childAsFrameworkElement->get_Tag(&tag)); + + if (tag) + { + ComPtr elementTagContent; + RETURN_IF_FAILED(tag.As(&elementTagContent)); + + ComPtr separator; + RETURN_IF_FAILED(elementTagContent->get_Separator(&separator)); + + Visibility visibility; + RETURN_IF_FAILED(child->get_Visibility(&visibility)); + + boolean expectedVisibility{}; + RETURN_IF_FAILED(elementTagContent->get_ExpectedVisibility(&expectedVisibility)); + + if (separator) + { + if (!expectedVisibility || !foundPreviousVisibleElement) + { + // If the element is collapsed, or if it's the first visible element, collapse the separator + // Images are hidden while they are retrieved, we shouldn't hide the separator + RETURN_IF_FAILED(separator->put_Visibility(Visibility_Collapsed)); + } + else + { + // Otherwise show the separator + RETURN_IF_FAILED(separator->put_Visibility(Visibility_Visible)); + } + } + + foundPreviousVisibleElement |= (visibility == Visibility_Visible); + } + + return S_OK; + }); + + return S_OK; + } + + HRESULT HandleStylingAndPadding(_In_ IAdaptiveContainerBase* adaptiveContainer, + _In_ IBorder* containerBorder, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _Out_ ABI::AdaptiveNamespace::ContainerStyle* containerStyle) + { + ABI::AdaptiveNamespace::ContainerStyle localContainerStyle; + RETURN_IF_FAILED(adaptiveContainer->get_Style(&localContainerStyle)); + + ABI::AdaptiveNamespace::ContainerStyle parentContainerStyle; + RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&parentContainerStyle)); + + bool hasExplicitContainerStyle{true}; + if (localContainerStyle == ABI::AdaptiveNamespace::ContainerStyle::None) + { + hasExplicitContainerStyle = false; + localContainerStyle = parentContainerStyle; + } + + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + ComPtr spacingConfig; + RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + + UINT32 padding; + RETURN_IF_FAILED(spacingConfig->get_Padding(&padding)); + DOUBLE paddingAsDouble = static_cast(padding); + + // If container style was explicitly assigned, apply background color and padding + if (hasExplicitContainerStyle) + { + ABI::Windows::UI::Color backgroundColor; + RETURN_IF_FAILED(GetBackgroundColorFromStyle(localContainerStyle, hostConfig.Get(), &backgroundColor)); + ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(backgroundColor); + RETURN_IF_FAILED(containerBorder->put_Background(backgroundColorBrush.Get())); + + // If the container style doesn't match its parent apply padding. + if (localContainerStyle != parentContainerStyle) + { + Thickness paddingThickness = {paddingAsDouble, paddingAsDouble, paddingAsDouble, paddingAsDouble}; + RETURN_IF_FAILED(containerBorder->put_Padding(paddingThickness)); + } + } + + // Find out which direction(s) we bleed in, and apply a negative margin to cause the + // container to bleed + ABI::AdaptiveNamespace::BleedDirection bleedDirection; + RETURN_IF_FAILED(adaptiveContainer->get_BleedDirection(&bleedDirection)); + + Thickness marginThickness = {0}; + if (bleedDirection != ABI::AdaptiveNamespace::BleedDirection::None) + { + if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Left) != ABI::AdaptiveNamespace::BleedDirection::None) + { + marginThickness.Left = -paddingAsDouble; + } + + if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Right) != ABI::AdaptiveNamespace::BleedDirection::None) + { + marginThickness.Right = -paddingAsDouble; + } + + if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Up) != ABI::AdaptiveNamespace::BleedDirection::None) + { + marginThickness.Top = -paddingAsDouble; + } + + if ((bleedDirection & ABI::AdaptiveNamespace::BleedDirection::Down) != ABI::AdaptiveNamespace::BleedDirection::None) + { + marginThickness.Bottom = -paddingAsDouble; + } + + ComPtr localContainerBorder(containerBorder); + ComPtr containerBorderAsFrameworkElement; + RETURN_IF_FAILED(localContainerBorder.As(&containerBorderAsFrameworkElement)); + RETURN_IF_FAILED(containerBorderAsFrameworkElement->put_Margin(marginThickness)); + } + + *containerStyle = localContainerStyle; + + return S_OK; + } + + void AddInputValueToContext(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IUIElement* inputUiElement) + { + ComPtr cardElement(adaptiveCardElement); + ComPtr inputElement; + THROW_IF_FAILED(cardElement.As(&inputElement)); + + ComPtr input; + THROW_IF_FAILED(MakeAndInitialize(&input, inputElement.Get(), inputUiElement)); + THROW_IF_FAILED(renderContext->AddInputValue(input.Get())); + } + + bool SupportsInteractivity(_In_ IAdaptiveHostConfig* hostConfig) + { + boolean supportsInteractivity; + THROW_IF_FAILED(hostConfig->get_SupportsInteractivity(&supportsInteractivity)); + return Boolify(supportsInteractivity); + } + + HRESULT HandleColumnWidth(_In_ IAdaptiveColumn* column, boolean isVisible, _In_ IColumnDefinition* columnDefinition) + { + HString adaptiveColumnWidth; + RETURN_IF_FAILED(column->get_Width(adaptiveColumnWidth.GetAddressOf())); + + INT32 isStretchResult; + RETURN_IF_FAILED(WindowsCompareStringOrdinal(adaptiveColumnWidth.Get(), HStringReference(L"stretch").Get(), &isStretchResult)); + const boolean isStretch = (isStretchResult == 0); + + INT32 isAutoResult; + RETURN_IF_FAILED(WindowsCompareStringOrdinal(adaptiveColumnWidth.Get(), HStringReference(L"auto").Get(), &isAutoResult)); + const boolean isAuto = (isAutoResult == 0); + + double widthAsDouble = _wtof(adaptiveColumnWidth.GetRawBuffer(nullptr)); + UINT32 pixelWidth = 0; + RETURN_IF_FAILED(column->get_PixelWidth(&pixelWidth)); + + // Valid widths are "auto", "stretch", a pixel width ("50px"), unset, or a value greater than 0 to use as a star value ("2") + const boolean isValidWidth = isAuto || isStretch || pixelWidth || !adaptiveColumnWidth.IsValid() || (widthAsDouble > 0); + + GridLength columnWidth; + if (!isVisible || isAuto || !isValidWidth) + { + // If the column isn't visible, or is set to "auto" or an invalid value ("-1", "foo"), set it to Auto + columnWidth.GridUnitType = GridUnitType::GridUnitType_Auto; + columnWidth.Value = 0; + } + else if (pixelWidth) + { + // If it's visible and pixel width is specified, use pixel width + columnWidth.GridUnitType = GridUnitType::GridUnitType_Pixel; + columnWidth.Value = pixelWidth; + } + else if (isStretch || !adaptiveColumnWidth.IsValid()) + { + // If it's visible and stretch is specified, or width is unset, use stretch with default of 1 + columnWidth.GridUnitType = GridUnitType::GridUnitType_Star; + columnWidth.Value = 1; + } + else + { + // If it's visible and the user specified a valid non-pixel width, use that as a star width + columnWidth.GridUnitType = GridUnitType::GridUnitType_Star; + columnWidth.Value = _wtof(adaptiveColumnWidth.GetRawBuffer(nullptr)); + } + + RETURN_IF_FAILED(columnDefinition->put_Width(columnWidth)); + + return S_OK; + } + + void ApplyBackgroundToRoot(_In_ IPanel* rootPanel, + _In_ IAdaptiveBackgroundImage* backgroundImage, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs) + { + // In order to reuse the image creation code paths, we simply create an adaptive card + // image element and then build that into xaml and apply to the root. + ComPtr adaptiveImage; + HSTRING url; + THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); + THROW_IF_FAILED(backgroundImage->get_Url(&url)); + THROW_IF_FAILED(adaptiveImage->put_Url(url)); + + ComPtr adaptiveCardElement; + THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); + + ComPtr elementRenderers; + THROW_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + + ComPtr elementRenderer; + THROW_IF_FAILED(elementRenderers->Get(HStringReference(L"Image").Get(), &elementRenderer)); + + ComPtr background; + if (elementRenderer != nullptr) + { + elementRenderer->Render(adaptiveCardElement.Get(), renderContext, renderArgs, &background); + if (background == nullptr) + { + return; + } + } + + ComPtr xamlImage; + THROW_IF_FAILED(background.As(&xamlImage)); + + ABI::AdaptiveNamespace::BackgroundImageFillMode fillMode; + THROW_IF_FAILED(backgroundImage->get_FillMode(&fillMode)); + + // Creates the background image for all fill modes + ComPtr tileControl; + THROW_IF_FAILED(MakeAndInitialize(&tileControl)); + THROW_IF_FAILED(tileControl->put_BackgroundImage(backgroundImage)); + + ComPtr rootElement; + THROW_IF_FAILED(rootPanel->QueryInterface(rootElement.GetAddressOf())); + THROW_IF_FAILED(tileControl->put_RootElement(rootElement.Get())); + + THROW_IF_FAILED(tileControl->LoadImageBrush(background.Get())); + + ComPtr backgroundAsFrameworkElement; + THROW_IF_FAILED(tileControl.As(&backgroundAsFrameworkElement)); + + XamlHelpers::AppendXamlElementToPanel(backgroundAsFrameworkElement.Get(), rootPanel); + + // The overlay applied to the background image is determined by a resouce, so create + // the overlay if that resources exists + ComPtr resourceDictionary; + THROW_IF_FAILED(renderContext->get_OverrideStyles(&resourceDictionary)); + ComPtr backgroundOverlayBrush; + if (SUCCEEDED(XamlHelpers::TryGetResourceFromResourceDictionaries(resourceDictionary.Get(), + c_BackgroundImageOverlayBrushKey, + &backgroundOverlayBrush))) + { + ComPtr overlayRectangle = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Shapes_Rectangle)); + THROW_IF_FAILED(overlayRectangle->put_Fill(backgroundOverlayBrush.Get())); + + ComPtr overlayRectangleAsUIElement; + THROW_IF_FAILED(overlayRectangle.As(&overlayRectangleAsUIElement)); + XamlHelpers::AppendXamlElementToPanel(overlayRectangle.Get(), rootPanel); + } + } + + HRESULT RenderFallback(_In_ IAdaptiveCardElement* currentElement, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ IUIElement** result) + { + ComPtr elementRenderers; + RETURN_IF_FAILED(renderContext->get_ElementRenderers(&elementRenderers)); + + ABI::AdaptiveNamespace::FallbackType elementFallback; + RETURN_IF_FAILED(currentElement->get_FallbackType(&elementFallback)); + + HString elementType; + RETURN_IF_FAILED(currentElement->get_ElementTypeString(elementType.GetAddressOf())); + + bool fallbackHandled = false; + ComPtr fallbackControl; + switch (elementFallback) + { + case ABI::AdaptiveNamespace::FallbackType::Content: + { + // We have content, get the type of the fallback element + ComPtr fallbackElement; + RETURN_IF_FAILED(currentElement->get_FallbackContent(&fallbackElement)); + + HString fallbackElementType; + RETURN_IF_FAILED(fallbackElement->get_ElementTypeString(fallbackElementType.GetAddressOf())); + + RETURN_IF_FAILED(WarnForFallbackContentElement(renderContext, elementType.Get(), fallbackElementType.Get())); + + // Try to render the fallback element + ComPtr fallbackElementRenderer; + RETURN_IF_FAILED(elementRenderers->Get(fallbackElementType.Get(), &fallbackElementRenderer)); + HRESULT hr = E_PERFORM_FALLBACK; + + if (fallbackElementRenderer) + { + // perform this element's fallback + hr = fallbackElementRenderer->Render(fallbackElement.Get(), renderContext, renderArgs, &fallbackControl); + } + + if (hr == E_PERFORM_FALLBACK) + { + // The fallback content told us to fallback, make a recursive call to this method + RETURN_IF_FAILED(RenderFallback(fallbackElement.Get(), renderContext, renderArgs, &fallbackControl)); + } + else + { + // Check the non-fallback return value from the render call + RETURN_IF_FAILED(hr); + } + + // We handled the fallback content + fallbackHandled = true; + break; + } + case ABI::AdaptiveNamespace::FallbackType::Drop: + { + // If the fallback is drop, nothing to do but warn + RETURN_IF_FAILED(XamlHelpers::WarnForFallbackDrop(renderContext, elementType.Get())); + fallbackHandled = true; + break; + } + case ABI::AdaptiveNamespace::FallbackType::None: + default: + { + break; + } + } + + if (fallbackHandled) + { + // We did it, copy out the result if any + RETURN_IF_FAILED(fallbackControl.CopyTo(result)); + return S_OK; + } + else + { + // We didn't do it, can our ancestor? + boolean ancestorHasFallback; + RETURN_IF_FAILED(renderArgs->get_AncestorHasFallback(&ancestorHasFallback)); + + if (!ancestorHasFallback) + { + // standard unknown element handling + std::wstring errorString = L"No Renderer found for type: "; + errorString += elementType.GetRawBuffer(nullptr); + RETURN_IF_FAILED(renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::NoRendererForType, + HStringReference(errorString.c_str()).Get())); + return S_OK; + } + else + { + return E_PERFORM_FALLBACK; + } + } + } + + void GetSeparationConfigForElement(_In_ IAdaptiveCardElement* cardElement, + _In_ IAdaptiveHostConfig* hostConfig, + _Out_ UINT* spacing, + _Out_ UINT* separatorThickness, + _Out_ ABI::Windows::UI::Color* separatorColor, + _Out_ bool* needsSeparator) + { + ABI::AdaptiveNamespace::Spacing elementSpacing; + THROW_IF_FAILED(cardElement->get_Spacing(&elementSpacing)); + + UINT localSpacing; + THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig, elementSpacing, &localSpacing)); + + boolean hasSeparator; + THROW_IF_FAILED(cardElement->get_Separator(&hasSeparator)); + + ABI::Windows::UI::Color localColor = {0}; + UINT localThickness = 0; + if (hasSeparator) + { + ComPtr separatorConfig; + THROW_IF_FAILED(hostConfig->get_Separator(&separatorConfig)); + + THROW_IF_FAILED(separatorConfig->get_LineColor(&localColor)); + THROW_IF_FAILED(separatorConfig->get_LineThickness(&localThickness)); + } + + *needsSeparator = hasSeparator || (elementSpacing != ABI::AdaptiveNamespace::Spacing::None); + + *spacing = localSpacing; + *separatorThickness = localThickness; + *separatorColor = localColor; + } + + HRESULT AddRenderedControl(_In_ IUIElement* newControl, + _In_ IAdaptiveCardElement* element, + _In_ IPanel* parentPanel, + _In_ IUIElement* separator, + _In_ IColumnDefinition* columnDefinition, + std::function childCreatedCallback) + { + if (newControl != nullptr) + { + boolean isVisible; + RETURN_IF_FAILED(element->get_IsVisible(&isVisible)); + + if (!isVisible) + { + RETURN_IF_FAILED(newControl->put_Visibility(Visibility_Collapsed)); + } + + ComPtr localControl(newControl); + ComPtr newControlAsFrameworkElement; + RETURN_IF_FAILED(localControl.As(&newControlAsFrameworkElement)); + + HString id; + RETURN_IF_FAILED(element->get_Id(id.GetAddressOf())); + + if (id.IsValid()) + { + RETURN_IF_FAILED(newControlAsFrameworkElement->put_Name(id.Get())); + } + + ComPtr tagContent; + RETURN_IF_FAILED(MakeAndInitialize(&tagContent, element, parentPanel, separator, columnDefinition, isVisible)); + RETURN_IF_FAILED(newControlAsFrameworkElement->put_Tag(tagContent.Get())); + + ABI::AdaptiveNamespace::HeightType heightType{}; + RETURN_IF_FAILED(element->get_Height(&heightType)); + XamlHelpers::AppendXamlElementToPanel(newControl, parentPanel, heightType); + + childCreatedCallback(newControl); + } + return S_OK; + } + + HRESULT AddHandledTappedEvent(_In_ IUIElement* uiElement) + { + if (uiElement == nullptr) + { + return E_INVALIDARG; + } + + EventRegistrationToken clickToken; + // Add Tap handler that sets the event as handled so that it doesn't propagate to the parent containers. + return uiElement->add_Tapped(Callback([](IInspectable* /*sender*/, ITappedRoutedEventArgs* args) -> HRESULT { + return args->put_Handled(TRUE); + }).Get(), + &clickToken); + } + + void HandleSelectAction(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IAdaptiveActionElement* selectAction, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IUIElement* uiElement, + bool supportsInteractivity, + bool fullWidthTouchTarget, + _COM_Outptr_ IUIElement** outUiElement) + { + if (selectAction != nullptr && supportsInteractivity) + { + XamlHelpers::WrapInTouchTarget(adaptiveCardElement, uiElement, selectAction, renderContext, fullWidthTouchTarget, L"Adaptive.SelectAction", outUiElement); + } + else + { + if (selectAction != nullptr) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"SelectAction present, but Interactivity is not supported").Get()); + } + + ComPtr localUiElement(uiElement); + THROW_IF_FAILED(localUiElement.CopyTo(outUiElement)); + } + } + + HRESULT BuildActions(_In_ IAdaptiveCard* adaptiveCard, + _In_ IVector* children, + _In_ IPanel* bodyPanel, + bool insertSeparator, + _In_ IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs) + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); + + // Create a separator between the body and the actions + if (insertSeparator) + { + ABI::AdaptiveNamespace::Spacing spacing; + RETURN_IF_FAILED(actionsConfig->get_Spacing(&spacing)); + + UINT spacingSize; + RETURN_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), spacing, &spacingSize)); + + ABI::Windows::UI::Color color = {0}; + auto separator = XamlHelpers::CreateSeparator(renderContext, spacingSize, 0, color); + XamlHelpers::AppendXamlElementToPanel(separator.Get(), bodyPanel); + } + + ComPtr actionSetControl; + RETURN_IF_FAILED(BuildActionSetHelper(adaptiveCard, nullptr, children, renderContext, renderArgs, &actionSetControl)); + + XamlHelpers::AppendXamlElementToPanel(actionSetControl.Get(), bodyPanel); + return S_OK; + } + + HRESULT SetAutoImageSize(_In_ IFrameworkElement* imageControl, _In_ IInspectable* parentElement, _In_ IBitmapSource* imageSource, bool setVisible) + { + INT32 pixelHeight; + RETURN_IF_FAILED(imageSource->get_PixelHeight(&pixelHeight)); + INT32 pixelWidth; + RETURN_IF_FAILED(imageSource->get_PixelWidth(&pixelWidth)); + DOUBLE maxHeight; + DOUBLE maxWidth; + ComPtr localParentElement(parentElement); + ComPtr localElement(imageControl); + ComPtr parentAsColumnDefinition; + + RETURN_IF_FAILED(localElement->get_MaxHeight(&maxHeight)); + RETURN_IF_FAILED(localElement->get_MaxWidth(&maxWidth)); + + if (SUCCEEDED(localParentElement.As(&parentAsColumnDefinition))) + { + DOUBLE parentWidth; + RETURN_IF_FAILED(parentAsColumnDefinition->get_ActualWidth(&parentWidth)); + if (parentWidth >= pixelWidth) + { + // Make sure to keep the aspect ratio of the image + maxWidth = min(maxWidth, parentWidth); + double aspectRatio = (double)pixelHeight / pixelWidth; + maxHeight = maxWidth * aspectRatio; + } + } + + // Prevent an image from being stretched out if it is smaller than the + // space allocated for it (when in auto mode). + ComPtr localElementAsEllipse; + if (SUCCEEDED(localElement.As(&localElementAsEllipse))) + { + // don't need to set both width and height when image size is auto since + // we want a circle as shape. + // max value for width should be set since adaptive cards is constrained horizontally + RETURN_IF_FAILED(localElement->put_MaxWidth(min(maxWidth, pixelWidth))); + } + else + { + RETURN_IF_FAILED(localElement->put_MaxHeight(min(maxHeight, pixelHeight))); + RETURN_IF_FAILED(localElement->put_MaxWidth(min(maxWidth, pixelWidth))); + } + + if (setVisible) + { + ComPtr frameworkElementAsUIElement; + RETURN_IF_FAILED(localElement.As(&frameworkElementAsUIElement)); + RETURN_IF_FAILED(frameworkElementAsUIElement->put_Visibility(Visibility::Visibility_Visible)); + } + + return S_OK; + } + + void AddSeparatorIfNeeded(int& currentElement, + _In_ IAdaptiveCardElement* element, + _In_ IAdaptiveHostConfig* hostConfig, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IPanel* parentPanel, + _Outptr_ IUIElement** addedSeparator) + { + // First element does not need a separator added + if (currentElement++ > 0) + { + bool needsSeparator; + UINT spacing; + UINT separatorThickness; + ABI::Windows::UI::Color separatorColor; + XamlHelpers::GetSeparationConfigForElement(element, hostConfig, &spacing, &separatorThickness, &separatorColor, &needsSeparator); + if (needsSeparator) + { + auto separator = XamlHelpers::CreateSeparator(renderContext, spacing, separatorThickness, separatorColor); + XamlHelpers::AppendXamlElementToPanel(separator.Get(), parentPanel); + THROW_IF_FAILED(separator.CopyTo(addedSeparator)); + } + } + } + + HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_opt_ IAdaptiveActionSet* adaptiveActionSet, + _In_ IVector* children, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _Outptr_ IUIElement** actionSetControl) + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); + + ABI::AdaptiveNamespace::ActionAlignment actionAlignment; + RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); + + ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; + RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); + + // Declare the panel that will host the buttons + ComPtr actionsPanel; + ComPtr> columnDefinitions; + + if (actionAlignment == ABI::AdaptiveNamespace::ActionAlignment::Stretch && + actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + // If stretch alignment and orientation is horizontal, we use a grid with equal column widths to achieve + // stretch behavior. For vertical orientation, we'll still just use a stack panel since the concept of + // stretching buttons height isn't really valid, especially when the height of cards are typically dynamic. + ComPtr actionsGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + RETURN_IF_FAILED(actionsGrid->get_ColumnDefinitions(&columnDefinitions)); + RETURN_IF_FAILED(actionsGrid.As(&actionsPanel)); + } + else + { + // Create a stack panel for the action buttons + ComPtr actionStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + + auto uiOrientation = (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) ? + Orientation::Orientation_Horizontal : + Orientation::Orientation_Vertical; + + RETURN_IF_FAILED(actionStackPanel->put_Orientation(uiOrientation)); + + ComPtr actionsFrameworkElement; + RETURN_IF_FAILED(actionStackPanel.As(&actionsFrameworkElement)); + + switch (actionAlignment) + { + case ABI::AdaptiveNamespace::ActionAlignment::Center: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Left: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Right: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Stretch: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); + break; + } + + // Add the action buttons to the stack panel + RETURN_IF_FAILED(actionStackPanel.As(&actionsPanel)); + } + + Thickness buttonMargin; + RETURN_IF_FAILED(ActionHelpers::GetButtonMargin(actionsConfig.Get(), buttonMargin)); + if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + // Negate the spacing on the sides so the left and right buttons are flush on the side. + // We do NOT remove the margin from the individual button itself, since that would cause + // the equal columns stretch behavior to not have equal columns (since the first and last + // button would be narrower without the same margins as its peers). + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({buttonMargin.Left * -1, 0, buttonMargin.Right * -1, 0})); + } + else + { + // Negate the spacing on the top and bottom so the first and last buttons don't have extra padding + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({0, buttonMargin.Top * -1, 0, buttonMargin.Bottom * -1})); + } + + UINT32 maxActions; + RETURN_IF_FAILED(actionsConfig->get_MaxActions(&maxActions)); + + bool allActionsHaveIcons{true}; + XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { + HSTRING iconUrl; + RETURN_IF_FAILED(child->get_IconUrl(&iconUrl)); + + bool iconUrlIsEmpty = WindowsIsStringEmpty(iconUrl); + if (iconUrlIsEmpty) + { + allActionsHaveIcons = false; + } + return S_OK; + }); + + UINT currentAction = 0; + + RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(allActionsHaveIcons)); + + std::shared_ptr>> allShowCards = std::make_shared>>(); + ComPtr showCardsStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + ComPtr gridStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); + XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { + if (currentAction < maxActions) + { + // Render each action using the registered renderer + ComPtr action(child); + ComPtr actionRegistration; + RETURN_IF_FAILED(renderContext->get_ActionRenderers(&actionRegistration)); + + ComPtr renderer; + while (!renderer) + { + HString actionTypeString; + RETURN_IF_FAILED(action->get_ActionTypeString(actionTypeString.GetAddressOf())); + RETURN_IF_FAILED(actionRegistration->Get(actionTypeString.Get(), &renderer)); + if (!renderer) + { + ABI::AdaptiveNamespace::FallbackType actionFallbackType; + action->get_FallbackType(&actionFallbackType); + switch (actionFallbackType) + { + case ABI::AdaptiveNamespace::FallbackType::Drop: + { + RETURN_IF_FAILED(XamlHelpers::WarnForFallbackDrop(renderContext, actionTypeString.Get())); + return S_OK; + } + + case ABI::AdaptiveNamespace::FallbackType::Content: + { + ComPtr actionFallback; + RETURN_IF_FAILED(action->get_FallbackContent(&actionFallback)); + + HString fallbackTypeString; + RETURN_IF_FAILED(actionFallback->get_ActionTypeString(fallbackTypeString.GetAddressOf())); + RETURN_IF_FAILED(XamlHelpers::WarnForFallbackContentElement(renderContext, + actionTypeString.Get(), + fallbackTypeString.Get())); + + action = actionFallback; + break; + } + + case ABI::AdaptiveNamespace::FallbackType::None: + default: + return E_FAIL; + } + } + } + + ComPtr actionControl; + RETURN_IF_FAILED(renderer->Render(action.Get(), renderContext, renderArgs, &actionControl)); + + XamlHelpers::AppendXamlElementToPanel(actionControl.Get(), actionsPanel.Get()); + + ABI::AdaptiveNamespace::ActionType actionType; + RETURN_IF_FAILED(action->get_ActionType(&actionType)); + + // Build inline show cards if needed + if (actionType == ABI::AdaptiveNamespace::ActionType_ShowCard) + { + ComPtr uiShowCard; + + ComPtr showCardActionConfig; + RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); + + ABI::AdaptiveNamespace::ActionMode showCardActionMode; + RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); + + if (showCardActionMode == ABI::AdaptiveNamespace::ActionMode::Inline) + { + ComPtr showCardAction; + RETURN_IF_FAILED(action.As(&showCardAction)); + + ComPtr showCard; + RETURN_IF_FAILED(showCardAction->get_Card(&showCard)); + + RETURN_IF_FAILED(AdaptiveShowCardActionRenderer::BuildShowCard( + showCard.Get(), renderContext, renderArgs, (adaptiveActionSet == nullptr), uiShowCard.GetAddressOf())); + + ComPtr showCardsPanel; + RETURN_IF_FAILED(showCardsStackPanel.As(&showCardsPanel)); + XamlHelpers::AppendXamlElementToPanel(uiShowCard.Get(), showCardsPanel.Get()); + + if (adaptiveActionSet) + { + RETURN_IF_FAILED( + renderContext->AddInlineShowCard(adaptiveActionSet, showCardAction.Get(), uiShowCard.Get())); + } + else + { + ComPtr contextImpl = + PeekInnards(renderContext); + + RETURN_IF_FAILED( + contextImpl->AddInlineShowCard(adaptiveCard, showCardAction.Get(), uiShowCard.Get())); + } + } + } + + if (columnDefinitions != nullptr) + { + // If using the equal width columns, we'll add a column and assign the column + ComPtr columnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + RETURN_IF_FAILED(columnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Star})); + RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); + + ComPtr actionFrameworkElement; + THROW_IF_FAILED(actionControl.As(&actionFrameworkElement)); + THROW_IF_FAILED(gridStatics->SetColumn(actionFrameworkElement.Get(), currentAction)); + } + } + else + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::MaxActionsExceeded, + HStringReference(L"Some actions were not rendered due to exceeding the maximum number of actions allowed") + .Get()); + } + currentAction++; + return S_OK; + }); + + // Reset icon placement value + RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(false)); + + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Actions", + actionsPanelAsFrameworkElement.Get())); + + ComPtr actionSet = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + ComPtr actionSetAsPanel; + actionSet.As(&actionSetAsPanel); + + // Add buttons and show cards to panel + XamlHelpers::AppendXamlElementToPanel(actionsPanel.Get(), actionSetAsPanel.Get()); + XamlHelpers::AppendXamlElementToPanel(showCardsStackPanel.Get(), actionSetAsPanel.Get()); + + return actionSetAsPanel.CopyTo(actionSetControl); + } +} diff --git a/source/uwp/Renderer/lib/XamlHelpers.h b/source/uwp/Renderer/lib/XamlHelpers.h index 6da2c52be3..0dfaf63f8a 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.h +++ b/source/uwp/Renderer/lib/XamlHelpers.h @@ -28,8 +28,83 @@ namespace AdaptiveNamespace::XamlHelpers return solidColorBrushAsBrush; } + void WireButtonClickToAction(_In_ ABI::Windows::UI::Xaml::Controls::IButton* button, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); + + HRESULT SetStyleFromResourceDictionary(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + const std::wstring& resourceName, + _In_ ABI::Windows::UI::Xaml::IFrameworkElement* frameworkElement) noexcept; + + void WrapInTouchTarget(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, + _In_ ABI::Windows::UI::Xaml::IUIElement* elementToWrap, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + bool fullWidth, + const std::wstring& style, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** finalElement); + + Microsoft::WRL::ComPtr CreateSeparator(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + UINT spacing, + UINT separatorThickness, + ABI::Windows::UI::Color separatorColor, + bool isHorizontal = true); + + template + HRESULT TryGetResourceFromResourceDictionaries(_In_ ABI::Windows::UI::Xaml::IResourceDictionary* resourceDictionary, + const std::wstring& resourceName, + _COM_Outptr_result_maybenull_ T** style) noexcept + { + if (resourceDictionary == nullptr) + { + return E_INVALIDARG; + } + + *style = nullptr; + try + { + // Get a resource key for the requested style that we can use for ResourceDictionary Lookups + ComPtr propertyValueStatics; + THROW_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), + &propertyValueStatics)); + ComPtr resourceKey; + THROW_IF_FAILED(propertyValueStatics->CreateString(HStringReference(resourceName.c_str()).Get(), + resourceKey.GetAddressOf())); + + // Search for the named resource + ComPtr strongDictionary = resourceDictionary; + ComPtr dictionaryValue; + ComPtr> resourceDictionaryMap; + + boolean hasKey{}; + if (SUCCEEDED(strongDictionary.As(&resourceDictionaryMap)) && + SUCCEEDED(resourceDictionaryMap->HasKey(resourceKey.Get(), &hasKey)) && hasKey && + SUCCEEDED(resourceDictionaryMap->Lookup(resourceKey.Get(), dictionaryValue.GetAddressOf()))) + { + ComPtr resourceToReturn; + if (SUCCEEDED(dictionaryValue.As(&resourceToReturn))) + { + THROW_IF_FAILED(resourceToReturn.CopyTo(style)); + return S_OK; + } + } + } + catch (...) + { + } + return E_FAIL; + } + + HRESULT SetSeparatorVisibility(_In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel); + + HRESULT HandleColumnWidth(_In_ ABI::AdaptiveNamespace::IAdaptiveColumn* column, + boolean isVisible, + _In_ ABI::Windows::UI::Xaml::Controls::IColumnDefinition* columnDefinition); + template - HRESULT IterateOverVectorWithFailure(_In_ ABI::Windows::Foundation::Collections::IVector* vector, const boolean stopOnFailure, C iterationCallback) + HRESULT IterateOverVectorWithFailure(_In_ ABI::Windows::Foundation::Collections::IVector* vector, + const boolean stopOnFailure, + C iterationCallback) { Microsoft::WRL::ComPtr> localVector(vector); ComPtr> vectorIterable; @@ -64,7 +139,9 @@ namespace AdaptiveNamespace::XamlHelpers } template - HRESULT IterateOverVectorWithFailure(_In_ ABI::Windows::Foundation::Collections::IVector* vector, const boolean stopOnFailure, C iterationCallback) + HRESULT IterateOverVectorWithFailure(_In_ ABI::Windows::Foundation::Collections::IVector* vector, + const boolean stopOnFailure, + C iterationCallback) { return IterateOverVectorWithFailure(vector, stopOnFailure, iterationCallback); } @@ -218,4 +295,123 @@ namespace AdaptiveNamespace::XamlHelpers THROW_IF_FAILED(localGrid.As(&localPanel)); XamlHelpers::AppendXamlElementToPanel(item, localPanel.Get()); } + + HRESULT HandleStylingAndPadding(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerBase* adaptiveContainer, + _In_ ABI::Windows::UI::Xaml::Controls::IBorder* containerBorder, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _Out_ ABI::AdaptiveNamespace::ContainerStyle* containerStyle); + + void HandleSelectAction(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* selectAction, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::Windows::UI::Xaml::IUIElement* uiElement, + bool supportsInteractivity, + bool fullWidthTouchTarget, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** outUiElement); + + bool SupportsInteractivity(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig); + + template + void SetVerticalContentAlignmentToChildren(_In_ T* container, _In_ ABI::AdaptiveNamespace::VerticalContentAlignment verticalContentAlignment) + { + ComPtr localContainer(container); + ComPtr containerAsPanel; + THROW_IF_FAILED(localContainer.As(&containerAsPanel)); + + ComPtr panel = PeekInnards(containerAsPanel); + panel->SetVerticalContentAlignment(verticalContentAlignment); + } + + HRESULT AddHandledTappedEvent(_In_ ABI::Windows::UI::Xaml::IUIElement* uiElement); + + void ApplyBackgroundToRoot(_In_ ABI::Windows::UI::Xaml::Controls::IPanel* rootPanel, + _In_ ABI::AdaptiveNamespace::IAdaptiveBackgroundImage* backgroundImage, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); + + HRESULT AddRenderedControl(_In_ ABI::Windows::UI::Xaml::IUIElement* newControl, + _In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* element, + _In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel, + _In_ ABI::Windows::UI::Xaml::IUIElement* separator, + _In_ ABI::Windows::UI::Xaml::Controls::IColumnDefinition* columnDefinition, + std::function childCreatedCallback); + + HRESULT RenderFallback(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* currentElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result); + + void GetSeparationConfigForElement(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* element, + _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, + _Out_ UINT* spacing, + _Out_ UINT* separatorThickness, + _Out_ ABI::Windows::UI::Color* separatorColor, + _Out_ bool* needsSeparator); + + void AddInputValueToContext(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, + _In_ ABI::Windows::UI::Xaml::IUIElement* inputUiElement); + + inline HRESULT WarnFallbackString(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, const std::string& warning) + { + HString warningMsg; + RETURN_IF_FAILED(UTF8ToHString(warning, warningMsg.GetAddressOf())); + + RETURN_IF_FAILED( + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::PerformingFallback, warningMsg.Get())); + return S_OK; + } + + inline HRESULT WarnForFallbackContentElement(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ HSTRING parentElementType, + _In_ HSTRING fallbackElementType) + try + { + std::string warning = "Performing fallback for element of type \""; + warning.append(HStringToUTF8(parentElementType)); + warning.append("\" (fallback element type \""); + warning.append(HStringToUTF8(fallbackElementType)); + warning.append("\")"); + + return WarnFallbackString(renderContext, warning); + } + CATCH_RETURN; + + inline HRESULT WarnForFallbackDrop(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, _In_ HSTRING elementType) + try + { + std::string warning = "Dropping element of type \""; + warning.append(HStringToUTF8(elementType)); + warning.append("\" for fallback"); + + return WarnFallbackString(renderContext, warning); + } + CATCH_RETURN; + + HRESULT BuildActions(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_ ABI::Windows::Foundation::Collections::IVector* children, + _In_ ABI::Windows::UI::Xaml::Controls::IPanel* bodyPanel, + bool insertSeparator, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); + + void AddSeparatorIfNeeded(int& currentElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* element, + _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::Windows::UI::Xaml::Controls::IPanel* parentPanel, + _Outptr_ ABI::Windows::UI::Xaml::IUIElement** addedSeparator); + + HRESULT SetAutoImageSize(_In_ ABI::Windows::UI::Xaml::IFrameworkElement* imageControl, + _In_ IInspectable* parentElement, + _In_ ABI::Windows::UI::Xaml::Media::Imaging::IBitmapSource* imageSource, + bool setVisible); + + HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_opt_ ABI::AdaptiveNamespace::IAdaptiveActionSet* adaptiveActionSet, + _In_ ABI::Windows::Foundation::Collections::IVector* children, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionSetControl); } diff --git a/source/uwp/Renderer/lib/pch.h b/source/uwp/Renderer/lib/pch.h index c0e14dfa44..020c8d6835 100644 --- a/source/uwp/Renderer/lib/pch.h +++ b/source/uwp/Renderer/lib/pch.h @@ -23,6 +23,7 @@ #include #include #include +#include // The #define of this in winbase.h windows.ui.xaml.media.animation.h's IStoryboard defintion // so we need to remove it @@ -30,10 +31,18 @@ #undef GetCurrentTime #endif -#include "ErrorHandling.h" -#include "Util.h" +// Shared Model headers +#include "Enums.h" +#include "HostConfig.h" +// Commonly-used AdaptiveCardRenderer headers #include "AdaptiveCards.Rendering.Uwp.h" +#include "AdaptiveCardElement.h" +#include "ErrorHandling.h" +#include "Util.h" +#include "Vector.h" +#include "XamlBuilder.h" +#include "XamlHelpers.h" #ifndef MAKE_HRESULT #define MAKE_HRESULT(sev, fac, code) \ @@ -43,3 +52,8 @@ #define FACILITY_ADAPTIVECARDS 0xADA #define ERRORBASE_ADAPTIVECARDS 0x1000 #define E_PERFORM_FALLBACK MAKE_HRESULT(1, FACILITY_ADAPTIVECARDS, ERRORBASE_ADAPTIVECARDS) + +#include +#include +#include +#include From a3a2b107b1a8825986345eb863ac78e12cd557aa Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 12:24:02 -0700 Subject: [PATCH 02/16] Get rid of _Use_decl_annotations_ use --- source/uwp/Renderer/lib/AdaptiveActionSet.cpp | 6 +- source/uwp/Renderer/lib/AdaptiveActionSet.h | 2 +- .../lib/AdaptiveContainerStylesDefinition.cpp | 29 +++---- .../lib/AdaptiveContainerStylesDefinition.h | 8 +- source/uwp/Renderer/lib/TileControl.cpp | 76 +++++++++---------- source/uwp/Renderer/lib/TileControl.h | 4 +- 6 files changed, 61 insertions(+), 64 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp index 4af193c90c..fb2a48c753 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp @@ -21,7 +21,7 @@ namespace AdaptiveNamespace } CATCH_RETURN; - _Use_decl_annotations_ HRESULT AdaptiveActionSet::RuntimeClassInitialize(const std::shared_ptr& sharedActionSet) + HRESULT AdaptiveActionSet::RuntimeClassInitialize(const std::shared_ptr& sharedActionSet) try { if (sharedActionSet == nullptr) @@ -35,12 +35,12 @@ namespace AdaptiveNamespace } CATCH_RETURN; - _Use_decl_annotations_ HRESULT AdaptiveActionSet::get_Actions(IVector** items) + HRESULT AdaptiveActionSet::get_Actions(_COM_Outptr_ IVector** items) { return m_actions.CopyTo(items); } - _Use_decl_annotations_ HRESULT AdaptiveActionSet::get_ElementType(ElementType* elementType) + HRESULT AdaptiveActionSet::get_ElementType(_Out_ ElementType* elementType) { *elementType = ElementType::ActionSet; return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.h b/source/uwp/Renderer/lib/AdaptiveActionSet.h index 79461d0a6e..c99396cdc0 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.h +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.h @@ -18,7 +18,7 @@ namespace AdaptiveNamespace public: AdaptiveActionSet(); HRESULT RuntimeClassInitialize() noexcept; - HRESULT RuntimeClassInitialize(_In_ const std::shared_ptr& sharedActionSet); + HRESULT RuntimeClassInitialize(const std::shared_ptr& sharedActionSet); // IAdaptiveActionSet IFACEMETHODIMP get_Actions( diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp index c4327d0372..b89b30f5fa 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp @@ -7,6 +7,8 @@ using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; +using namespace ABI::AdaptiveNamespace; + namespace AdaptiveNamespace { HRESULT AdaptiveContainerStylesDefinition::RuntimeClassInitialize() noexcept try @@ -21,74 +23,75 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(MakeAndInitialize(m_default.GetAddressOf(), stylesDefinition.defaultPalette)); RETURN_IF_FAILED(MakeAndInitialize(m_emphasis.GetAddressOf(), stylesDefinition.emphasisPalette)); RETURN_IF_FAILED(MakeAndInitialize(m_good.GetAddressOf(), stylesDefinition.goodPalette)); - RETURN_IF_FAILED(MakeAndInitialize(m_attention.GetAddressOf(), stylesDefinition.attentionPalette)); + RETURN_IF_FAILED(MakeAndInitialize(m_attention.GetAddressOf(), + stylesDefinition.attentionPalette)); RETURN_IF_FAILED(MakeAndInitialize(m_warning.GetAddressOf(), stylesDefinition.warningPalette)); RETURN_IF_FAILED(MakeAndInitialize(m_accent.GetAddressOf(), stylesDefinition.accentPalette)); return S_OK; } - HRESULT AdaptiveContainerStylesDefinition::get_Default(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Default(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_default.CopyTo(value); } - HRESULT AdaptiveContainerStylesDefinition::put_Default(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Default(_In_ IAdaptiveContainerStyleDefinition* value) { m_default = value; return S_OK; } - HRESULT AdaptiveContainerStylesDefinition::get_Emphasis(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Emphasis(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_emphasis.CopyTo(value); } - HRESULT AdaptiveContainerStylesDefinition::put_Emphasis(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Emphasis(_In_ IAdaptiveContainerStyleDefinition* value) { m_emphasis = value; return S_OK; } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::get_Good(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Good(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_good.CopyTo(value); } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::put_Good(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Good(_In_ IAdaptiveContainerStyleDefinition* value) { m_good = value; return S_OK; } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::get_Attention(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Attention(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_attention.CopyTo(value); } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::put_Attention(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Attention(_In_ IAdaptiveContainerStyleDefinition* value) { m_emphasis = value; return S_OK; } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::get_Warning(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Warning(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_warning.CopyTo(value); } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::put_Warning(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Warning(_In_ IAdaptiveContainerStyleDefinition* value) { m_warning = value; return S_OK; } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::get_Accent(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value) + HRESULT AdaptiveContainerStylesDefinition::get_Accent(_COM_Outptr_ IAdaptiveContainerStyleDefinition** value) { return m_accent.CopyTo(value); } - _Use_decl_annotations_ HRESULT AdaptiveContainerStylesDefinition::put_Accent(ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value) + HRESULT AdaptiveContainerStylesDefinition::put_Accent(_In_ IAdaptiveContainerStyleDefinition* value) { m_accent = value; return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h index 6ab85011ee..57847e56a0 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h +++ b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.h @@ -19,16 +19,16 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_Emphasis(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); IFACEMETHODIMP put_Emphasis(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value); - IFACEMETHODIMP get_Good(_Out_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); + IFACEMETHODIMP get_Good(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); IFACEMETHODIMP put_Good(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value); - IFACEMETHODIMP get_Attention(_Out_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); + IFACEMETHODIMP get_Attention(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); IFACEMETHODIMP put_Attention(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value); - IFACEMETHODIMP get_Warning(_Out_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); + IFACEMETHODIMP get_Warning(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); IFACEMETHODIMP put_Warning(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value); - IFACEMETHODIMP get_Accent(_Out_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); + IFACEMETHODIMP get_Accent(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition** value); IFACEMETHODIMP put_Accent(_In_ ABI::AdaptiveNamespace::IAdaptiveContainerStyleDefinition* value); private: diff --git a/source/uwp/Renderer/lib/TileControl.cpp b/source/uwp/Renderer/lib/TileControl.cpp index 624438d859..640f3153f6 100644 --- a/source/uwp/Renderer/lib/TileControl.cpp +++ b/source/uwp/Renderer/lib/TileControl.cpp @@ -48,30 +48,27 @@ namespace AdaptiveNamespace } CATCH_RETURN; - _Use_decl_annotations_ HRESULT TileControl::put_BackgroundImage(_In_ IAdaptiveBackgroundImage* value) + HRESULT TileControl::put_BackgroundImage(_In_ IAdaptiveBackgroundImage* value) { m_adaptiveBackgroundImage = value; return S_OK; } - _Use_decl_annotations_ HRESULT TileControl::put_RootElement(_In_ IFrameworkElement* value) + HRESULT TileControl::put_RootElement(_In_ IFrameworkElement* value) { m_rootElement = value; return S_OK; } - _Use_decl_annotations_ HRESULT TileControl::get_ResolvedImage(_In_ IUIElement** value) - { - return m_resolvedImage.CopyTo(value); - } + HRESULT TileControl::get_ResolvedImage(_COM_Outptr_ IUIElement** value) { return m_resolvedImage.CopyTo(value); } - _Use_decl_annotations_ HRESULT TileControl::put_ImageSize(_In_ Size value) + HRESULT TileControl::put_ImageSize(_In_ Size value) { m_imageSize = value; return S_OK; } - _Use_decl_annotations_ HRESULT TileControl::LoadImageBrush(_In_ IUIElement* uielement) + HRESULT TileControl::LoadImageBrush(_In_ IUIElement* uielement) { m_resolvedImage = uielement; @@ -86,34 +83,33 @@ namespace AdaptiveNamespace EventRegistrationToken eventToken; ComPtr bitmapImage; THROW_IF_FAILED(imageSource.As(&bitmapImage)); - THROW_IF_FAILED(bitmapImage->add_ImageOpened(Callback( - [&](IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { - ComPtr uiElement; - THROW_IF_FAILED(get_ResolvedImage(&uiElement)); - - // Extract BitmapSource from Image - ComPtr image; - THROW_IF_FAILED(uiElement.As(&image)); - ComPtr imageSource; - THROW_IF_FAILED(image->get_Source(&imageSource)); - ComPtr bitmapSource; - THROW_IF_FAILED(imageSource.As(&bitmapSource)); - - // Extract Size from Image - int height{}, width{}; - THROW_IF_FAILED(bitmapSource->get_PixelHeight(&height)); - THROW_IF_FAILED(bitmapSource->get_PixelWidth(&width)); - - // Save size to member variable - Size imageSize{}; - imageSize.Height = static_cast(height); - imageSize.Width = static_cast(width); - THROW_IF_FAILED(put_ImageSize(imageSize)); - - RefreshContainerTile(); - return S_OK; - }) - .Get(), + THROW_IF_FAILED(bitmapImage->add_ImageOpened(Callback([&](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + ComPtr uiElement; + THROW_IF_FAILED(get_ResolvedImage(&uiElement)); + + // Extract BitmapSource from Image + ComPtr image; + THROW_IF_FAILED(uiElement.As(&image)); + ComPtr imageSource; + THROW_IF_FAILED(image->get_Source(&imageSource)); + ComPtr bitmapSource; + THROW_IF_FAILED(imageSource.As(&bitmapSource)); + + // Extract Size from Image + int height{}, width{}; + THROW_IF_FAILED(bitmapSource->get_PixelHeight(&height)); + THROW_IF_FAILED(bitmapSource->get_PixelWidth(&width)); + + // Save size to member variable + Size imageSize{}; + imageSize.Height = static_cast(height); + imageSize.Width = static_cast(width); + THROW_IF_FAILED(put_ImageSize(imageSize)); + + RefreshContainerTile(); + return S_OK; + }).Get(), &eventToken)); THROW_IF_FAILED(image->get_Source(&imageSource)); @@ -286,8 +282,8 @@ namespace AdaptiveNamespace // Get Rectangle auto rectangle = m_xamlChildren[index]; - // For cover, the bitmapimage must be scaled to fill the container and then clipped to only the necessary section - // Set rectangle.Fill + // For cover, the bitmapimage must be scaled to fill the container and then clipped to only the + // necessary section Set rectangle.Fill ComPtr rectangleAsShape; THROW_IF_FAILED(rectangle.As(&rectangleAsShape)); THROW_IF_FAILED(rectangleAsShape->put_Fill(brushXamlAsBrush.Get())); @@ -343,9 +339,7 @@ namespace AdaptiveNamespace } } - HRESULT TileControl::ExtractBackgroundImageData(BackgroundImageFillMode* fillMode, - HAlignment* hAlignment, - VAlignment* vAlignment) + HRESULT TileControl::ExtractBackgroundImageData(BackgroundImageFillMode* fillMode, HAlignment* hAlignment, VAlignment* vAlignment) { RETURN_IF_FAILED(m_adaptiveBackgroundImage->get_FillMode(fillMode)); RETURN_IF_FAILED(m_adaptiveBackgroundImage->get_HorizontalAlignment(hAlignment)); diff --git a/source/uwp/Renderer/lib/TileControl.h b/source/uwp/Renderer/lib/TileControl.h index 2046909275..7302abdc00 100644 --- a/source/uwp/Renderer/lib/TileControl.h +++ b/source/uwp/Renderer/lib/TileControl.h @@ -30,8 +30,8 @@ namespace AdaptiveNamespace virtual HRESULT STDMETHODCALLTYPE put_BackgroundImage(_In_ IAdaptiveBackgroundImage* value); virtual HRESULT STDMETHODCALLTYPE put_RootElement(_In_ IFrameworkElement* value); - virtual HRESULT STDMETHODCALLTYPE get_ResolvedImage(_Outptr_ IUIElement** value); - virtual HRESULT STDMETHODCALLTYPE put_ImageSize(ABI::Windows::Foundation::Size value); + virtual HRESULT STDMETHODCALLTYPE get_ResolvedImage(_COM_Outptr_ IUIElement** value); + virtual HRESULT STDMETHODCALLTYPE put_ImageSize(_In_ ABI::Windows::Foundation::Size value); virtual HRESULT STDMETHODCALLTYPE LoadImageBrush(_In_ IUIElement* image); From b5cba020e96f74a79e073cb744bf33b19e87d562 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 13:05:23 -0700 Subject: [PATCH 03/16] TryInsertResourceToResourceDictionaries -> AdaptiveCardRenderer::TryInsertResourceToSentimentResourceDictionary --- .../lib/AdaptiveCardRendererComponent.cpp | 36 +++++++------------ .../lib/AdaptiveCardRendererComponent.h | 15 ++++---- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp index ad18804d08..b5cea88ad6 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp @@ -53,7 +53,7 @@ using namespace ABI::Windows::UI::Xaml::Media::Imaging; namespace AdaptiveNamespace { - HRESULT AdaptiveCardRenderer::RuntimeClassInitialize() + HRESULT AdaptiveCardRenderer::RuntimeClassInitialize() noexcept try { RETURN_IF_FAILED(MakeAndInitialize(&m_xamlBuilder)); RETURN_IF_FAILED(MakeAndInitialize(&m_elementRendererRegistration)); @@ -66,6 +66,7 @@ namespace AdaptiveNamespace UpdateActionSentimentResourceDictionary(); return MakeAndInitialize(&m_resourceResolvers); } + CATCH_RETURN; HRESULT AdaptiveCardRenderer::put_OverrideStyles(_In_ ABI::Windows::UI::Xaml::IResourceDictionary* overrideDictionary) { @@ -296,15 +297,9 @@ namespace AdaptiveNamespace m_actionSentimentResourceDictionary = actionSentimentResourceDictionary; } - static HRESULT TryInsertResourceToResourceDictionaries(_In_ IResourceDictionary* resourceDictionary, - const std::wstring& resourceName, - _In_ IInspectable* value) + HRESULT AdaptiveCardRenderer::TryInsertResourceToSentimentResourceDictionary(const std::wstring& resourceName, + _In_ IInspectable* value) { - if (!resourceDictionary) - { - return E_INVALIDARG; - } - ComPtr propertyValueStatics; RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics)); @@ -312,9 +307,8 @@ namespace AdaptiveNamespace ComPtr resourceKey; RETURN_IF_FAILED(propertyValueStatics->CreateString(HStringReference(resourceName.c_str()).Get(), resourceKey.GetAddressOf())); - ComPtr strongDictionary = resourceDictionary; ComPtr> resourceDictionaryMap; - RETURN_IF_FAILED(strongDictionary.As(&resourceDictionaryMap)); + RETURN_IF_FAILED(m_actionSentimentResourceDictionary.As(&resourceDictionaryMap)); boolean replaced{}; RETURN_IF_FAILED(resourceDictionaryMap->Insert(resourceKey.Get(), value, &replaced)); @@ -343,24 +337,20 @@ namespace AdaptiveNamespace ABI::Windows::UI::Color lighterAttentionColor = GenerateLighterColor(attentionColor); ComPtr accentColorBrush = XamlHelpers::GetSolidColorBrush(accentColor); - THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Positive.Button.Static.Background", - accentColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToSentimentResourceDictionary(L"Adaptive.Action.Positive.Button.Static.Background", + accentColorBrush.Get())); ComPtr lightAccentColorBrush = XamlHelpers::GetSolidColorBrush(lighterAccentColor); - THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Positive.Button.MouseOver.Background", - lightAccentColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToSentimentResourceDictionary(L"Adaptive.Action.Positive.Button.MouseOver.Background", + lightAccentColorBrush.Get())); ComPtr attentionColorBrush = XamlHelpers::GetSolidColorBrush(attentionColor); - THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Destructive.Button.Foreground", - attentionColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToSentimentResourceDictionary(L"Adaptive.Action.Destructive.Button.Foreground", + attentionColorBrush.Get())); ComPtr lightAttentionColorBrush = XamlHelpers::GetSolidColorBrush(lighterAttentionColor); - THROW_IF_FAILED(TryInsertResourceToResourceDictionaries(m_actionSentimentResourceDictionary.Get(), - L"Adaptive.Action.Destructive.Button.MouseOver.Foreground", - lightAttentionColorBrush.Get())); + THROW_IF_FAILED(TryInsertResourceToSentimentResourceDictionary(L"Adaptive.Action.Destructive.Button.MouseOver.Foreground", + lightAttentionColorBrush.Get())); } HRESULT AdaptiveCardRenderer::SetMergedDictionary() diff --git a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.h b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.h index 4f82fcd2f5..1cea156e0a 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.h +++ b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.h @@ -18,7 +18,7 @@ namespace AdaptiveNamespace AdaptiveRuntime(AdaptiveCardRenderer); public: - HRESULT RuntimeClassInitialize(); + HRESULT RuntimeClassInitialize() noexcept; // IAdaptiveCardRenderer IFACEMETHODIMP put_OverrideStyles(_In_ ABI::Windows::UI::Xaml::IResourceDictionary* overrideDictionary); @@ -62,6 +62,13 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_ResourceResolvers(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardResourceResolvers** value); private: + HRESULT CreateAdaptiveCardFromJsonString(_In_ HSTRING adaptiveJson, + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardParseResult** adaptiveCard); + void InitializeDefaultResourceDictionary(); + void UpdateActionSentimentResourceDictionary(); + HRESULT TryInsertResourceToSentimentResourceDictionary(const std::wstring& resourceName, _In_ IInspectable* value); + HRESULT SetMergedDictionary(); + Microsoft::WRL::ComPtr m_overrideDictionary; Microsoft::WRL::ComPtr m_defaultResourceDictionary; Microsoft::WRL::ComPtr m_mergedResourceDictionary; @@ -76,12 +83,6 @@ namespace AdaptiveNamespace bool m_explicitDimensions = false; UINT32 m_desiredWidth = 0; UINT32 m_desiredHeight = 0; - - HRESULT CreateAdaptiveCardFromJsonString(_In_ HSTRING adaptiveJson, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardParseResult** adaptiveCard); - void InitializeDefaultResourceDictionary(); - void UpdateActionSentimentResourceDictionary(); - HRESULT SetMergedDictionary(); }; ActivatableClass(AdaptiveCardRenderer); From e418de2104a605fb377920ab97655a481d5df9e3 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 13:18:17 -0700 Subject: [PATCH 04/16] Make GetChoiceSetValueVector and IsChoiceSelected member methods --- source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp | 6 +++--- source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp index b8a49c820d..3e4d31be32 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp @@ -74,7 +74,7 @@ namespace AdaptiveNamespace } CATCH_RETURN; - static std::vector GetChoiceSetValueVector(_In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput) + std::vector AdaptiveChoiceSetInputRenderer::GetChoiceSetValueVector(_In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput) { HString value; THROW_IF_FAILED(adaptiveChoiceSetInput->get_Value(value.GetAddressOf())); @@ -87,13 +87,13 @@ namespace AdaptiveNamespace { std::string subString; std::getline(streamValue, subString, ','); - values.push_back(subString); + values.push_back(std::move(subString)); } return values; } - static bool IsChoiceSelected(std::vector selectedValues, _In_ IAdaptiveChoiceInput* choice) + bool AdaptiveChoiceSetInputRenderer::IsChoiceSelected(std::vector selectedValues, _In_ IAdaptiveChoiceInput* choice) { HString value; THROW_IF_FAILED(choice->get_Value(value.GetAddressOf())); diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h index 8ab53c6e8e..445f072666 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h @@ -28,6 +28,10 @@ namespace AdaptiveNamespace _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept override; private: + static std::vector GetChoiceSetValueVector(_In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput); + static bool IsChoiceSelected(std::vector selectedValues, + _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceInput* choice); + HRESULT _BuildExpandedChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, boolean isMultiSelect, From 403ed591ce14164d0f898bd284e5b0061e05d836 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 13:24:41 -0700 Subject: [PATCH 05/16] Add banner comment explaining XamlBuilder in AdaptiveImageRenderer --- source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index 2c2ff63edf..a26e0ba57b 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -68,6 +68,14 @@ namespace AdaptiveNamespace } CATCH_RETURN; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // IMPORTANT! Methods below here are actually XamlBuilder methods. They're defined here because they're only used + // by the AdaptiveImageRenderer. They exist on XamlBuilder because it's the only place we have that can track + // loading and lifetime for images. + // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HRESULT XamlBuilder::BuildImage(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, From 3a776c37920f891836268eecd894ea9610fbcec4 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 13:27:31 -0700 Subject: [PATCH 06/16] Some cleanup for AdaptiveActionSetRenderer --- source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp index da82d6ee49..3ee5e8f81d 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp @@ -4,11 +4,8 @@ #include "AdaptiveActionSet.h" #include "AdaptiveActionSetRenderer.h" -#include "AdaptiveShowCardActionRenderer.h" #include "AdaptiveElementParserRegistration.h" -#include "AdaptiveImage.h" #include "AdaptiveRenderArgs.h" -#include "ActionHelpers.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -21,11 +18,10 @@ using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { - HRESULT AdaptiveActionSetRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveActionSetRenderer::RuntimeClassInitialize() noexcept { return S_OK; } - CATCH_RETURN; HRESULT AdaptiveActionSetRenderer::FromJson( _In_ ABI::Windows::Data::Json::IJsonObject* jsonObject, From cceb8bc482230f7eeed3e6d3f3ce327bac626d47 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 14:23:19 -0700 Subject: [PATCH 07/16] AdaptiveTimeInputRenderer THROW_IF_FAILED -> RETURN_IF_FAILED --- source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp index 1d5c475f8f..d6ff3be308 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp @@ -16,11 +16,10 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTimeInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTimeInputRenderer::RuntimeClassInitialize() noexcept { return S_OK; } - CATCH_RETURN; HRESULT AdaptiveTimeInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, @@ -52,17 +51,17 @@ namespace AdaptiveNamespace ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveTimeInput; - THROW_IF_FAILED(cardElement.As(&adaptiveTimeInput)); + RETURN_IF_FAILED(cardElement.As(&adaptiveTimeInput)); // Set initial value HString hstringValue; - THROW_IF_FAILED(adaptiveTimeInput->get_Value(hstringValue.GetAddressOf())); + RETURN_IF_FAILED(adaptiveTimeInput->get_Value(hstringValue.GetAddressOf())); std::string value = HStringToUTF8(hstringValue.Get()); unsigned int hours, minutes; if (DateTimePreparser::TryParseSimpleTime(value, hours, minutes)) { TimeSpan initialTime{(INT64)(hours * 60 + minutes) * 10000000 * 60}; - THROW_IF_FAILED(timePicker->put_Time(initialTime)); + RETURN_IF_FAILED(timePicker->put_Time(initialTime)); } // Note: Placeholder text and min/max are not supported by ITimePicker From 7ce0aff0c4abf5a7a54228aa7223cbd3cf525676 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 14:45:38 -0700 Subject: [PATCH 08/16] HSTRING->HString everywhere --- source/uwp/Renderer/lib/ActionHelpers.cpp | 6 +++--- .../uwp/Renderer/lib/AdaptiveImageRenderer.cpp | 16 ++++++++-------- .../uwp/Renderer/lib/AdaptiveMediaRenderer.cpp | 3 ++- source/uwp/Renderer/lib/MediaHelpers.cpp | 3 ++- source/uwp/Renderer/lib/Util.cpp | 8 ++++---- source/uwp/Renderer/lib/WholeItemsPanel.cpp | 15 +++++++-------- source/uwp/Renderer/lib/XamlHelpers.cpp | 13 ++++++------- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/source/uwp/Renderer/lib/ActionHelpers.cpp b/source/uwp/Renderer/lib/ActionHelpers.cpp index 01279bcbd0..778bcffda6 100644 --- a/source/uwp/Renderer/lib/ActionHelpers.cpp +++ b/source/uwp/Renderer/lib/ActionHelpers.cpp @@ -51,8 +51,8 @@ namespace AdaptiveNamespace::ActionHelpers HString title; THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); - HSTRING iconUrl; - THROW_IF_FAILED(action->get_IconUrl(&iconUrl)); + HString iconUrl; + THROW_IF_FAILED(action->get_IconUrl(iconUrl.GetAddressOf())); ComPtr localButton(button); @@ -74,7 +74,7 @@ namespace AdaptiveNamespace::ActionHelpers ComPtr adaptiveImage; THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - adaptiveImage->put_Url(iconUrl); + adaptiveImage->put_Url(iconUrl.Get()); adaptiveImage->put_HorizontalAlignment(ABI::AdaptiveNamespace::HAlignment::Center); ComPtr adaptiveCardElement; diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index a26e0ba57b..7510ffe587 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -88,11 +88,11 @@ namespace AdaptiveNamespace ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - HSTRING url; - RETURN_IF_FAILED(adaptiveImage->get_Url(&url)); + HString url; + RETURN_IF_FAILED(adaptiveImage->get_Url(url.GetAddressOf())); ComPtr imageUrl; - GetUrlFromString(hostConfig.Get(), url, imageUrl.GetAddressOf()); + GetUrlFromString(hostConfig.Get(), url.Get(), imageUrl.GetAddressOf()); if (imageUrl == nullptr) { @@ -127,8 +127,8 @@ namespace AdaptiveNamespace ComPtr resourceResolvers; RETURN_IF_FAILED(renderContext->get_ResourceResolvers(&resourceResolvers)); - HSTRING backgroundColor; - RETURN_IF_FAILED(adaptiveImage->get_BackgroundColor(&backgroundColor)); + HString backgroundColor; + RETURN_IF_FAILED(adaptiveImage->get_BackgroundColor(backgroundColor.GetAddressOf())); boolean isVisible; RETURN_IF_FAILED(adaptiveCardElement->get_IsVisible(&isVisible)); @@ -178,11 +178,11 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(backgroundEllipseAsShape->put_Stretch(ellipseStretch)); } - if (backgroundColor != nullptr) + if (backgroundColor.Get() != nullptr) { // Fill the background ellipse with solid color brush ABI::Windows::UI::Color color; - RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); + RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor.Get()), &color)); ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); RETURN_IF_FAILED(backgroundEllipseAsShape->put_Fill(backgroundColorBrush.Get())); @@ -215,7 +215,7 @@ namespace AdaptiveNamespace XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Border)); ABI::Windows::UI::Color color; - RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor), &color)); + RETURN_IF_FAILED(GetColorFromString(HStringToUTF8(backgroundColor.Get()), &color)); ComPtr backgroundColorBrush = XamlHelpers::GetSolidColorBrush(color); RETURN_IF_FAILED(border->put_Background(backgroundColorBrush.Get())); diff --git a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp index c79c137bd3..8d4481b890 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp @@ -134,7 +134,8 @@ namespace AdaptiveNamespace ComPtr touchTargetAsButtonBase; RETURN_IF_FAILED(touchTargetUIElement.As(&touchTargetAsButtonBase)); - // Take a reference to the mime type string for the lambda + // Take a reference to the mime type string for the lambda (lifetime dictated by localMimeType in the below + // lambda) HSTRING lambdaMimeType; WindowsDuplicateString(mimeType.Get(), &lambdaMimeType); ComPtr lambdaRenderContext{renderContext}; diff --git a/source/uwp/Renderer/lib/MediaHelpers.cpp b/source/uwp/Renderer/lib/MediaHelpers.cpp index bb6fd2eb05..7b83b8c630 100644 --- a/source/uwp/Renderer/lib/MediaHelpers.cpp +++ b/source/uwp/Renderer/lib/MediaHelpers.cpp @@ -346,7 +346,8 @@ HRESULT HandleMediaClick(_In_ IAdaptiveRenderContext* renderContext, ComPtr> getResourceStreamOperation; RETURN_IF_FAILED(resourceResolver->GetResourceStreamAsync(args.Get(), &getResourceStreamOperation)); - // Take a reference to the mime type string for the lambda + // Take a reference to the mime type string for the lambda (lifetime dictated by localMimeType in the below + // lambda) HSTRING lambdaMimeType; WindowsDuplicateString(mimeType, &lambdaMimeType); diff --git a/source/uwp/Renderer/lib/Util.cpp b/source/uwp/Renderer/lib/Util.cpp index 900018349a..82c9534a36 100644 --- a/source/uwp/Renderer/lib/Util.cpp +++ b/source/uwp/Renderer/lib/Util.cpp @@ -1488,12 +1488,12 @@ void GetUrlFromString(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConf // Otherwise, try to treat URI as relative if (isUrlRelative) { - HSTRING imageBaseUrl; - THROW_IF_FAILED(hostConfig->get_ImageBaseUrl(&imageBaseUrl)); + HString imageBaseUrl; + THROW_IF_FAILED(hostConfig->get_ImageBaseUrl(imageBaseUrl.GetAddressOf())); - if (imageBaseUrl != nullptr) + if (imageBaseUrl.Get() != nullptr) { - THROW_IF_FAILED(uriActivationFactory->CreateWithRelativeUri(imageBaseUrl, urlString, localUrl.GetAddressOf())); + THROW_IF_FAILED(uriActivationFactory->CreateWithRelativeUri(imageBaseUrl.Get(), urlString, localUrl.GetAddressOf())); } } diff --git a/source/uwp/Renderer/lib/WholeItemsPanel.cpp b/source/uwp/Renderer/lib/WholeItemsPanel.cpp index 88c589cc00..3a0a67f628 100644 --- a/source/uwp/Renderer/lib/WholeItemsPanel.cpp +++ b/source/uwp/Renderer/lib/WholeItemsPanel.cpp @@ -405,11 +405,11 @@ namespace AdaptiveNamespace std::string elementAccessKey = std::to_string(m_accessKeyCount); ++m_accessKeyCount; - HSTRING accessKey; - if (SUCCEEDED(UTF8ToHString(elementAccessKey, &accessKey))) + HString accessKey; + if (SUCCEEDED(UTF8ToHString(elementAccessKey, accessKey.GetAddressOf()))) { - elementWithAccessKey->put_AccessKey(accessKey); - m_stretchableItems.insert(elementAccessKey); + elementWithAccessKey->put_AccessKey(accessKey.Get()); + m_stretchableItems.insert(std::move(elementAccessKey)); } } } @@ -420,11 +420,10 @@ namespace AdaptiveNamespace ComPtr elementWithAccessKey; if (SUCCEEDED(localElement.As(&elementWithAccessKey))) { - HSTRING elementAccessKey; - if (SUCCEEDED(elementWithAccessKey->get_AccessKey(&elementAccessKey))) + HString elementAccessKey; + if (SUCCEEDED(elementWithAccessKey->get_AccessKey(elementAccessKey.GetAddressOf()))) { - std::string accessKey = HStringToUTF8(elementAccessKey); - return (m_stretchableItems.find(accessKey) != m_stretchableItems.end()); + return (m_stretchableItems.find(HStringToUTF8(elementAccessKey.Get())) != m_stretchableItems.end()); } } diff --git a/source/uwp/Renderer/lib/XamlHelpers.cpp b/source/uwp/Renderer/lib/XamlHelpers.cpp index f2c5f9038f..93a66e4bb1 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.cpp +++ b/source/uwp/Renderer/lib/XamlHelpers.cpp @@ -413,10 +413,10 @@ namespace AdaptiveNamespace::XamlHelpers // In order to reuse the image creation code paths, we simply create an adaptive card // image element and then build that into xaml and apply to the root. ComPtr adaptiveImage; - HSTRING url; + HString url; THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - THROW_IF_FAILED(backgroundImage->get_Url(&url)); - THROW_IF_FAILED(adaptiveImage->put_Url(url)); + THROW_IF_FAILED(backgroundImage->get_Url(url.GetAddressOf())); + THROW_IF_FAILED(adaptiveImage->put_Url(url.Get())); ComPtr adaptiveCardElement; THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); @@ -895,11 +895,10 @@ namespace AdaptiveNamespace::XamlHelpers bool allActionsHaveIcons{true}; XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { - HSTRING iconUrl; - RETURN_IF_FAILED(child->get_IconUrl(&iconUrl)); + HString iconUrl; + RETURN_IF_FAILED(child->get_IconUrl(iconUrl.GetAddressOf())); - bool iconUrlIsEmpty = WindowsIsStringEmpty(iconUrl); - if (iconUrlIsEmpty) + if (WindowsIsStringEmpty(iconUrl.Get())) { allActionsHaveIcons = false; } From 3a35dc3b3c054850fe276a520efd2e2fd43229d7 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 15:04:16 -0700 Subject: [PATCH 09/16] Move some helpers from XamlHelpers to ActionHelpers --- source/uwp/Renderer/lib/ActionHelpers.cpp | 433 +++++++++++++++++- source/uwp/Renderer/lib/ActionHelpers.h | 34 ++ .../lib/AdaptiveActionSetRenderer.cpp | 17 +- .../Renderer/lib/AdaptiveColumnRenderer.cpp | 19 +- .../lib/AdaptiveColumnSetRenderer.cpp | 18 +- .../lib/AdaptiveContainerRenderer.cpp | 22 +- .../Renderer/lib/AdaptiveImageRenderer.cpp | 15 +- .../Renderer/lib/AdaptiveMediaRenderer.cpp | 4 +- source/uwp/Renderer/lib/XamlBuilder.cpp | 29 +- source/uwp/Renderer/lib/XamlHelpers.cpp | 424 ----------------- source/uwp/Renderer/lib/XamlHelpers.h | 34 -- 11 files changed, 525 insertions(+), 524 deletions(-) diff --git a/source/uwp/Renderer/lib/ActionHelpers.cpp b/source/uwp/Renderer/lib/ActionHelpers.cpp index 778bcffda6..59ce061a7a 100644 --- a/source/uwp/Renderer/lib/ActionHelpers.cpp +++ b/source/uwp/Renderer/lib/ActionHelpers.cpp @@ -5,6 +5,7 @@ #include "ActionHelpers.h" #include "AdaptiveImage.h" #include "AdaptiveRenderArgs.h" +#include "AdaptiveShowCardActionRenderer.h" using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -12,6 +13,7 @@ using namespace ABI::AdaptiveNamespace; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Automation; using namespace ABI::Windows::UI::Xaml::Controls; using namespace ABI::Windows::UI::Xaml::Controls::Primitives; using namespace ABI::Windows::UI::Xaml::Input; @@ -552,13 +554,7 @@ namespace AdaptiveNamespace::ActionHelpers // Wrap the action in a button ComPtr touchTargetUIElement; - XamlHelpers::WrapInTouchTarget(nullptr, - actionUIElement.Get(), - localInlineAction.Get(), - renderContext, - false, - L"Adaptive.Input.Text.InlineAction", - &touchTargetUIElement); + WrapInTouchTarget(nullptr, actionUIElement.Get(), localInlineAction.Get(), renderContext, false, L"Adaptive.Input.Text.InlineAction", &touchTargetUIElement); ComPtr touchTargetFrameworkElement; THROW_IF_FAILED(touchTargetUIElement.As(&touchTargetFrameworkElement)); @@ -592,4 +588,427 @@ namespace AdaptiveNamespace::ActionHelpers THROW_IF_FAILED(xamlGrid.CopyTo(textBoxWithInlineAction)); } + + void WrapInTouchTarget(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IUIElement* elementToWrap, + _In_ IAdaptiveActionElement* action, + _In_ IAdaptiveRenderContext* renderContext, + bool fullWidth, + const std::wstring& style, + _COM_Outptr_ IUIElement** finalElement) + { + ComPtr hostConfig; + THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + + if (ActionHelpers::WarnForInlineShowCard(renderContext, action, L"Inline ShowCard not supported for SelectAction")) + { + // Was inline show card, so don't wrap the element and just return + ComPtr localElementToWrap(elementToWrap); + localElementToWrap.CopyTo(finalElement); + return; + } + + ComPtr button = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); + + ComPtr buttonAsContentControl; + THROW_IF_FAILED(button.As(&buttonAsContentControl)); + THROW_IF_FAILED(buttonAsContentControl->put_Content(elementToWrap)); + + ComPtr spacingConfig; + THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + + UINT32 cardPadding = 0; + if (fullWidth) + { + THROW_IF_FAILED(spacingConfig->get_Padding(&cardPadding)); + } + + ComPtr buttonAsFrameworkElement; + THROW_IF_FAILED(button.As(&buttonAsFrameworkElement)); + + // We want the hit target to equally split the vertical space above and below the current item. + // However, all we know is the spacing of the current item, which only applies to the spacing above. + // We don't know what the spacing of the NEXT element will be, so we can't calculate the correct spacing + // below. For now, we'll simply assume the bottom spacing is the same as the top. NOTE: Only apply spacings + // (padding, margin) for adaptive card elements to avoid adding spacings to card-level selectAction. + if (adaptiveCardElement != nullptr) + { + ABI::AdaptiveNamespace::Spacing elementSpacing; + THROW_IF_FAILED(adaptiveCardElement->get_Spacing(&elementSpacing)); + UINT spacingSize; + THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), elementSpacing, &spacingSize)); + double topBottomPadding = spacingSize / 2.0; + + // For button padding, we apply the cardPadding and topBottomPadding (and then we negate these in the margin) + ComPtr buttonAsControl; + THROW_IF_FAILED(button.As(&buttonAsControl)); + THROW_IF_FAILED(buttonAsControl->put_Padding({(double)cardPadding, topBottomPadding, (double)cardPadding, topBottomPadding})); + + double negativeCardMargin = cardPadding * -1.0; + double negativeTopBottomMargin = topBottomPadding * -1.0; + + THROW_IF_FAILED(buttonAsFrameworkElement->put_Margin( + {negativeCardMargin, negativeTopBottomMargin, negativeCardMargin, negativeTopBottomMargin})); + } + + // Style the hit target button + THROW_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, style.c_str(), buttonAsFrameworkElement.Get())); + + if (action != nullptr) + { + // If we have an action, use the title for the AutomationProperties.Name + HString title; + THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); + + ComPtr buttonAsDependencyObject; + THROW_IF_FAILED(button.As(&buttonAsDependencyObject)); + + ComPtr automationPropertiesStatics; + THROW_IF_FAILED( + GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), + &automationPropertiesStatics)); + + THROW_IF_FAILED(automationPropertiesStatics->SetName(buttonAsDependencyObject.Get(), title.Get())); + + WireButtonClickToAction(button.Get(), action, renderContext); + } + + THROW_IF_FAILED(button.CopyTo(finalElement)); + } + + void WireButtonClickToAction(_In_ IButton* button, _In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext) + { + // Note that this method currently doesn't support inline show card actions, it + // assumes the caller won't call this method if inline show card is specified. + ComPtr localButton(button); + ComPtr actionInvoker; + THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); + ComPtr strongAction(action); + + // Add click handler + ComPtr buttonBase; + THROW_IF_FAILED(localButton.As(&buttonBase)); + + EventRegistrationToken clickToken; + THROW_IF_FAILED(buttonBase->add_Click(Callback([strongAction, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + THROW_IF_FAILED(actionInvoker->SendActionEvent(strongAction.Get())); + return S_OK; + }).Get(), + &clickToken)); + } + + void HandleSelectAction(_In_ IAdaptiveCardElement* adaptiveCardElement, + _In_ IAdaptiveActionElement* selectAction, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IUIElement* uiElement, + bool supportsInteractivity, + bool fullWidthTouchTarget, + _COM_Outptr_ IUIElement** outUiElement) + { + if (selectAction != nullptr && supportsInteractivity) + { + WrapInTouchTarget(adaptiveCardElement, uiElement, selectAction, renderContext, fullWidthTouchTarget, L"Adaptive.SelectAction", outUiElement); + } + else + { + if (selectAction != nullptr) + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, + HStringReference(L"SelectAction present, but Interactivity is not supported").Get()); + } + + ComPtr localUiElement(uiElement); + THROW_IF_FAILED(localUiElement.CopyTo(outUiElement)); + } + } + + HRESULT BuildActions(_In_ IAdaptiveCard* adaptiveCard, + _In_ IVector* children, + _In_ IPanel* bodyPanel, + bool insertSeparator, + _In_ IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs) + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); + + // Create a separator between the body and the actions + if (insertSeparator) + { + ABI::AdaptiveNamespace::Spacing spacing; + RETURN_IF_FAILED(actionsConfig->get_Spacing(&spacing)); + + UINT spacingSize; + RETURN_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), spacing, &spacingSize)); + + ABI::Windows::UI::Color color = {0}; + auto separator = XamlHelpers::CreateSeparator(renderContext, spacingSize, 0, color); + XamlHelpers::AppendXamlElementToPanel(separator.Get(), bodyPanel); + } + + ComPtr actionSetControl; + RETURN_IF_FAILED(BuildActionSetHelper(adaptiveCard, nullptr, children, renderContext, renderArgs, &actionSetControl)); + + XamlHelpers::AppendXamlElementToPanel(actionSetControl.Get(), bodyPanel); + return S_OK; + } + + HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_opt_ IAdaptiveActionSet* adaptiveActionSet, + _In_ IVector* children, + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _Outptr_ IUIElement** actionSetControl) + { + ComPtr hostConfig; + RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); + ComPtr actionsConfig; + RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); + + ABI::AdaptiveNamespace::ActionAlignment actionAlignment; + RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); + + ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; + RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); + + // Declare the panel that will host the buttons + ComPtr actionsPanel; + ComPtr> columnDefinitions; + + if (actionAlignment == ABI::AdaptiveNamespace::ActionAlignment::Stretch && + actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + // If stretch alignment and orientation is horizontal, we use a grid with equal column widths to achieve + // stretch behavior. For vertical orientation, we'll still just use a stack panel since the concept of + // stretching buttons height isn't really valid, especially when the height of cards are typically dynamic. + ComPtr actionsGrid = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); + RETURN_IF_FAILED(actionsGrid->get_ColumnDefinitions(&columnDefinitions)); + RETURN_IF_FAILED(actionsGrid.As(&actionsPanel)); + } + else + { + // Create a stack panel for the action buttons + ComPtr actionStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + + auto uiOrientation = (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) ? + Orientation::Orientation_Horizontal : + Orientation::Orientation_Vertical; + + RETURN_IF_FAILED(actionStackPanel->put_Orientation(uiOrientation)); + + ComPtr actionsFrameworkElement; + RETURN_IF_FAILED(actionStackPanel.As(&actionsFrameworkElement)); + + switch (actionAlignment) + { + case ABI::AdaptiveNamespace::ActionAlignment::Center: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Left: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Right: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); + break; + case ABI::AdaptiveNamespace::ActionAlignment::Stretch: + RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); + break; + } + + // Add the action buttons to the stack panel + RETURN_IF_FAILED(actionStackPanel.As(&actionsPanel)); + } + + Thickness buttonMargin; + RETURN_IF_FAILED(ActionHelpers::GetButtonMargin(actionsConfig.Get(), buttonMargin)); + if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) + { + // Negate the spacing on the sides so the left and right buttons are flush on the side. + // We do NOT remove the margin from the individual button itself, since that would cause + // the equal columns stretch behavior to not have equal columns (since the first and last + // button would be narrower without the same margins as its peers). + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({buttonMargin.Left * -1, 0, buttonMargin.Right * -1, 0})); + } + else + { + // Negate the spacing on the top and bottom so the first and last buttons don't have extra padding + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({0, buttonMargin.Top * -1, 0, buttonMargin.Bottom * -1})); + } + + UINT32 maxActions; + RETURN_IF_FAILED(actionsConfig->get_MaxActions(&maxActions)); + + bool allActionsHaveIcons{true}; + XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { + HString iconUrl; + RETURN_IF_FAILED(child->get_IconUrl(iconUrl.GetAddressOf())); + + if (WindowsIsStringEmpty(iconUrl.Get())) + { + allActionsHaveIcons = false; + } + return S_OK; + }); + + UINT currentAction = 0; + + RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(allActionsHaveIcons)); + + std::shared_ptr>> allShowCards = std::make_shared>>(); + ComPtr showCardsStackPanel = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + ComPtr gridStatics; + RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); + XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { + if (currentAction < maxActions) + { + // Render each action using the registered renderer + ComPtr action(child); + ComPtr actionRegistration; + RETURN_IF_FAILED(renderContext->get_ActionRenderers(&actionRegistration)); + + ComPtr renderer; + while (!renderer) + { + HString actionTypeString; + RETURN_IF_FAILED(action->get_ActionTypeString(actionTypeString.GetAddressOf())); + RETURN_IF_FAILED(actionRegistration->Get(actionTypeString.Get(), &renderer)); + if (!renderer) + { + ABI::AdaptiveNamespace::FallbackType actionFallbackType; + action->get_FallbackType(&actionFallbackType); + switch (actionFallbackType) + { + case ABI::AdaptiveNamespace::FallbackType::Drop: + { + RETURN_IF_FAILED(XamlHelpers::WarnForFallbackDrop(renderContext, actionTypeString.Get())); + return S_OK; + } + + case ABI::AdaptiveNamespace::FallbackType::Content: + { + ComPtr actionFallback; + RETURN_IF_FAILED(action->get_FallbackContent(&actionFallback)); + + HString fallbackTypeString; + RETURN_IF_FAILED(actionFallback->get_ActionTypeString(fallbackTypeString.GetAddressOf())); + RETURN_IF_FAILED(XamlHelpers::WarnForFallbackContentElement(renderContext, + actionTypeString.Get(), + fallbackTypeString.Get())); + + action = actionFallback; + break; + } + + case ABI::AdaptiveNamespace::FallbackType::None: + default: + return E_FAIL; + } + } + } + + ComPtr actionControl; + RETURN_IF_FAILED(renderer->Render(action.Get(), renderContext, renderArgs, &actionControl)); + + XamlHelpers::AppendXamlElementToPanel(actionControl.Get(), actionsPanel.Get()); + + ABI::AdaptiveNamespace::ActionType actionType; + RETURN_IF_FAILED(action->get_ActionType(&actionType)); + + // Build inline show cards if needed + if (actionType == ABI::AdaptiveNamespace::ActionType_ShowCard) + { + ComPtr uiShowCard; + + ComPtr showCardActionConfig; + RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); + + ABI::AdaptiveNamespace::ActionMode showCardActionMode; + RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); + + if (showCardActionMode == ABI::AdaptiveNamespace::ActionMode::Inline) + { + ComPtr showCardAction; + RETURN_IF_FAILED(action.As(&showCardAction)); + + ComPtr showCard; + RETURN_IF_FAILED(showCardAction->get_Card(&showCard)); + + RETURN_IF_FAILED(AdaptiveShowCardActionRenderer::BuildShowCard( + showCard.Get(), renderContext, renderArgs, (adaptiveActionSet == nullptr), uiShowCard.GetAddressOf())); + + ComPtr showCardsPanel; + RETURN_IF_FAILED(showCardsStackPanel.As(&showCardsPanel)); + XamlHelpers::AppendXamlElementToPanel(uiShowCard.Get(), showCardsPanel.Get()); + + if (adaptiveActionSet) + { + RETURN_IF_FAILED( + renderContext->AddInlineShowCard(adaptiveActionSet, showCardAction.Get(), uiShowCard.Get())); + } + else + { + ComPtr contextImpl = + PeekInnards(renderContext); + + RETURN_IF_FAILED( + contextImpl->AddInlineShowCard(adaptiveCard, showCardAction.Get(), uiShowCard.Get())); + } + } + } + + if (columnDefinitions != nullptr) + { + // If using the equal width columns, we'll add a column and assign the column + ComPtr columnDefinition = XamlHelpers::CreateXamlClass( + HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); + RETURN_IF_FAILED(columnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Star})); + RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); + + ComPtr actionFrameworkElement; + THROW_IF_FAILED(actionControl.As(&actionFrameworkElement)); + THROW_IF_FAILED(gridStatics->SetColumn(actionFrameworkElement.Get(), currentAction)); + } + } + else + { + renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::MaxActionsExceeded, + HStringReference(L"Some actions were not rendered due to exceeding the maximum number of actions allowed") + .Get()); + } + currentAction++; + return S_OK; + }); + + // Reset icon placement value + RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(false)); + + ComPtr actionsPanelAsFrameworkElement; + RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); + RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, + L"Adaptive.Actions", + actionsPanelAsFrameworkElement.Get())); + + ComPtr actionSet = + XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); + ComPtr actionSetAsPanel; + actionSet.As(&actionSetAsPanel); + + // Add buttons and show cards to panel + XamlHelpers::AppendXamlElementToPanel(actionsPanel.Get(), actionSetAsPanel.Get()); + XamlHelpers::AppendXamlElementToPanel(showCardsStackPanel.Get(), actionSetAsPanel.Get()); + + return actionSetAsPanel.CopyTo(actionSetControl); + } } diff --git a/source/uwp/Renderer/lib/ActionHelpers.h b/source/uwp/Renderer/lib/ActionHelpers.h index e428535171..ae87299f48 100644 --- a/source/uwp/Renderer/lib/ActionHelpers.h +++ b/source/uwp/Renderer/lib/ActionHelpers.h @@ -36,4 +36,38 @@ namespace AdaptiveNamespace::ActionHelpers _In_ ABI::Windows::UI::Xaml::Controls::ITextBox* textBox, _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* inlineAction, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** textBoxWithInlineAction); + + void WireButtonClickToAction(_In_ ABI::Windows::UI::Xaml::Controls::IButton* button, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); + + void WrapInTouchTarget(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, + _In_ ABI::Windows::UI::Xaml::IUIElement* elementToWrap, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + bool fullWidth, + const std::wstring& style, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** finalElement); + + void HandleSelectAction(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, + _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* selectAction, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::Windows::UI::Xaml::IUIElement* uiElement, + bool supportsInteractivity, + bool fullWidthTouchTarget, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** outUiElement); + + HRESULT BuildActions(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_ ABI::Windows::Foundation::Collections::IVector* children, + _In_ ABI::Windows::UI::Xaml::Controls::IPanel* bodyPanel, + bool insertSeparator, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); + + HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, + _In_opt_ ABI::AdaptiveNamespace::IAdaptiveActionSet* adaptiveActionSet, + _In_ ABI::Windows::Foundation::Collections::IVector* children, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, + _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionSetControl); } diff --git a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp index 3ee5e8f81d..f019ee57b8 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSetRenderer.cpp @@ -2,8 +2,10 @@ // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveActionSet.h" #include "AdaptiveActionSetRenderer.h" + +#include "ActionHelpers.h" +#include "AdaptiveActionSet.h" #include "AdaptiveElementParserRegistration.h" #include "AdaptiveRenderArgs.h" @@ -18,17 +20,15 @@ using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { - HRESULT AdaptiveActionSetRenderer::RuntimeClassInitialize() noexcept - { - return S_OK; - } + HRESULT AdaptiveActionSetRenderer::RuntimeClassInitialize() noexcept { return S_OK; } HRESULT AdaptiveActionSetRenderer::FromJson( _In_ ABI::Windows::Data::Json::IJsonObject* jsonObject, _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); @@ -38,7 +38,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveActionSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** actionSetControl) noexcept try + _COM_Outptr_ IUIElement** actionSetControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -58,7 +59,7 @@ namespace AdaptiveNamespace ComPtr> actions; RETURN_IF_FAILED(adaptiveActionSet->get_Actions(&actions)); - return XamlHelpers::BuildActionSetHelper(nullptr, adaptiveActionSet.Get(), actions.Get(), renderContext, renderArgs, actionSetControl); + return ActionHelpers::BuildActionSetHelper(nullptr, adaptiveActionSet.Get(), actions.Get(), renderContext, renderArgs, actionSetControl); } CATCH_RETURN; } diff --git a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp index 972be5c9ce..746420bf6b 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp @@ -3,6 +3,8 @@ #include "pch.h" #include "AdaptiveColumnRenderer.h" + +#include "ActionHelpers.h" #include "AdaptiveColumn.h" #include "AdaptiveElementParserRegistration.h" #include "AdaptiveRenderArgs.h" @@ -17,11 +19,10 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveColumnRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColumnRenderer::RuntimeClassInitialize() noexcept { return S_OK; } - CATCH_RETURN; HRESULT AdaptiveColumnRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, @@ -121,13 +122,13 @@ namespace AdaptiveNamespace ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - XamlHelpers::HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - columnAsUIElement.Get(), - XamlHelpers::SupportsInteractivity(hostConfig.Get()), - false, - ColumnControl); + ActionHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + columnAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + false, + ColumnControl); return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp index 53831cdac7..c94cb0d4a4 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp @@ -2,8 +2,10 @@ // Licensed under the MIT License. #include "pch.h" -#include "AdaptiveColumnSet.h" #include "AdaptiveColumnSetRenderer.h" + +#include "ActionHelpers.h" +#include "AdaptiveColumnSet.h" #include "AdaptiveElementParserRegistration.h" #include "AdaptiveRenderArgs.h" @@ -213,13 +215,13 @@ namespace AdaptiveNamespace ComPtr columnSetBorderAsUIElement; RETURN_IF_FAILED(columnSetBorder.As(&columnSetBorderAsUIElement)); - XamlHelpers::HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - columnSetBorderAsUIElement.Get(), - XamlHelpers::SupportsInteractivity(hostConfig.Get()), - true, - columnSetControl); + ActionHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + columnSetBorderAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + columnSetControl); return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp index 16b10c9401..906188a9aa 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp @@ -3,6 +3,8 @@ #include "pch.h" #include "AdaptiveContainer.h" + +#include "ActionHelpers.h" #include "AdaptiveContainerRenderer.h" #include "AdaptiveElementParserRegistration.h" #include "AdaptiveRenderArgs.h" @@ -17,11 +19,7 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveContainerRenderer::RuntimeClassInitialize() noexcept try - { - return S_OK; - } - CATCH_RETURN; + HRESULT AdaptiveContainerRenderer::RuntimeClassInitialize() noexcept { return S_OK; } HRESULT AdaptiveContainerRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, @@ -126,13 +124,13 @@ namespace AdaptiveNamespace ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - XamlHelpers::HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - containerBorderAsUIElement.Get(), - XamlHelpers::SupportsInteractivity(hostConfig.Get()), - true, - containerControl); + ActionHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + containerBorderAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + containerControl); return S_OK; } CATCH_RETURN; diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index 7510ffe587..f739382011 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -4,6 +4,7 @@ #include "AdaptiveImageRenderer.h" +#include "ActionHelpers.h" #include "AdaptiveElementParserRegistration.h" #include "AdaptiveImage.h" #include "AdaptiveBase64Util.h" @@ -359,13 +360,13 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(automationPropertiesStatics->SetName(imageAsDependencyObject.Get(), altText.Get())); - XamlHelpers::HandleSelectAction(adaptiveCardElement, - selectAction.Get(), - renderContext, - imageAsUIElement.Get(), - XamlHelpers::SupportsInteractivity(hostConfig.Get()), - true, - imageControl); + ActionHelpers::HandleSelectAction(adaptiveCardElement, + selectAction.Get(), + renderContext, + imageAsUIElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + imageControl); return S_OK; } diff --git a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp index 8d4481b890..f559fc3147 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp @@ -3,6 +3,8 @@ #include "pch.h" #include "AdaptiveMedia.h" + +#include "ActionHelpers.h" #include "AdaptiveMediaRenderer.h" #include "AdaptiveElementParserRegistration.h" #include "MediaHelpers.h" @@ -60,7 +62,7 @@ namespace AdaptiveNamespace CreatePosterContainerWithPlayButton(posterImage.Get(), renderContext, renderArgs, &posterContainer); ComPtr touchTargetUIElement; - XamlHelpers::WrapInTouchTarget(adaptiveCardElement, posterContainer.Get(), nullptr, renderContext, true, L"Adaptive.SelectAction", &touchTargetUIElement); + ActionHelpers::WrapInTouchTarget(adaptiveCardElement, posterContainer.Get(), nullptr, renderContext, true, L"Adaptive.SelectAction", &touchTargetUIElement); // Create a panel to hold the poster and the media element ComPtr mediaStackPanel = diff --git a/source/uwp/Renderer/lib/XamlBuilder.cpp b/source/uwp/Renderer/lib/XamlBuilder.cpp index 7707ff4cf8..61bd5617ba 100644 --- a/source/uwp/Renderer/lib/XamlBuilder.cpp +++ b/source/uwp/Renderer/lib/XamlBuilder.cpp @@ -75,7 +75,8 @@ namespace AdaptiveNamespace ComPtr bodyElementContainer; ComPtr rootElement; - RETURN_IF_FAILED(CreateRootCardElement(adaptiveCard, renderContext, renderArgs.Get(), xamlBuilder, &bodyElementContainer, &rootElement)); + RETURN_IF_FAILED( + CreateRootCardElement(adaptiveCard, renderContext, renderArgs.Get(), xamlBuilder, &bodyElementContainer, &rootElement)); ComPtr rootAsFrameworkElement; RETURN_IF_FAILED(rootElement.As(&rootAsFrameworkElement)); @@ -91,13 +92,13 @@ namespace AdaptiveNamespace // Create a new IUIElement pointer to house the root element decorated with select action ComPtr rootSelectActionElement; - XamlHelpers::HandleSelectAction(nullptr, - selectAction.Get(), - renderContext, - rootElement.Get(), - XamlHelpers::SupportsInteractivity(hostConfig.Get()), - true, - &rootSelectActionElement); + ActionHelpers::HandleSelectAction(nullptr, + selectAction.Get(), + renderContext, + rootElement.Get(), + XamlHelpers::SupportsInteractivity(hostConfig.Get()), + true, + &rootSelectActionElement); RETURN_IF_FAILED(rootSelectActionElement.As(&rootAsFrameworkElement)); // Enumerate the child items of the card and build xaml for them @@ -123,12 +124,12 @@ namespace AdaptiveNamespace { unsigned int bodyCount; RETURN_IF_FAILED(body->get_Size(&bodyCount)); - XamlHelpers::BuildActions(adaptiveCard, - actions.Get(), - bodyElementContainer.Get(), - bodyCount > 0, - renderContext, - renderArgs.Get()); + ActionHelpers::BuildActions(adaptiveCard, + actions.Get(), + bodyElementContainer.Get(), + bodyCount > 0, + renderContext, + renderArgs.Get()); } else { diff --git a/source/uwp/Renderer/lib/XamlHelpers.cpp b/source/uwp/Renderer/lib/XamlHelpers.cpp index 93a66e4bb1..ff09a65562 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.cpp +++ b/source/uwp/Renderer/lib/XamlHelpers.cpp @@ -7,7 +7,6 @@ #include "ActionHelpers.h" #include "ElementTagContent.h" #include "TileControl.h" -#include "AdaptiveShowCardActionRenderer.h" #include "AdaptiveImage.h" using namespace Microsoft::WRL; @@ -84,117 +83,6 @@ namespace AdaptiveNamespace::XamlHelpers return S_OK; } - void WrapInTouchTarget(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IUIElement* elementToWrap, - _In_ IAdaptiveActionElement* action, - _In_ IAdaptiveRenderContext* renderContext, - bool fullWidth, - const std::wstring& style, - _COM_Outptr_ IUIElement** finalElement) - { - ComPtr hostConfig; - THROW_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - - if (ActionHelpers::WarnForInlineShowCard(renderContext, action, L"Inline ShowCard not supported for SelectAction")) - { - // Was inline show card, so don't wrap the element and just return - ComPtr localElementToWrap(elementToWrap); - localElementToWrap.CopyTo(finalElement); - return; - } - - ComPtr button = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Button)); - - ComPtr buttonAsContentControl; - THROW_IF_FAILED(button.As(&buttonAsContentControl)); - THROW_IF_FAILED(buttonAsContentControl->put_Content(elementToWrap)); - - ComPtr spacingConfig; - THROW_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 cardPadding = 0; - if (fullWidth) - { - THROW_IF_FAILED(spacingConfig->get_Padding(&cardPadding)); - } - - ComPtr buttonAsFrameworkElement; - THROW_IF_FAILED(button.As(&buttonAsFrameworkElement)); - - // We want the hit target to equally split the vertical space above and below the current item. - // However, all we know is the spacing of the current item, which only applies to the spacing above. - // We don't know what the spacing of the NEXT element will be, so we can't calculate the correct spacing - // below. For now, we'll simply assume the bottom spacing is the same as the top. NOTE: Only apply spacings - // (padding, margin) for adaptive card elements to avoid adding spacings to card-level selectAction. - if (adaptiveCardElement != nullptr) - { - ABI::AdaptiveNamespace::Spacing elementSpacing; - THROW_IF_FAILED(adaptiveCardElement->get_Spacing(&elementSpacing)); - UINT spacingSize; - THROW_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), elementSpacing, &spacingSize)); - double topBottomPadding = spacingSize / 2.0; - - // For button padding, we apply the cardPadding and topBottomPadding (and then we negate these in the margin) - ComPtr buttonAsControl; - THROW_IF_FAILED(button.As(&buttonAsControl)); - THROW_IF_FAILED(buttonAsControl->put_Padding({(double)cardPadding, topBottomPadding, (double)cardPadding, topBottomPadding})); - - double negativeCardMargin = cardPadding * -1.0; - double negativeTopBottomMargin = topBottomPadding * -1.0; - - THROW_IF_FAILED(buttonAsFrameworkElement->put_Margin( - {negativeCardMargin, negativeTopBottomMargin, negativeCardMargin, negativeTopBottomMargin})); - } - - // Style the hit target button - THROW_IF_FAILED( - XamlHelpers::SetStyleFromResourceDictionary(renderContext, style.c_str(), buttonAsFrameworkElement.Get())); - - if (action != nullptr) - { - // If we have an action, use the title for the AutomationProperties.Name - HString title; - THROW_IF_FAILED(action->get_Title(title.GetAddressOf())); - - ComPtr buttonAsDependencyObject; - THROW_IF_FAILED(button.As(&buttonAsDependencyObject)); - - ComPtr automationPropertiesStatics; - THROW_IF_FAILED( - GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Automation_AutomationProperties).Get(), - &automationPropertiesStatics)); - - THROW_IF_FAILED(automationPropertiesStatics->SetName(buttonAsDependencyObject.Get(), title.Get())); - - WireButtonClickToAction(button.Get(), action, renderContext); - } - - THROW_IF_FAILED(button.CopyTo(finalElement)); - } - - void WireButtonClickToAction(_In_ IButton* button, _In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext) - { - // Note that this method currently doesn't support inline show card actions, it - // assumes the caller won't call this method if inline show card is specified. - ComPtr localButton(button); - ComPtr actionInvoker; - THROW_IF_FAILED(renderContext->get_ActionInvoker(&actionInvoker)); - ComPtr strongAction(action); - - // Add click handler - ComPtr buttonBase; - THROW_IF_FAILED(localButton.As(&buttonBase)); - - EventRegistrationToken clickToken; - THROW_IF_FAILED(buttonBase->add_Click(Callback([strongAction, actionInvoker](IInspectable* /*sender*/, IRoutedEventArgs * - /*args*/) -> HRESULT { - THROW_IF_FAILED(actionInvoker->SendActionEvent(strongAction.Get())); - return S_OK; - }).Get(), - &clickToken)); - } - HRESULT XamlHelpers::SetSeparatorVisibility(_In_ IPanel* parentPanel) { // Iterate over the elements in a container and ensure that the correct separators are marked as visible @@ -666,64 +554,6 @@ namespace AdaptiveNamespace::XamlHelpers &clickToken); } - void HandleSelectAction(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveActionElement* selectAction, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IUIElement* uiElement, - bool supportsInteractivity, - bool fullWidthTouchTarget, - _COM_Outptr_ IUIElement** outUiElement) - { - if (selectAction != nullptr && supportsInteractivity) - { - XamlHelpers::WrapInTouchTarget(adaptiveCardElement, uiElement, selectAction, renderContext, fullWidthTouchTarget, L"Adaptive.SelectAction", outUiElement); - } - else - { - if (selectAction != nullptr) - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::InteractivityNotSupported, - HStringReference(L"SelectAction present, but Interactivity is not supported").Get()); - } - - ComPtr localUiElement(uiElement); - THROW_IF_FAILED(localUiElement.CopyTo(outUiElement)); - } - } - - HRESULT BuildActions(_In_ IAdaptiveCard* adaptiveCard, - _In_ IVector* children, - _In_ IPanel* bodyPanel, - bool insertSeparator, - _In_ IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); - - // Create a separator between the body and the actions - if (insertSeparator) - { - ABI::AdaptiveNamespace::Spacing spacing; - RETURN_IF_FAILED(actionsConfig->get_Spacing(&spacing)); - - UINT spacingSize; - RETURN_IF_FAILED(GetSpacingSizeFromSpacing(hostConfig.Get(), spacing, &spacingSize)); - - ABI::Windows::UI::Color color = {0}; - auto separator = XamlHelpers::CreateSeparator(renderContext, spacingSize, 0, color); - XamlHelpers::AppendXamlElementToPanel(separator.Get(), bodyPanel); - } - - ComPtr actionSetControl; - RETURN_IF_FAILED(BuildActionSetHelper(adaptiveCard, nullptr, children, renderContext, renderArgs, &actionSetControl)); - - XamlHelpers::AppendXamlElementToPanel(actionSetControl.Get(), bodyPanel); - return S_OK; - } - HRESULT SetAutoImageSize(_In_ IFrameworkElement* imageControl, _In_ IInspectable* parentElement, _In_ IBitmapSource* imageSource, bool setVisible) { INT32 pixelHeight; @@ -801,258 +631,4 @@ namespace AdaptiveNamespace::XamlHelpers } } } - - HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_opt_ IAdaptiveActionSet* adaptiveActionSet, - _In_ IVector* children, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _Outptr_ IUIElement** actionSetControl) - { - ComPtr hostConfig; - RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); - ComPtr actionsConfig; - RETURN_IF_FAILED(hostConfig->get_Actions(actionsConfig.GetAddressOf())); - - ABI::AdaptiveNamespace::ActionAlignment actionAlignment; - RETURN_IF_FAILED(actionsConfig->get_ActionAlignment(&actionAlignment)); - - ABI::AdaptiveNamespace::ActionsOrientation actionsOrientation; - RETURN_IF_FAILED(actionsConfig->get_ActionsOrientation(&actionsOrientation)); - - // Declare the panel that will host the buttons - ComPtr actionsPanel; - ComPtr> columnDefinitions; - - if (actionAlignment == ABI::AdaptiveNamespace::ActionAlignment::Stretch && - actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - // If stretch alignment and orientation is horizontal, we use a grid with equal column widths to achieve - // stretch behavior. For vertical orientation, we'll still just use a stack panel since the concept of - // stretching buttons height isn't really valid, especially when the height of cards are typically dynamic. - ComPtr actionsGrid = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid)); - RETURN_IF_FAILED(actionsGrid->get_ColumnDefinitions(&columnDefinitions)); - RETURN_IF_FAILED(actionsGrid.As(&actionsPanel)); - } - else - { - // Create a stack panel for the action buttons - ComPtr actionStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - - auto uiOrientation = (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) ? - Orientation::Orientation_Horizontal : - Orientation::Orientation_Vertical; - - RETURN_IF_FAILED(actionStackPanel->put_Orientation(uiOrientation)); - - ComPtr actionsFrameworkElement; - RETURN_IF_FAILED(actionStackPanel.As(&actionsFrameworkElement)); - - switch (actionAlignment) - { - case ABI::AdaptiveNamespace::ActionAlignment::Center: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Center)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Left: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Left)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Right: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Right)); - break; - case ABI::AdaptiveNamespace::ActionAlignment::Stretch: - RETURN_IF_FAILED(actionsFrameworkElement->put_HorizontalAlignment(ABI::Windows::UI::Xaml::HorizontalAlignment_Stretch)); - break; - } - - // Add the action buttons to the stack panel - RETURN_IF_FAILED(actionStackPanel.As(&actionsPanel)); - } - - Thickness buttonMargin; - RETURN_IF_FAILED(ActionHelpers::GetButtonMargin(actionsConfig.Get(), buttonMargin)); - if (actionsOrientation == ABI::AdaptiveNamespace::ActionsOrientation::Horizontal) - { - // Negate the spacing on the sides so the left and right buttons are flush on the side. - // We do NOT remove the margin from the individual button itself, since that would cause - // the equal columns stretch behavior to not have equal columns (since the first and last - // button would be narrower without the same margins as its peers). - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({buttonMargin.Left * -1, 0, buttonMargin.Right * -1, 0})); - } - else - { - // Negate the spacing on the top and bottom so the first and last buttons don't have extra padding - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED(actionsPanelAsFrameworkElement->put_Margin({0, buttonMargin.Top * -1, 0, buttonMargin.Bottom * -1})); - } - - UINT32 maxActions; - RETURN_IF_FAILED(actionsConfig->get_MaxActions(&maxActions)); - - bool allActionsHaveIcons{true}; - XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { - HString iconUrl; - RETURN_IF_FAILED(child->get_IconUrl(iconUrl.GetAddressOf())); - - if (WindowsIsStringEmpty(iconUrl.Get())) - { - allActionsHaveIcons = false; - } - return S_OK; - }); - - UINT currentAction = 0; - - RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(allActionsHaveIcons)); - - std::shared_ptr>> allShowCards = std::make_shared>>(); - ComPtr showCardsStackPanel = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - ComPtr gridStatics; - RETURN_IF_FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_Grid).Get(), &gridStatics)); - XamlHelpers::IterateOverVector(children, [&](IAdaptiveActionElement* child) { - if (currentAction < maxActions) - { - // Render each action using the registered renderer - ComPtr action(child); - ComPtr actionRegistration; - RETURN_IF_FAILED(renderContext->get_ActionRenderers(&actionRegistration)); - - ComPtr renderer; - while (!renderer) - { - HString actionTypeString; - RETURN_IF_FAILED(action->get_ActionTypeString(actionTypeString.GetAddressOf())); - RETURN_IF_FAILED(actionRegistration->Get(actionTypeString.Get(), &renderer)); - if (!renderer) - { - ABI::AdaptiveNamespace::FallbackType actionFallbackType; - action->get_FallbackType(&actionFallbackType); - switch (actionFallbackType) - { - case ABI::AdaptiveNamespace::FallbackType::Drop: - { - RETURN_IF_FAILED(XamlHelpers::WarnForFallbackDrop(renderContext, actionTypeString.Get())); - return S_OK; - } - - case ABI::AdaptiveNamespace::FallbackType::Content: - { - ComPtr actionFallback; - RETURN_IF_FAILED(action->get_FallbackContent(&actionFallback)); - - HString fallbackTypeString; - RETURN_IF_FAILED(actionFallback->get_ActionTypeString(fallbackTypeString.GetAddressOf())); - RETURN_IF_FAILED(XamlHelpers::WarnForFallbackContentElement(renderContext, - actionTypeString.Get(), - fallbackTypeString.Get())); - - action = actionFallback; - break; - } - - case ABI::AdaptiveNamespace::FallbackType::None: - default: - return E_FAIL; - } - } - } - - ComPtr actionControl; - RETURN_IF_FAILED(renderer->Render(action.Get(), renderContext, renderArgs, &actionControl)); - - XamlHelpers::AppendXamlElementToPanel(actionControl.Get(), actionsPanel.Get()); - - ABI::AdaptiveNamespace::ActionType actionType; - RETURN_IF_FAILED(action->get_ActionType(&actionType)); - - // Build inline show cards if needed - if (actionType == ABI::AdaptiveNamespace::ActionType_ShowCard) - { - ComPtr uiShowCard; - - ComPtr showCardActionConfig; - RETURN_IF_FAILED(actionsConfig->get_ShowCard(&showCardActionConfig)); - - ABI::AdaptiveNamespace::ActionMode showCardActionMode; - RETURN_IF_FAILED(showCardActionConfig->get_ActionMode(&showCardActionMode)); - - if (showCardActionMode == ABI::AdaptiveNamespace::ActionMode::Inline) - { - ComPtr showCardAction; - RETURN_IF_FAILED(action.As(&showCardAction)); - - ComPtr showCard; - RETURN_IF_FAILED(showCardAction->get_Card(&showCard)); - - RETURN_IF_FAILED(AdaptiveShowCardActionRenderer::BuildShowCard( - showCard.Get(), renderContext, renderArgs, (adaptiveActionSet == nullptr), uiShowCard.GetAddressOf())); - - ComPtr showCardsPanel; - RETURN_IF_FAILED(showCardsStackPanel.As(&showCardsPanel)); - XamlHelpers::AppendXamlElementToPanel(uiShowCard.Get(), showCardsPanel.Get()); - - if (adaptiveActionSet) - { - RETURN_IF_FAILED( - renderContext->AddInlineShowCard(adaptiveActionSet, showCardAction.Get(), uiShowCard.Get())); - } - else - { - ComPtr contextImpl = - PeekInnards(renderContext); - - RETURN_IF_FAILED( - contextImpl->AddInlineShowCard(adaptiveCard, showCardAction.Get(), uiShowCard.Get())); - } - } - } - - if (columnDefinitions != nullptr) - { - // If using the equal width columns, we'll add a column and assign the column - ComPtr columnDefinition = XamlHelpers::CreateXamlClass( - HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ColumnDefinition)); - RETURN_IF_FAILED(columnDefinition->put_Width({1.0, GridUnitType::GridUnitType_Star})); - RETURN_IF_FAILED(columnDefinitions->Append(columnDefinition.Get())); - - ComPtr actionFrameworkElement; - THROW_IF_FAILED(actionControl.As(&actionFrameworkElement)); - THROW_IF_FAILED(gridStatics->SetColumn(actionFrameworkElement.Get(), currentAction)); - } - } - else - { - renderContext->AddWarning(ABI::AdaptiveNamespace::WarningStatusCode::MaxActionsExceeded, - HStringReference(L"Some actions were not rendered due to exceeding the maximum number of actions allowed") - .Get()); - } - currentAction++; - return S_OK; - }); - - // Reset icon placement value - RETURN_IF_FAILED(renderArgs->put_AllowAboveTitleIconPlacement(false)); - - ComPtr actionsPanelAsFrameworkElement; - RETURN_IF_FAILED(actionsPanel.As(&actionsPanelAsFrameworkElement)); - RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, - L"Adaptive.Actions", - actionsPanelAsFrameworkElement.Get())); - - ComPtr actionSet = - XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_StackPanel)); - ComPtr actionSetAsPanel; - actionSet.As(&actionSetAsPanel); - - // Add buttons and show cards to panel - XamlHelpers::AppendXamlElementToPanel(actionsPanel.Get(), actionSetAsPanel.Get()); - XamlHelpers::AppendXamlElementToPanel(showCardsStackPanel.Get(), actionSetAsPanel.Get()); - - return actionSetAsPanel.CopyTo(actionSetControl); - } } diff --git a/source/uwp/Renderer/lib/XamlHelpers.h b/source/uwp/Renderer/lib/XamlHelpers.h index 0dfaf63f8a..d02b0ced8b 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.h +++ b/source/uwp/Renderer/lib/XamlHelpers.h @@ -28,22 +28,10 @@ namespace AdaptiveNamespace::XamlHelpers return solidColorBrushAsBrush; } - void WireButtonClickToAction(_In_ ABI::Windows::UI::Xaml::Controls::IButton* button, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext); - HRESULT SetStyleFromResourceDictionary(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, const std::wstring& resourceName, _In_ ABI::Windows::UI::Xaml::IFrameworkElement* frameworkElement) noexcept; - void WrapInTouchTarget(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::Windows::UI::Xaml::IUIElement* elementToWrap, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - bool fullWidth, - const std::wstring& style, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** finalElement); - Microsoft::WRL::ComPtr CreateSeparator(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, UINT spacing, UINT separatorThickness, @@ -302,14 +290,6 @@ namespace AdaptiveNamespace::XamlHelpers _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, _Out_ ABI::AdaptiveNamespace::ContainerStyle* containerStyle); - void HandleSelectAction(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* adaptiveCardElement, - _In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* selectAction, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::Windows::UI::Xaml::IUIElement* uiElement, - bool supportsInteractivity, - bool fullWidthTouchTarget, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** outUiElement); - bool SupportsInteractivity(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig); template @@ -389,13 +369,6 @@ namespace AdaptiveNamespace::XamlHelpers } CATCH_RETURN; - HRESULT BuildActions(_In_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_ ABI::Windows::Foundation::Collections::IVector* children, - _In_ ABI::Windows::UI::Xaml::Controls::IPanel* bodyPanel, - bool insertSeparator, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs); - void AddSeparatorIfNeeded(int& currentElement, _In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* element, _In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, @@ -407,11 +380,4 @@ namespace AdaptiveNamespace::XamlHelpers _In_ IInspectable* parentElement, _In_ ABI::Windows::UI::Xaml::Media::Imaging::IBitmapSource* imageSource, bool setVisible); - - HRESULT BuildActionSetHelper(_In_opt_ ABI::AdaptiveNamespace::IAdaptiveCard* adaptiveCard, - _In_opt_ ABI::AdaptiveNamespace::IAdaptiveActionSet* adaptiveActionSet, - _In_ ABI::Windows::Foundation::Collections::IVector* children, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveRenderArgs* renderArgs, - _Outptr_ ABI::Windows::UI::Xaml::IUIElement** actionSetControl); } From 05aec670f7f6bb94e3f1b0654c9fa7c3c2209d90 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 15:09:50 -0700 Subject: [PATCH 10/16] Add missing RETURN_IF_FAILED in ActionHelpers.cpp --- source/uwp/Renderer/lib/ActionHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/uwp/Renderer/lib/ActionHelpers.cpp b/source/uwp/Renderer/lib/ActionHelpers.cpp index 59ce061a7a..8b6e91e9cb 100644 --- a/source/uwp/Renderer/lib/ActionHelpers.cpp +++ b/source/uwp/Renderer/lib/ActionHelpers.cpp @@ -317,7 +317,7 @@ namespace AdaptiveNamespace::ActionHelpers } ABI::AdaptiveNamespace::ContainerStyle containerStyle; - renderArgs->get_ContainerStyle(&containerStyle); + RETURN_IF_FAILED(renderArgs->get_ContainerStyle(&containerStyle)); boolean allowAboveTitleIconPlacement; RETURN_IF_FAILED(renderArgs->get_AllowAboveTitleIconPlacement(&allowAboveTitleIconPlacement)); From 23fec9895240338304bf3325067f3a1f8feb3317 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 15:14:07 -0700 Subject: [PATCH 11/16] Remove `_` from private method names in AdaptiveChoiceSetInputRenderer --- .../lib/AdaptiveChoiceSetInputRenderer.cpp | 21 +++++++++---------- .../lib/AdaptiveChoiceSetInputRenderer.h | 12 +++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp index 3e4d31be32..188bbb2575 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp @@ -17,11 +17,10 @@ using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { - HRESULT AdaptiveChoiceSetInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveChoiceSetInputRenderer::RuntimeClassInitialize() noexcept { return S_OK; } - CATCH_RETURN; HRESULT AdaptiveChoiceSetInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, @@ -50,11 +49,11 @@ namespace AdaptiveNamespace if (choiceSetStyle == ABI::AdaptiveNamespace::ChoiceSetStyle_Compact && !isMultiSelect) { - _BuildCompactChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), choiceInputSet); + BuildCompactChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), choiceInputSet); } else { - _BuildExpandedChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), isMultiSelect, choiceInputSet); + BuildExpandedChoiceSetInput(renderContext, adaptiveChoiceSetInput.Get(), isMultiSelect, choiceInputSet); } XamlHelpers::AddInputValueToContext(renderContext, adaptiveCardElement, *choiceInputSet); @@ -101,9 +100,9 @@ namespace AdaptiveNamespace return std::find(selectedValues.begin(), selectedValues.end(), stdValue) != selectedValues.end(); } - HRESULT AdaptiveChoiceSetInputRenderer::_BuildCompactChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - _COM_Outptr_ IUIElement** choiceInputSet) + HRESULT AdaptiveChoiceSetInputRenderer::BuildCompactChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + _COM_Outptr_ IUIElement** choiceInputSet) { ComPtr comboBox = XamlHelpers::CreateXamlClass(HStringReference(RuntimeClass_Windows_UI_Xaml_Controls_ComboBox)); @@ -170,10 +169,10 @@ namespace AdaptiveNamespace return comboBoxAsUIElement.CopyTo(choiceInputSet); } - HRESULT AdaptiveChoiceSetInputRenderer::_BuildExpandedChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - boolean isMultiSelect, - _COM_Outptr_ IUIElement** choiceInputSet) + HRESULT AdaptiveChoiceSetInputRenderer::BuildExpandedChoiceSetInput(_In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + boolean isMultiSelect, + _COM_Outptr_ IUIElement** choiceInputSet) { ComPtr> choices; RETURN_IF_FAILED(adaptiveChoiceSetInput->get_Choices(&choices)); diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h index 445f072666..81785cd869 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.h @@ -32,14 +32,14 @@ namespace AdaptiveNamespace static bool IsChoiceSelected(std::vector selectedValues, _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceInput* choice); - HRESULT _BuildExpandedChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, - _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, - boolean isMultiSelect, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSet); - - HRESULT _BuildCompactChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + HRESULT BuildExpandedChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + boolean isMultiSelect, _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSet); + + HRESULT BuildCompactChoiceSetInput(_In_ ABI::AdaptiveNamespace::IAdaptiveRenderContext* renderContext, + _In_ ABI::AdaptiveNamespace::IAdaptiveChoiceSetInput* adaptiveChoiceSetInput, + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** choiceInputSet); }; ActivatableClass(AdaptiveChoiceSetInputRenderer); From 62a00d6f153edc55287c1edf0714aedc3a450693 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 15:19:22 -0700 Subject: [PATCH 12/16] Move ApplyMarginToXamlElement to XamlHelpers --- source/uwp/Renderer/lib/XamlBuilder.cpp | 16 +--------------- source/uwp/Renderer/lib/XamlHelpers.cpp | 14 ++++++++++++++ source/uwp/Renderer/lib/XamlHelpers.h | 3 +++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/source/uwp/Renderer/lib/XamlBuilder.cpp b/source/uwp/Renderer/lib/XamlBuilder.cpp index 61bd5617ba..f19f66b1d3 100644 --- a/source/uwp/Renderer/lib/XamlBuilder.cpp +++ b/source/uwp/Renderer/lib/XamlBuilder.cpp @@ -216,20 +216,6 @@ namespace AdaptiveNamespace m_enableXamlImageHandling = enableXamlImageHandling; } - static HRESULT ApplyMarginToXamlElement(_In_ IAdaptiveHostConfig* hostConfig, _In_ IFrameworkElement* element) noexcept - { - ComPtr localElement(element); - ComPtr spacingConfig; - RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); - - UINT32 padding; - spacingConfig->get_Padding(&padding); - Thickness margin = {(double)padding, (double)padding, (double)padding, (double)padding}; - - RETURN_IF_FAILED(localElement->put_Margin(margin)); - return S_OK; - } - HRESULT XamlBuilder::CreateRootCardElement(_In_ IAdaptiveCard* adaptiveCard, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, @@ -289,7 +275,7 @@ namespace AdaptiveNamespace ComPtr bodyElementHostAsElement; RETURN_IF_FAILED(bodyElementHost.As(&bodyElementHostAsElement)); - RETURN_IF_FAILED(ApplyMarginToXamlElement(hostConfig.Get(), bodyElementHostAsElement.Get())); + RETURN_IF_FAILED(XamlHelpers::ApplyMarginToXamlElement(hostConfig.Get(), bodyElementHostAsElement.Get())); ABI::AdaptiveNamespace::HeightType adaptiveCardHeightType; RETURN_IF_FAILED(adaptiveCard->get_Height(&adaptiveCardHeightType)); diff --git a/source/uwp/Renderer/lib/XamlHelpers.cpp b/source/uwp/Renderer/lib/XamlHelpers.cpp index ff09a65562..49895322f8 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.cpp +++ b/source/uwp/Renderer/lib/XamlHelpers.cpp @@ -631,4 +631,18 @@ namespace AdaptiveNamespace::XamlHelpers } } } + + HRESULT ApplyMarginToXamlElement(_In_ IAdaptiveHostConfig* hostConfig, _In_ IFrameworkElement* element) noexcept + { + ComPtr localElement(element); + ComPtr spacingConfig; + RETURN_IF_FAILED(hostConfig->get_Spacing(&spacingConfig)); + + UINT32 padding; + spacingConfig->get_Padding(&padding); + Thickness margin = {(double)padding, (double)padding, (double)padding, (double)padding}; + + RETURN_IF_FAILED(localElement->put_Margin(margin)); + return S_OK; + } } diff --git a/source/uwp/Renderer/lib/XamlHelpers.h b/source/uwp/Renderer/lib/XamlHelpers.h index d02b0ced8b..5cd1df90b4 100644 --- a/source/uwp/Renderer/lib/XamlHelpers.h +++ b/source/uwp/Renderer/lib/XamlHelpers.h @@ -380,4 +380,7 @@ namespace AdaptiveNamespace::XamlHelpers _In_ IInspectable* parentElement, _In_ ABI::Windows::UI::Xaml::Media::Imaging::IBitmapSource* imageSource, bool setVisible); + + HRESULT ApplyMarginToXamlElement(_In_ ABI::AdaptiveNamespace::IAdaptiveHostConfig* hostConfig, + _In_ ABI::Windows::UI::Xaml::IFrameworkElement* element) noexcept; } From 41f9f2b996059edcd7b1fc3b499e93a4d44a4d87 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Thu, 19 Sep 2019 16:00:38 -0700 Subject: [PATCH 13/16] Missing RETURN_IF_FAILED --- source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp index cd501b5930..b2f0eb5d11 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp @@ -73,7 +73,7 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(localAdaptiveImage->put_Size(imageSize)); ComPtr adaptiveElementImage; - localAdaptiveImage.As(&adaptiveElementImage); + RETURN_IF_FAILED(localAdaptiveImage.As(&adaptiveElementImage)); RETURN_IF_FAILED(imageRenderer->Render(adaptiveElementImage.Get(), renderContext, childRenderArgs.Get(), &uiImage)); ComPtr imageAsFrameworkElement; From 78aae56b1e0f7c7775d6e8654bcf2e39e39cc0c1 Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Mon, 23 Sep 2019 14:00:19 -0700 Subject: [PATCH 14/16] Clean up padding negation --- source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp index ca725d0286..297d2f1c73 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp @@ -89,9 +89,10 @@ namespace AdaptiveNamespace UINT32 inlineTopMargin; RETURN_IF_FAILED(showCardActionConfig->get_InlineTopMargin(&inlineTopMargin)); - double sideMargin = (double)padding * -1; - double topMargin = isBottomActionBar ? inlineTopMargin + padding : inlineTopMargin; - double bottomMargin = isBottomActionBar ? (double)padding * -1 : 0; + const double negativePadding = -(static_cast(padding)); + const double sideMargin = negativePadding; + const double topMargin = isBottomActionBar ? inlineTopMargin + padding : inlineTopMargin; + const double bottomMargin = isBottomActionBar ? negativePadding : 0; Thickness margin = {sideMargin, topMargin, sideMargin, bottomMargin}; RETURN_IF_FAILED(showCardFrameworkElement->put_Margin(margin)); From 2206eda20ad1fbde955d0bedfa8758a6f36b6b7b Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Mon, 23 Sep 2019 14:27:38 -0700 Subject: [PATCH 15/16] Add more missing THROW_IF_FAILEDs --- source/uwp/Renderer/lib/ActionHelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/uwp/Renderer/lib/ActionHelpers.cpp b/source/uwp/Renderer/lib/ActionHelpers.cpp index 8b6e91e9cb..d15202ca09 100644 --- a/source/uwp/Renderer/lib/ActionHelpers.cpp +++ b/source/uwp/Renderer/lib/ActionHelpers.cpp @@ -76,8 +76,8 @@ namespace AdaptiveNamespace::ActionHelpers ComPtr adaptiveImage; THROW_IF_FAILED(MakeAndInitialize(&adaptiveImage)); - adaptiveImage->put_Url(iconUrl.Get()); - adaptiveImage->put_HorizontalAlignment(ABI::AdaptiveNamespace::HAlignment::Center); + THROW_IF_FAILED(adaptiveImage->put_Url(iconUrl.Get())); + THROW_IF_FAILED(adaptiveImage->put_HorizontalAlignment(ABI::AdaptiveNamespace::HAlignment::Center)); ComPtr adaptiveCardElement; THROW_IF_FAILED(adaptiveImage.As(&adaptiveCardElement)); From 1169ddf4c1497133c1610c597e43fa486b0d176d Mon Sep 17 00:00:00 2001 From: "Paul Campbell (DEP)" Date: Mon, 23 Sep 2019 14:29:42 -0700 Subject: [PATCH 16/16] Clang-format update --- .../Renderer/lib/AdaptiveActionElement.cpp | 10 +-- .../Renderer/lib/AdaptiveActionInvoker.cpp | 3 +- .../lib/AdaptiveActionParserRegistration.cpp | 12 ++- .../lib/AdaptiveActionParserRegistration.h | 2 +- .../AdaptiveActionRendererRegistration.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveActionSet.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveActionSet.h | 1 - .../Renderer/lib/AdaptiveActionsConfig.cpp | 3 +- .../Renderer/lib/AdaptiveBackgroundImage.cpp | 10 ++- source/uwp/Renderer/lib/AdaptiveCard.cpp | 14 +-- .../uwp/Renderer/lib/AdaptiveCardConfig.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveCardElement.h | 3 +- .../lib/AdaptiveCardRendererComponent.cpp | 3 +- .../lib/AdaptiveCardResourceResolvers.cpp | 3 +- .../uwp/Renderer/lib/AdaptiveChoiceInput.cpp | 3 +- .../Renderer/lib/AdaptiveChoiceSetInput.cpp | 9 +- .../lib/AdaptiveChoiceSetInputRenderer.cpp | 11 ++- .../uwp/Renderer/lib/AdaptiveColorConfig.cpp | 4 +- .../uwp/Renderer/lib/AdaptiveColorsConfig.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveColumn.cpp | 9 +- .../Renderer/lib/AdaptiveColumnRenderer.cpp | 11 ++- source/uwp/Renderer/lib/AdaptiveColumnSet.cpp | 9 +- .../lib/AdaptiveColumnSetRenderer.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveContainer.cpp | 9 +- .../lib/AdaptiveContainerRenderer.cpp | 6 +- .../lib/AdaptiveContainerStyleDefinition.cpp | 3 +- .../lib/AdaptiveContainerStylesDefinition.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveDateInput.cpp | 9 +- .../lib/AdaptiveDateInputRenderer.cpp | 9 +- .../lib/AdaptiveElementParserRegistration.cpp | 12 ++- .../AdaptiveElementRendererRegistration.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveFact.cpp | 6 +- source/uwp/Renderer/lib/AdaptiveFactSet.cpp | 9 +- .../Renderer/lib/AdaptiveFactSetConfig.cpp | 3 +- .../Renderer/lib/AdaptiveFactSetRenderer.cpp | 9 +- .../lib/AdaptiveFeatureRegistration.cpp | 15 ++-- .../Renderer/lib/AdaptiveFontSizesConfig.cpp | 3 +- .../lib/AdaptiveFontTypeDefinition.cpp | 8 +- .../lib/AdaptiveFontTypesDefinition.cpp | 3 +- .../lib/AdaptiveFontWeightsConfig.cpp | 3 +- .../lib/AdaptiveHighlightColorConfig.cpp | 3 +- .../uwp/Renderer/lib/AdaptiveHostConfig.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveImage.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveImageConfig.cpp | 3 +- .../Renderer/lib/AdaptiveImageRenderer.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveImageSet.cpp | 9 +- .../Renderer/lib/AdaptiveImageSetConfig.cpp | 3 +- .../Renderer/lib/AdaptiveImageSetRenderer.cpp | 16 ++-- .../Renderer/lib/AdaptiveImageSizesConfig.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveMedia.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveMedia.h | 20 ++++- .../uwp/Renderer/lib/AdaptiveMediaConfig.cpp | 3 +- .../lib/AdaptiveMediaEventInvoker.cpp | 3 +- .../Renderer/lib/AdaptiveMediaRenderer.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveMediaSource.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveNumberInput.cpp | 9 +- .../lib/AdaptiveNumberInputRenderer.cpp | 9 +- .../Renderer/lib/AdaptiveOpenUrlAction.cpp | 12 ++- .../uwp/Renderer/lib/AdaptiveOpenUrlAction.h | 10 +-- .../lib/AdaptiveOpenUrlActionRenderer.cpp | 9 +- .../lib/AdaptiveRemoteResourceInformation.cpp | 6 +- .../uwp/Renderer/lib/AdaptiveRenderArgs.cpp | 3 +- .../Renderer/lib/AdaptiveRenderContext.cpp | 3 +- .../Renderer/lib/AdaptiveRichTextBlock.cpp | 9 +- .../lib/AdaptiveRichTextBlockRenderer.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveSeparator.cpp | 3 +- .../Renderer/lib/AdaptiveSeparatorConfig.cpp | 6 +- .../Renderer/lib/AdaptiveShowCardAction.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveShowCardAction.h | 10 +-- .../lib/AdaptiveShowCardActionConfig.cpp | 3 +- .../lib/AdaptiveShowCardActionRenderer.cpp | 15 ++-- .../Renderer/lib/AdaptiveSpacingConfig.cpp | 6 +- .../uwp/Renderer/lib/AdaptiveSubmitAction.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveSubmitAction.h | 10 +-- .../lib/AdaptiveSubmitActionRenderer.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveTextBlock.cpp | 9 +- .../lib/AdaptiveTextBlockRenderer.cpp | 9 +- .../uwp/Renderer/lib/AdaptiveTextConfig.cpp | 3 +- source/uwp/Renderer/lib/AdaptiveTextElement.h | 5 +- source/uwp/Renderer/lib/AdaptiveTextInput.cpp | 9 +- .../lib/AdaptiveTextInputRenderer.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveTextRun.cpp | 9 +- source/uwp/Renderer/lib/AdaptiveTimeInput.cpp | 9 +- .../lib/AdaptiveTimeInputRenderer.cpp | 11 ++- .../uwp/Renderer/lib/AdaptiveToggleInput.cpp | 9 +- .../lib/AdaptiveToggleInputRenderer.cpp | 9 +- .../lib/AdaptiveToggleVisibilityAction.cpp | 10 ++- .../lib/AdaptiveToggleVisibilityAction.h | 10 +-- ...AdaptiveToggleVisibilityActionRenderer.cpp | 9 +- .../lib/AdaptiveToggleVisibilityTarget.cpp | 6 +- .../lib/AdaptiveUnsupportedAction.cpp | 9 +- .../Renderer/lib/AdaptiveUnsupportedAction.h | 10 +-- .../lib/AdaptiveUnsupportedElement.cpp | 9 +- source/uwp/Renderer/lib/AsyncOperations.h | 9 +- .../Renderer/lib/DefaultResourceDictionary.h | 3 +- source/uwp/Renderer/lib/ElementTagContent.h | 7 +- source/uwp/Renderer/lib/ImageLoadTracker.cpp | 6 +- source/uwp/Renderer/lib/MediaHelpers.cpp | 3 +- source/uwp/Renderer/lib/TextHelpers.cpp | 6 +- source/uwp/Renderer/lib/TextHelpers.h | 15 ++-- source/uwp/Renderer/lib/TileControl.cpp | 3 +- source/uwp/Renderer/lib/TileControl.h | 5 +- source/uwp/Renderer/lib/Util.cpp | 90 ++++++++++++------- source/uwp/Renderer/lib/WholeItemsPanel.h | 1 - source/uwp/Renderer/lib/XamlBuilder.cpp | 18 ++-- 105 files changed, 521 insertions(+), 329 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveActionElement.cpp b/source/uwp/Renderer/lib/AdaptiveActionElement.cpp index bb4a2cb7dc..fc41757084 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionElement.cpp @@ -78,15 +78,9 @@ namespace AdaptiveNamespace HRESULT AdaptiveActionElementBase::put_IconUrl(_In_ HSTRING iconUrl) { return m_iconUrl.Set(iconUrl); } - IFACEMETHODIMP AdaptiveActionElementBase::get_Style(_Outptr_ HSTRING* style) - { - return m_style.CopyTo(style); - } + IFACEMETHODIMP AdaptiveActionElementBase::get_Style(_Outptr_ HSTRING* style) { return m_style.CopyTo(style); } - IFACEMETHODIMP AdaptiveActionElementBase::put_Style(_In_ HSTRING style) - { - return m_style.Set(style); - } + IFACEMETHODIMP AdaptiveActionElementBase::put_Style(_In_ HSTRING style) { return m_style.Set(style); } IFACEMETHODIMP AdaptiveActionElementBase::get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveActionInvoker.cpp b/source/uwp/Renderer/lib/AdaptiveActionInvoker.cpp index c98d39c2fc..53589cd586 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionInvoker.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionInvoker.cpp @@ -15,7 +15,8 @@ namespace AdaptiveNamespace { HRESULT AdaptiveActionInvoker::RuntimeClassInitialize() noexcept { return S_OK; } - HRESULT AdaptiveActionInvoker::RuntimeClassInitialize(_In_ RenderedAdaptiveCard* renderResult) noexcept try + HRESULT AdaptiveActionInvoker::RuntimeClassInitialize(_In_ RenderedAdaptiveCard* renderResult) noexcept + try { ComPtr strongRenderResult = renderResult; return strongRenderResult.AsWeak(&m_weakRenderResult); diff --git a/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.cpp b/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.cpp index 8b17c39448..20dad1186d 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.cpp @@ -20,7 +20,8 @@ namespace AdaptiveNamespace { AdaptiveActionParserRegistration::AdaptiveActionParserRegistration() {} - HRESULT AdaptiveActionParserRegistration::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveActionParserRegistration::RuntimeClassInitialize() noexcept + try { m_registration = std::make_shared(); m_sharedParserRegistration = std::make_shared(); @@ -38,7 +39,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveActionParserRegistration::Set(_In_ HSTRING type, _In_ IAdaptiveActionParser* Parser) noexcept try + HRESULT AdaptiveActionParserRegistration::Set(_In_ HSTRING type, _In_ IAdaptiveActionParser* Parser) noexcept + try { std::string typeString = HStringToUTF8(type); @@ -56,7 +58,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveActionParserRegistration::Get(_In_ HSTRING type, _COM_Outptr_ IAdaptiveActionParser** result) noexcept try + HRESULT AdaptiveActionParserRegistration::Get(_In_ HSTRING type, _COM_Outptr_ IAdaptiveActionParser** result) noexcept + try { *result = nullptr; @@ -69,7 +72,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveActionParserRegistration::Remove(_In_ HSTRING type) noexcept try + HRESULT AdaptiveActionParserRegistration::Remove(_In_ HSTRING type) noexcept + try { std::string typeString = HStringToUTF8(type); diff --git a/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.h b/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.h index d2d5f34865..0a7527bce4 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.h +++ b/source/uwp/Renderer/lib/AdaptiveActionParserRegistration.h @@ -3,7 +3,7 @@ #pragma once #include "AdaptiveCards.Rendering.Uwp.h" - + namespace AdaptiveNamespace { constexpr char* c_upwActionParserRegistration = "AB3CC8B0-FF27-4859-A2AA-BCE2E729805"; diff --git a/source/uwp/Renderer/lib/AdaptiveActionRendererRegistration.cpp b/source/uwp/Renderer/lib/AdaptiveActionRendererRegistration.cpp index e60a991411..daae972226 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionRendererRegistration.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionRendererRegistration.cpp @@ -12,7 +12,8 @@ namespace AdaptiveNamespace { AdaptiveActionRendererRegistration::AdaptiveActionRendererRegistration() {} - HRESULT AdaptiveActionRendererRegistration::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveActionRendererRegistration::RuntimeClassInitialize() noexcept + try { m_registration = std::make_shared(); return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp index fb2a48c753..d2d0241c60 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.cpp @@ -14,7 +14,8 @@ namespace AdaptiveNamespace { AdaptiveActionSet::AdaptiveActionSet() { m_actions = Microsoft::WRL::Make>(); } - HRESULT AdaptiveActionSet::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveActionSet::RuntimeClassInitialize() noexcept + try { std::shared_ptr ActionSet = std::make_shared(); return RuntimeClassInitialize(ActionSet); diff --git a/source/uwp/Renderer/lib/AdaptiveActionSet.h b/source/uwp/Renderer/lib/AdaptiveActionSet.h index c99396cdc0..c130987536 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionSet.h +++ b/source/uwp/Renderer/lib/AdaptiveActionSet.h @@ -105,7 +105,6 @@ namespace AdaptiveNamespace return AdaptiveCardElementBase::get_Requirements(requirements); } - IFACEMETHODIMP ToJson(_Out_ ABI::Windows::Data::Json::IJsonObject** result) { return AdaptiveCardElementBase::ToJson(result); diff --git a/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp b/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp index 44d58168fc..69329cccc1 100644 --- a/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveActionsConfig.cpp @@ -10,7 +10,8 @@ using namespace ABI::Windows::UI; namespace AdaptiveNamespace { - HRESULT AdaptiveActionsConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveActionsConfig::RuntimeClassInitialize() noexcept + try { ActionsConfig actionsConfig; return RuntimeClassInitialize(actionsConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveBackgroundImage.cpp b/source/uwp/Renderer/lib/AdaptiveBackgroundImage.cpp index 8d113a3855..3b96b4b471 100644 --- a/source/uwp/Renderer/lib/AdaptiveBackgroundImage.cpp +++ b/source/uwp/Renderer/lib/AdaptiveBackgroundImage.cpp @@ -16,7 +16,8 @@ namespace AdaptiveNamespace { AdaptiveBackgroundImage::AdaptiveBackgroundImage() {} - HRESULT AdaptiveBackgroundImage::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveBackgroundImage::RuntimeClassInitialize() noexcept + try { std::shared_ptr image = std::make_shared(); @@ -24,8 +25,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveBackgroundImage::RuntimeClassInitialize( - const std::shared_ptr& sharedImage) try + HRESULT AdaptiveBackgroundImage::RuntimeClassInitialize(const std::shared_ptr& sharedImage) + try { if (sharedImage == nullptr) { @@ -85,7 +86,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveBackgroundImage::GetSharedModel(std::shared_ptr& sharedImage) try + HRESULT AdaptiveBackgroundImage::GetSharedModel(std::shared_ptr& sharedImage) + try { std::shared_ptr image = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveCard.cpp b/source/uwp/Renderer/lib/AdaptiveCard.cpp index 15956f3ec0..7985b54a0a 100644 --- a/source/uwp/Renderer/lib/AdaptiveCard.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCard.cpp @@ -25,8 +25,8 @@ using namespace Microsoft::WRL::Wrappers; namespace AdaptiveNamespace { - HRESULT AdaptiveCardStaticsImpl::FromJsonString(_In_ HSTRING adaptiveJson, - _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept try + HRESULT AdaptiveCardStaticsImpl::FromJsonString(_In_ HSTRING adaptiveJson, _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept + try { return FromJsonStringWithParserRegistration(adaptiveJson, nullptr, nullptr, parseResult); } @@ -35,7 +35,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveCardStaticsImpl::FromJsonStringWithParserRegistration(_In_ HSTRING adaptiveJson, _In_ IAdaptiveElementParserRegistration* elementParserRegistration, _In_ IAdaptiveActionParserRegistration* actionParserRegistration, - _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept try + _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept + try { *parseResult = nullptr; @@ -46,8 +47,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveCardStaticsImpl::FromJson(_In_ IJsonObject* adaptiveJson, - _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept try + HRESULT AdaptiveCardStaticsImpl::FromJson(_In_ IJsonObject* adaptiveJson, _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept + try { return FromJsonWithParserRegistration(adaptiveJson, nullptr, nullptr, parseResult); } @@ -56,7 +57,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveCardStaticsImpl::FromJsonWithParserRegistration(_In_ IJsonObject* adaptiveJson, _In_ IAdaptiveElementParserRegistration* elementParserRegistration, _In_ IAdaptiveActionParserRegistration* actionParserRegistration, - _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept try + _COM_Outptr_ IAdaptiveCardParseResult** parseResult) noexcept + try { *parseResult = nullptr; diff --git a/source/uwp/Renderer/lib/AdaptiveCardConfig.cpp b/source/uwp/Renderer/lib/AdaptiveCardConfig.cpp index be46cf9486..2cbe57176a 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCardConfig.cpp @@ -10,7 +10,8 @@ using namespace ABI::Windows::UI; namespace AdaptiveNamespace { - HRESULT AdaptiveCardConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveCardConfig::RuntimeClassInitialize() noexcept + try { AdaptiveSharedNamespace::AdaptiveCardConfig cardConfig; return RuntimeClassInitialize(cardConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveCardElement.h b/source/uwp/Renderer/lib/AdaptiveCardElement.h index 55da085639..15c2fecb87 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardElement.h +++ b/source/uwp/Renderer/lib/AdaptiveCardElement.h @@ -40,7 +40,8 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_Height(_Out_ ABI::AdaptiveNamespace::HeightType* height); IFACEMETHODIMP put_Height(ABI::AdaptiveNamespace::HeightType height); - IFACEMETHODIMP get_Requirements(_COM_Outptr_ ABI::Windows::Foundation::Collections::IVector** requirements); + IFACEMETHODIMP get_Requirements( + _COM_Outptr_ ABI::Windows::Foundation::Collections::IVector** requirements); IFACEMETHODIMP ToJson(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result); diff --git a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp index b5cea88ad6..e5d536bd53 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCardRendererComponent.cpp @@ -53,7 +53,8 @@ using namespace ABI::Windows::UI::Xaml::Media::Imaging; namespace AdaptiveNamespace { - HRESULT AdaptiveCardRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveCardRenderer::RuntimeClassInitialize() noexcept + try { RETURN_IF_FAILED(MakeAndInitialize(&m_xamlBuilder)); RETURN_IF_FAILED(MakeAndInitialize(&m_elementRendererRegistration)); diff --git a/source/uwp/Renderer/lib/AdaptiveCardResourceResolvers.cpp b/source/uwp/Renderer/lib/AdaptiveCardResourceResolvers.cpp index 3ae7b66045..1ef1cf1b26 100644 --- a/source/uwp/Renderer/lib/AdaptiveCardResourceResolvers.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCardResourceResolvers.cpp @@ -9,7 +9,8 @@ using namespace ABI::Windows::Foundation; namespace AdaptiveNamespace { - HRESULT AdaptiveCardResourceResolvers::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveCardResourceResolvers::RuntimeClassInitialize() noexcept + try { return S_OK; } diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceInput.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceInput.cpp index 3cba8f7608..ab7a42df3c 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceInput.cpp @@ -14,7 +14,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveChoiceInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveChoiceInput::RuntimeClassInitialize() noexcept + try { m_sharedChoiceInput = std::make_shared(); return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.cpp index edb996cad8..8e2afc9809 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.cpp @@ -21,7 +21,8 @@ namespace AdaptiveNamespace m_choices = Microsoft::WRL::Make>(); } - HRESULT AdaptiveChoiceSetInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveChoiceSetInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr choiceSet = std::make_shared(); @@ -29,7 +30,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveChoiceSetInput::RuntimeClassInitialize(const std::shared_ptr& sharedChoiceSetInput) try + HRESULT AdaptiveChoiceSetInput::RuntimeClassInitialize(const std::shared_ptr& sharedChoiceSetInput) + try { if (sharedChoiceSetInput == nullptr) { @@ -107,7 +109,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveChoiceSetInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveChoiceSetInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr choiceSet = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp index 188bbb2575..e092ba463d 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInputRenderer.cpp @@ -17,15 +17,13 @@ using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { - HRESULT AdaptiveChoiceSetInputRenderer::RuntimeClassInitialize() noexcept - { - return S_OK; - } + HRESULT AdaptiveChoiceSetInputRenderer::RuntimeClassInitialize() noexcept { return S_OK; } HRESULT AdaptiveChoiceSetInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** choiceInputSet) noexcept try + _COM_Outptr_ IUIElement** choiceInputSet) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -66,7 +64,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveColorConfig.cpp b/source/uwp/Renderer/lib/AdaptiveColorConfig.cpp index 9a8609182b..4fb9dc2aed 100644 --- a/source/uwp/Renderer/lib/AdaptiveColorConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColorConfig.cpp @@ -11,7 +11,8 @@ using namespace ABI::Windows::UI; namespace AdaptiveNamespace { - HRESULT AdaptiveColorConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColorConfig::RuntimeClassInitialize() noexcept + try { ColorConfig colorConfig; return RuntimeClassInitialize(colorConfig); @@ -57,7 +58,6 @@ namespace AdaptiveNamespace return m_highlightColors.CopyTo(highlightColors); } - HRESULT AdaptiveColorConfig::put_HighlightColors(_In_ IAdaptiveHighlightColorConfig* highlightColors) { m_highlightColors = highlightColors; diff --git a/source/uwp/Renderer/lib/AdaptiveColorsConfig.cpp b/source/uwp/Renderer/lib/AdaptiveColorsConfig.cpp index 966996f8fa..e1f8db2f78 100644 --- a/source/uwp/Renderer/lib/AdaptiveColorsConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColorsConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveColorsConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColorsConfig::RuntimeClassInitialize() noexcept + try { ColorsConfig colorsConfig; return RuntimeClassInitialize(colorsConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveColumn.cpp b/source/uwp/Renderer/lib/AdaptiveColumn.cpp index 3b2c458170..562e2fb8ab 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumn.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumn.cpp @@ -21,14 +21,16 @@ namespace AdaptiveNamespace m_items = Microsoft::WRL::Make>(); } - HRESULT AdaptiveColumn::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColumn::RuntimeClassInitialize() noexcept + try { std::shared_ptr column = std::make_shared(); return RuntimeClassInitialize(column); } CATCH_RETURN; - HRESULT AdaptiveColumn::RuntimeClassInitialize(const std::shared_ptr& sharedColumn) try + HRESULT AdaptiveColumn::RuntimeClassInitialize(const std::shared_ptr& sharedColumn) + try { GenerateContainedElementsProjection(sharedColumn->GetItems(), m_items.Get()); GenerateActionProjection(sharedColumn->GetSelectAction(), &m_selectAction); @@ -157,7 +159,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveColumn::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveColumn::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr column = std::make_shared(); RETURN_IF_FAILED(SetSharedElementProperties(std::static_pointer_cast(column))); diff --git a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp index 746420bf6b..08f075a77d 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnRenderer.cpp @@ -19,15 +19,13 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveColumnRenderer::RuntimeClassInitialize() noexcept - { - return S_OK; - } + HRESULT AdaptiveColumnRenderer::RuntimeClassInitialize() noexcept { return S_OK; } HRESULT AdaptiveColumnRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** ColumnControl) noexcept try + _COM_Outptr_ IUIElement** ColumnControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveColumn; @@ -138,7 +136,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSet.cpp b/source/uwp/Renderer/lib/AdaptiveColumnSet.cpp index e6a3f5affb..651ec40808 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnSet.cpp @@ -23,14 +23,16 @@ namespace AdaptiveNamespace m_columns = Microsoft::WRL::Make>(); } - HRESULT AdaptiveColumnSet::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColumnSet::RuntimeClassInitialize() noexcept + try { std::shared_ptr columnSet = std::make_shared(); return RuntimeClassInitialize(columnSet); } CATCH_RETURN; - HRESULT AdaptiveColumnSet::RuntimeClassInitialize(const std::shared_ptr& sharedColumnSet) noexcept try + HRESULT AdaptiveColumnSet::RuntimeClassInitialize(const std::shared_ptr& sharedColumnSet) noexcept + try { if (sharedColumnSet == nullptr) { @@ -117,7 +119,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveColumnSet::GetSharedModel(std::shared_ptr& sharedModel) noexcept try + HRESULT AdaptiveColumnSet::GetSharedModel(std::shared_ptr& sharedModel) noexcept + try { std::shared_ptr columnSet = std::make_shared(); RETURN_IF_FAILED(SetSharedElementProperties(std::static_pointer_cast(columnSet))); diff --git a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp index c94cb0d4a4..24aa990d89 100644 --- a/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveColumnSetRenderer.cpp @@ -19,7 +19,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveColumnSetRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveColumnSetRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -28,7 +29,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveColumnSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** columnSetControl) noexcept try + _COM_Outptr_ IUIElement** columnSetControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveColumnSet; @@ -231,7 +233,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveContainer.cpp b/source/uwp/Renderer/lib/AdaptiveContainer.cpp index f326b8851b..e90022c92c 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainer.cpp @@ -21,14 +21,16 @@ namespace AdaptiveNamespace m_items = Microsoft::WRL::Make>(); } - HRESULT AdaptiveContainer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveContainer::RuntimeClassInitialize() noexcept + try { std::shared_ptr container = std::make_shared(); return RuntimeClassInitialize(container); } CATCH_RETURN; - HRESULT AdaptiveContainer::RuntimeClassInitialize(const std::shared_ptr& sharedContainer) try + HRESULT AdaptiveContainer::RuntimeClassInitialize(const std::shared_ptr& sharedContainer) + try { if (sharedContainer == nullptr) { @@ -144,7 +146,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveContainer::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveContainer::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr container = std::make_shared(); RETURN_IF_FAILED(SetSharedElementProperties(std::static_pointer_cast(container))); diff --git a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp index 906188a9aa..fcdf0f2feb 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerRenderer.cpp @@ -24,7 +24,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveContainerRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** containerControl) noexcept try + _COM_Outptr_ IUIElement** containerControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveContainer; @@ -140,7 +141,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.cpp index b686bad0d7..b926a64cf9 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerStyleDefinition.cpp @@ -9,7 +9,8 @@ using namespace Microsoft::WRL::Wrappers; namespace AdaptiveNamespace { - HRESULT AdaptiveContainerStyleDefinition::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveContainerStyleDefinition::RuntimeClassInitialize() noexcept + try { ContainerStyleDefinition styleDefinition; return RuntimeClassInitialize(styleDefinition); diff --git a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp index b89b30f5fa..5076431666 100644 --- a/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveContainerStylesDefinition.cpp @@ -11,7 +11,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveContainerStylesDefinition::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveContainerStylesDefinition::RuntimeClassInitialize() noexcept + try { ContainerStylesDefinition stylesDefinition; return RuntimeClassInitialize(stylesDefinition); diff --git a/source/uwp/Renderer/lib/AdaptiveDateInput.cpp b/source/uwp/Renderer/lib/AdaptiveDateInput.cpp index 86b06dcacf..e199a82fff 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveDateInput.cpp @@ -14,14 +14,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveDateInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveDateInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr dateInput = std::make_shared(); return RuntimeClassInitialize(dateInput); } CATCH_RETURN; - HRESULT AdaptiveDateInput::RuntimeClassInitialize(const std::shared_ptr& sharedDateInput) try + HRESULT AdaptiveDateInput::RuntimeClassInitialize(const std::shared_ptr& sharedDateInput) + try { if (sharedDateInput == nullptr) { @@ -63,7 +65,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveDateInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveDateInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr dateInput = std::make_shared(); RETURN_IF_FAILED(SetSharedElementProperties(std::static_pointer_cast(dateInput))); diff --git a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp index 7ef8394a92..f9527f30d2 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveDateInputRenderer.cpp @@ -16,7 +16,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveDateInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveDateInputRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -25,7 +26,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveDateInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** dateInputControl) noexcept try + _COM_Outptr_ IUIElement** dateInputControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -119,7 +121,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveElementParserRegistration.cpp b/source/uwp/Renderer/lib/AdaptiveElementParserRegistration.cpp index 4c47592ef4..ebe5e35e17 100644 --- a/source/uwp/Renderer/lib/AdaptiveElementParserRegistration.cpp +++ b/source/uwp/Renderer/lib/AdaptiveElementParserRegistration.cpp @@ -35,7 +35,8 @@ namespace AdaptiveNamespace { AdaptiveElementParserRegistration::AdaptiveElementParserRegistration() {} - HRESULT AdaptiveElementParserRegistration::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveElementParserRegistration::RuntimeClassInitialize() noexcept + try { m_registration = std::make_shared(); m_sharedParserRegistration = std::make_shared(); @@ -52,7 +53,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveElementParserRegistration::Set(_In_ HSTRING type, _In_ IAdaptiveElementParser* Parser) noexcept try + HRESULT AdaptiveElementParserRegistration::Set(_In_ HSTRING type, _In_ IAdaptiveElementParser* Parser) noexcept + try { std::string typeString = HStringToUTF8(type); @@ -70,7 +72,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveElementParserRegistration::Get(_In_ HSTRING type, _COM_Outptr_ IAdaptiveElementParser** result) noexcept try + HRESULT AdaptiveElementParserRegistration::Get(_In_ HSTRING type, _COM_Outptr_ IAdaptiveElementParser** result) noexcept + try { *result = nullptr; @@ -83,7 +86,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveElementParserRegistration::Remove(_In_ HSTRING type) noexcept try + HRESULT AdaptiveElementParserRegistration::Remove(_In_ HSTRING type) noexcept + try { std::string typeString = HStringToUTF8(type); diff --git a/source/uwp/Renderer/lib/AdaptiveElementRendererRegistration.cpp b/source/uwp/Renderer/lib/AdaptiveElementRendererRegistration.cpp index 21d3cff158..a43e635108 100644 --- a/source/uwp/Renderer/lib/AdaptiveElementRendererRegistration.cpp +++ b/source/uwp/Renderer/lib/AdaptiveElementRendererRegistration.cpp @@ -12,7 +12,8 @@ namespace AdaptiveNamespace { AdaptiveElementRendererRegistration::AdaptiveElementRendererRegistration() {} - HRESULT AdaptiveElementRendererRegistration::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveElementRendererRegistration::RuntimeClassInitialize() noexcept + try { m_registration = std::make_shared(); return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveFact.cpp b/source/uwp/Renderer/lib/AdaptiveFact.cpp index e25eade52f..98e3530952 100644 --- a/source/uwp/Renderer/lib/AdaptiveFact.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFact.cpp @@ -13,7 +13,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveFact::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFact::RuntimeClassInitialize() noexcept + try { RuntimeClassInitialize(std::make_shared()); return S_OK; @@ -46,7 +47,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveFact::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveFact::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr fact = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveFactSet.cpp b/source/uwp/Renderer/lib/AdaptiveFactSet.cpp index 96c3f86a43..b6c9579ffc 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFactSet.cpp @@ -18,14 +18,16 @@ namespace AdaptiveNamespace { AdaptiveFactSet::AdaptiveFactSet() { m_facts = Microsoft::WRL::Make>(); } - HRESULT AdaptiveFactSet::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFactSet::RuntimeClassInitialize() noexcept + try { std::shared_ptr factSet = std::make_shared(); return RuntimeClassInitialize(factSet); } CATCH_RETURN; - HRESULT AdaptiveFactSet::RuntimeClassInitialize(const std::shared_ptr& sharedFactSet) try + HRESULT AdaptiveFactSet::RuntimeClassInitialize(const std::shared_ptr& sharedFactSet) + try { if (sharedFactSet == nullptr) { @@ -50,7 +52,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveFactSet::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveFactSet::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr factSet = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp index d7a5e65aa6..e87ea8ce5e 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFactSetConfig.cpp @@ -10,7 +10,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveFactSetConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFactSetConfig::RuntimeClassInitialize() noexcept + try { FactSetConfig factSetConfig; return RuntimeClassInitialize(factSetConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp index 419a5b10de..982837ed55 100644 --- a/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFactSetRenderer.cpp @@ -27,7 +27,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveFactSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** factSetControl) noexcept try + _COM_Outptr_ IUIElement** factSetControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveFactSet; @@ -150,7 +151,8 @@ namespace AdaptiveNamespace ComPtr factSetAsFrameworkElement; RETURN_IF_FAILED(xamlGrid.As(&factSetAsFrameworkElement)); - RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.FactSet", factSetAsFrameworkElement.Get())); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.FactSet", factSetAsFrameworkElement.Get())); return xamlGrid.CopyTo(factSetControl); } @@ -161,7 +163,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveFeatureRegistration.cpp b/source/uwp/Renderer/lib/AdaptiveFeatureRegistration.cpp index b2b7456cc7..9dd6b3b7ff 100644 --- a/source/uwp/Renderer/lib/AdaptiveFeatureRegistration.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFeatureRegistration.cpp @@ -12,28 +12,32 @@ namespace AdaptiveNamespace { AdaptiveFeatureRegistration::AdaptiveFeatureRegistration() {} - HRESULT AdaptiveFeatureRegistration::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFeatureRegistration::RuntimeClassInitialize() noexcept + try { std::shared_ptr sharedParserRegistration = std::make_shared(); return RuntimeClassInitialize(sharedParserRegistration); } CATCH_RETURN; - HRESULT AdaptiveFeatureRegistration::RuntimeClassInitialize(std::shared_ptr sharedParserRegistration) noexcept try + HRESULT AdaptiveFeatureRegistration::RuntimeClassInitialize(std::shared_ptr sharedParserRegistration) noexcept + try { m_sharedFeatureRegistration = sharedParserRegistration; return S_OK; } CATCH_RETURN; - HRESULT AdaptiveFeatureRegistration::Set(_In_ HSTRING name, _In_ HSTRING version) noexcept try + HRESULT AdaptiveFeatureRegistration::Set(_In_ HSTRING name, _In_ HSTRING version) noexcept + try { m_sharedFeatureRegistration->AddFeature(HStringToUTF8(name), HStringToUTF8(version)); return S_OK; } CATCH_RETURN; - HRESULT AdaptiveFeatureRegistration::Get(_In_ HSTRING name, _Outptr_ HSTRING* version) noexcept try + HRESULT AdaptiveFeatureRegistration::Get(_In_ HSTRING name, _Outptr_ HSTRING* version) noexcept + try { *version = nullptr; const std::string featureVersion = m_sharedFeatureRegistration->GetFeatureVersion(HStringToUTF8(name)); @@ -42,7 +46,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveFeatureRegistration::Remove(_In_ HSTRING name) noexcept try + HRESULT AdaptiveFeatureRegistration::Remove(_In_ HSTRING name) noexcept + try { m_sharedFeatureRegistration->RemoveFeature(HStringToUTF8(name)); diff --git a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp index f6ec36af9c..bfc8640c9b 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontSizesConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveFontSizesConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFontSizesConfig::RuntimeClassInitialize() noexcept + try { FontSizesConfig fontSizesConfig; return RuntimeClassInitialize(fontSizesConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp index fc2e3f058a..2fbce011f4 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontTypeDefinition.cpp @@ -11,7 +11,8 @@ using namespace Microsoft::WRL::Wrappers; namespace AdaptiveNamespace { - HRESULT AdaptiveFontTypeDefinition::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFontTypeDefinition::RuntimeClassInitialize() noexcept + try { FontTypeDefinition typeDefinition; return RuntimeClassInitialize(typeDefinition); @@ -28,10 +29,7 @@ namespace AdaptiveNamespace HRESULT AdaptiveFontTypeDefinition::get_FontFamily(_Outptr_ HSTRING* value) { return m_fontFamily.CopyTo(value); } - HRESULT AdaptiveFontTypeDefinition::put_FontFamily(_In_ HSTRING fontFamily) - { - return m_fontFamily.Set(fontFamily); - } + HRESULT AdaptiveFontTypeDefinition::put_FontFamily(_In_ HSTRING fontFamily) { return m_fontFamily.Set(fontFamily); } HRESULT AdaptiveFontTypeDefinition::get_FontWeights(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveFontWeightsConfig** weightsConfig) { diff --git a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp index e71d1f8e4b..2b1a36c389 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontTypesDefinition.cpp @@ -10,7 +10,8 @@ using namespace Microsoft::WRL::Wrappers; namespace AdaptiveNamespace { - HRESULT AdaptiveFontTypesDefinition::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFontTypesDefinition::RuntimeClassInitialize() noexcept + try { FontTypesDefinition stylesDefinition; return RuntimeClassInitialize(stylesDefinition); diff --git a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp index 86e07ecf33..57a6fa692d 100644 --- a/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveFontWeightsConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveFontWeightsConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveFontWeightsConfig::RuntimeClassInitialize() noexcept + try { FontWeightsConfig fontWeightsConfig; return RuntimeClassInitialize(fontWeightsConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp index cb264d0a69..41ef529c6f 100644 --- a/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveHighlightColorConfig.cpp @@ -10,7 +10,8 @@ using namespace ABI::Windows::UI; namespace AdaptiveNamespace { - HRESULT AdaptiveHighlightColorConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveHighlightColorConfig::RuntimeClassInitialize() noexcept + try { HighlightColorConfig colorConfig; return RuntimeClassInitialize(colorConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp b/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp index 3a50dcff50..5996827955 100644 --- a/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveHostConfig.cpp @@ -27,7 +27,8 @@ using namespace ABI::Windows::Data::Json; namespace AdaptiveNamespace { HRESULT AdaptiveHostConfigStaticsImpl::FromJsonString(_In_ HSTRING adaptiveJson, - _COM_Outptr_ IAdaptiveHostConfigParseResult** parseResult) noexcept try + _COM_Outptr_ IAdaptiveHostConfigParseResult** parseResult) noexcept + try { *parseResult = nullptr; @@ -38,7 +39,8 @@ namespace AdaptiveNamespace CATCH_RETURN; HRESULT AdaptiveHostConfigStaticsImpl::FromJson(_In_ IJsonObject* adaptiveJson, - _COM_Outptr_ IAdaptiveHostConfigParseResult** parseResult) noexcept try + _COM_Outptr_ IAdaptiveHostConfigParseResult** parseResult) noexcept + try { *parseResult = nullptr; @@ -61,7 +63,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveHostConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveHostConfig::RuntimeClassInitialize() noexcept + try { HostConfig sharedHostConfig; return RuntimeClassInitialize(sharedHostConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveImage.cpp b/source/uwp/Renderer/lib/AdaptiveImage.cpp index a25add3e5b..04523e2fda 100644 --- a/source/uwp/Renderer/lib/AdaptiveImage.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImage.cpp @@ -15,14 +15,16 @@ namespace AdaptiveNamespace { AdaptiveImage::AdaptiveImage() {} - HRESULT AdaptiveImage::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImage::RuntimeClassInitialize() noexcept + try { std::shared_ptr image = std::make_shared(); return RuntimeClassInitialize(image); } CATCH_RETURN; - HRESULT AdaptiveImage::RuntimeClassInitialize(const std::shared_ptr& sharedImage) try + HRESULT AdaptiveImage::RuntimeClassInitialize(const std::shared_ptr& sharedImage) + try { if (sharedImage == nullptr) { @@ -141,7 +143,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveImage::GetSharedModel(std::shared_ptr& sharedImage) try + HRESULT AdaptiveImage::GetSharedModel(std::shared_ptr& sharedImage) + try { std::shared_ptr image = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp index 09ef8a7bf5..455436a151 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveImageConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageConfig::RuntimeClassInitialize() noexcept + try { ImageConfig imageConfig; return RuntimeClassInitialize(imageConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index f739382011..da587e3452 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -41,7 +41,8 @@ namespace AdaptiveNamespace AdaptiveImageRenderer::AdaptiveImageRenderer(ComPtr xamlBuilder) : m_xamlBuilder(xamlBuilder) {} - HRESULT AdaptiveImageRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageRenderer::RuntimeClassInitialize() noexcept + try { RETURN_IF_FAILED(MakeAndInitialize(&m_xamlBuilder)); return S_OK; @@ -51,7 +52,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveImageRenderer::Render(_In_ IAdaptiveCardElement* cardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { return m_xamlBuilder->BuildImage(cardElement, renderContext, renderArgs, result); } @@ -62,7 +64,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveImageSet.cpp b/source/uwp/Renderer/lib/AdaptiveImageSet.cpp index b3617ae48d..750edc7061 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSet.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSet.cpp @@ -15,14 +15,16 @@ namespace AdaptiveNamespace { AdaptiveImageSet::AdaptiveImageSet() { m_images = Microsoft::WRL::Make>(); } - HRESULT AdaptiveImageSet::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageSet::RuntimeClassInitialize() noexcept + try { std::shared_ptr imageSet = std::make_shared(); return RuntimeClassInitialize(imageSet); } CATCH_RETURN; - HRESULT AdaptiveImageSet::RuntimeClassInitialize(const std::shared_ptr& sharedImageSet) try + HRESULT AdaptiveImageSet::RuntimeClassInitialize(const std::shared_ptr& sharedImageSet) + try { if (sharedImageSet == nullptr) { @@ -61,7 +63,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveImageSet::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveImageSet::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr imageSet = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp index dd422d7ae9..4f12a80b71 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSetConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveImageSetConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageSetConfig::RuntimeClassInitialize() noexcept + try { ImageSetConfig imageSetConfig; return RuntimeClassInitialize(imageSetConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp index b2f0eb5d11..340dcc13c2 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSetRenderer.cpp @@ -17,16 +17,18 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveImageSetRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageSetRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } CATCH_RETURN; HRESULT AdaptiveImageSetRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, - _In_ IAdaptiveRenderContext* renderContext, - _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** imageSetControl) noexcept try + _In_ IAdaptiveRenderContext* renderContext, + _In_ IAdaptiveRenderArgs* renderArgs, + _COM_Outptr_ IUIElement** imageSetControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveImageSet; @@ -100,7 +102,8 @@ namespace AdaptiveNamespace ComPtr imageSetAsFrameworkElement; RETURN_IF_FAILED(xamlGrid.As(&imageSetAsFrameworkElement)); - RETURN_IF_FAILED(XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.ImageSet", imageSetAsFrameworkElement.Get())); + RETURN_IF_FAILED( + XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.ImageSet", imageSetAsFrameworkElement.Get())); return xamlGrid.CopyTo(imageSetControl); } @@ -111,7 +114,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp index cf7af8889d..a89347f875 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageSizesConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveImageSizesConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveImageSizesConfig::RuntimeClassInitialize() noexcept + try { ImageSizesConfig imageSizesConfig; return RuntimeClassInitialize(imageSizesConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveMedia.cpp b/source/uwp/Renderer/lib/AdaptiveMedia.cpp index 37cce06cde..5f7037bc37 100644 --- a/source/uwp/Renderer/lib/AdaptiveMedia.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMedia.cpp @@ -9,14 +9,16 @@ using namespace ABI::Windows::Foundation::Collections; namespace AdaptiveNamespace { - HRESULT AdaptiveMedia::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveMedia::RuntimeClassInitialize() noexcept + try { std::shared_ptr media = std::make_shared(); return RuntimeClassInitialize(media); } CATCH_RETURN; - HRESULT AdaptiveMedia::RuntimeClassInitialize(const std::shared_ptr& sharedMedia) try + HRESULT AdaptiveMedia::RuntimeClassInitialize(const std::shared_ptr& sharedMedia) + try { if (sharedMedia == nullptr) { @@ -53,7 +55,8 @@ namespace AdaptiveNamespace return m_sources.CopyTo(sources); } - HRESULT AdaptiveMedia::GetSharedModel(std::shared_ptr& sharedMedia) try + HRESULT AdaptiveMedia::GetSharedModel(std::shared_ptr& sharedMedia) + try { std::shared_ptr media = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveMedia.h b/source/uwp/Renderer/lib/AdaptiveMedia.h index e93addbd5f..0d19e114df 100644 --- a/source/uwp/Renderer/lib/AdaptiveMedia.h +++ b/source/uwp/Renderer/lib/AdaptiveMedia.h @@ -58,10 +58,22 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_Id(_Outptr_ HSTRING* id) { return AdaptiveCardElementBase::get_Id(id); } IFACEMETHODIMP put_Id(_In_ HSTRING id) { return AdaptiveCardElementBase::put_Id(id); } - IFACEMETHODIMP get_FallbackType(_Out_ ABI::AdaptiveNamespace::FallbackType * fallback) { return AdaptiveCardElementBase::get_FallbackType(fallback); } - IFACEMETHODIMP get_FallbackContent(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement ** content) { return AdaptiveCardElementBase::get_FallbackContent(content); } - IFACEMETHODIMP put_FallbackType(ABI::AdaptiveNamespace::FallbackType fallback) { return AdaptiveCardElementBase::put_FallbackType(fallback); } - IFACEMETHODIMP put_FallbackContent(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement * content) { return AdaptiveCardElementBase::put_FallbackContent(content); } + IFACEMETHODIMP get_FallbackType(_Out_ ABI::AdaptiveNamespace::FallbackType* fallback) + { + return AdaptiveCardElementBase::get_FallbackType(fallback); + } + IFACEMETHODIMP get_FallbackContent(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** content) + { + return AdaptiveCardElementBase::get_FallbackContent(content); + } + IFACEMETHODIMP put_FallbackType(ABI::AdaptiveNamespace::FallbackType fallback) + { + return AdaptiveCardElementBase::put_FallbackType(fallback); + } + IFACEMETHODIMP put_FallbackContent(_In_ ABI::AdaptiveNamespace::IAdaptiveCardElement* content) + { + return AdaptiveCardElementBase::put_FallbackContent(content); + } IFACEMETHODIMP get_ElementTypeString(_Outptr_ HSTRING* value) { diff --git a/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp b/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp index c8fe337705..6e33c207f3 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveMediaConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveMediaConfig::RuntimeClassInitialize() noexcept + try { MediaConfig mediaConfig; return RuntimeClassInitialize(mediaConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveMediaEventInvoker.cpp b/source/uwp/Renderer/lib/AdaptiveMediaEventInvoker.cpp index f834aa8e89..cceeca9c3a 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaEventInvoker.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaEventInvoker.cpp @@ -15,7 +15,8 @@ namespace AdaptiveNamespace { HRESULT AdaptiveMediaEventInvoker::RuntimeClassInitialize() noexcept { return S_OK; } - HRESULT AdaptiveMediaEventInvoker::RuntimeClassInitialize(_In_ RenderedAdaptiveCard* renderResult) noexcept try + HRESULT AdaptiveMediaEventInvoker::RuntimeClassInitialize(_In_ RenderedAdaptiveCard* renderResult) noexcept + try { ComPtr strongRenderResult = renderResult; return strongRenderResult.AsWeak(&m_weakRenderResult); diff --git a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp index f559fc3147..ef4aced326 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaRenderer.cpp @@ -21,7 +21,8 @@ using namespace ABI::Windows::UI::Xaml::Media; namespace AdaptiveNamespace { - HRESULT AdaptiveMediaRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveMediaRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -30,7 +31,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveMediaRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** mediaControl) noexcept try + _COM_Outptr_ IUIElement** mediaControl) noexcept + try { ComPtr localCardElement{adaptiveCardElement}; ComPtr adaptiveMedia; @@ -176,7 +178,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveMediaSource.cpp b/source/uwp/Renderer/lib/AdaptiveMediaSource.cpp index 01377a4b6c..7891eca043 100644 --- a/source/uwp/Renderer/lib/AdaptiveMediaSource.cpp +++ b/source/uwp/Renderer/lib/AdaptiveMediaSource.cpp @@ -5,7 +5,8 @@ namespace AdaptiveNamespace { - HRESULT AdaptiveMediaSource::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveMediaSource::RuntimeClassInitialize() noexcept + try { std::shared_ptr mediaSource = std::make_shared(); @@ -13,7 +14,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveMediaSource::RuntimeClassInitialize(const std::shared_ptr& sharedMediaSource) try + HRESULT AdaptiveMediaSource::RuntimeClassInitialize(const std::shared_ptr& sharedMediaSource) + try { if (sharedMediaSource == nullptr) { @@ -35,7 +37,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveMediaSource::put_Url(_In_ HSTRING value) { return m_url.Set(value); } - HRESULT AdaptiveMediaSource::GetSharedModel(std::shared_ptr& sharedMediaSource) try + HRESULT AdaptiveMediaSource::GetSharedModel(std::shared_ptr& sharedMediaSource) + try { std::shared_ptr mediaSource = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp b/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp index 2cea66655f..1fb1d551f2 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveNumberInput.cpp @@ -13,7 +13,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveNumberInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveNumberInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr numberInput = std::make_shared(); @@ -21,7 +22,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveNumberInput::RuntimeClassInitialize(const std::shared_ptr& sharedNumberInput) try + HRESULT AdaptiveNumberInput::RuntimeClassInitialize(const std::shared_ptr& sharedNumberInput) + try { if (sharedNumberInput == nullptr) { @@ -87,7 +89,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveNumberInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveNumberInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr numberInput = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp index 351be69dcc..190b0ee527 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveNumberInputRenderer.cpp @@ -17,7 +17,8 @@ using namespace ABI::Windows::UI::Xaml::Input; namespace AdaptiveNamespace { - HRESULT AdaptiveNumberInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveNumberInputRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -26,7 +27,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveNumberInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** numberInputControl) noexcept try + _COM_Outptr_ IUIElement** numberInputControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -89,7 +91,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp index ae18e7b5b7..2513e0ac32 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.cpp @@ -11,7 +11,8 @@ using namespace ABI::Windows::Foundation; namespace AdaptiveNamespace { - HRESULT AdaptiveOpenUrlAction::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveOpenUrlAction::RuntimeClassInitialize() noexcept + try { std::shared_ptr openUrlAction = std::make_shared(); @@ -19,7 +20,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveOpenUrlAction::RuntimeClassInitialize(const std::shared_ptr& sharedOpenUrlAction) try + HRESULT AdaptiveOpenUrlAction::RuntimeClassInitialize(const std::shared_ptr& sharedOpenUrlAction) + try { if (sharedOpenUrlAction == nullptr) { @@ -43,7 +45,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveOpenUrlAction::get_Url(_COM_Outptr_ IUriRuntimeClass** url) { return m_url.CopyTo(url); } - HRESULT AdaptiveOpenUrlAction::put_Url(_In_ IUriRuntimeClass* url) try + HRESULT AdaptiveOpenUrlAction::put_Url(_In_ IUriRuntimeClass* url) + try { m_url = url; return S_OK; @@ -56,7 +59,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveOpenUrlAction::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveOpenUrlAction::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr openUrlAction = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h index be8503aa6a..9071f28910 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlAction.h @@ -63,14 +63,8 @@ namespace AdaptiveNamespace } IFACEMETHODIMP put_IconUrl(_In_ HSTRING iconUrl) { return AdaptiveActionElementBase::put_IconUrl(iconUrl); } - IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) - { - return AdaptiveActionElementBase::get_Style(style); - } - IFACEMETHODIMP put_Style(_In_ HSTRING style) - { - return AdaptiveActionElementBase::put_Style(style); - } + IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) { return AdaptiveActionElementBase::get_Style(style); } + IFACEMETHODIMP put_Style(_In_ HSTRING style) { return AdaptiveActionElementBase::put_Style(style); } IFACEMETHODIMP get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp index f6cf6ae869..cf682a0c79 100644 --- a/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveOpenUrlActionRenderer.cpp @@ -13,7 +13,8 @@ using namespace Microsoft::WRL; namespace AdaptiveNamespace { - HRESULT AdaptiveOpenUrlActionRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveOpenUrlActionRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -22,7 +23,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveOpenUrlActionRenderer::Render(_In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } @@ -33,7 +35,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp index f73ce9deee..932c398eed 100644 --- a/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRemoteResourceInformation.cpp @@ -13,14 +13,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveRemoteResourceInformation::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveRemoteResourceInformation::RuntimeClassInitialize() noexcept + try { RemoteResourceInformation uriInformation; return RuntimeClassInitialize(uriInformation); } CATCH_RETURN; - HRESULT AdaptiveRemoteResourceInformation::RuntimeClassInitialize(RemoteResourceInformation& uriInformation) try + HRESULT AdaptiveRemoteResourceInformation::RuntimeClassInitialize(RemoteResourceInformation& uriInformation) + try { RETURN_IF_FAILED(UTF8ToHString(uriInformation.url, m_url.GetAddressOf())); RETURN_IF_FAILED(UTF8ToHString(uriInformation.mimeType, m_mimeType.GetAddressOf())); diff --git a/source/uwp/Renderer/lib/AdaptiveRenderArgs.cpp b/source/uwp/Renderer/lib/AdaptiveRenderArgs.cpp index 3c00444d13..011dff923c 100644 --- a/source/uwp/Renderer/lib/AdaptiveRenderArgs.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRenderArgs.cpp @@ -16,7 +16,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveRenderArgs::RuntimeClassInitialize(ABI::AdaptiveNamespace::ContainerStyle containerStyle, _In_opt_ IInspectable* parentElement, - _In_opt_ IAdaptiveRenderArgs* renderArgs) noexcept try + _In_opt_ IAdaptiveRenderArgs* renderArgs) noexcept + try { m_containerStyle = containerStyle; m_parentElement = parentElement; diff --git a/source/uwp/Renderer/lib/AdaptiveRenderContext.cpp b/source/uwp/Renderer/lib/AdaptiveRenderContext.cpp index fd5579859a..93e61a2fe7 100644 --- a/source/uwp/Renderer/lib/AdaptiveRenderContext.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRenderContext.cpp @@ -26,7 +26,8 @@ namespace AdaptiveNamespace _In_ IAdaptiveCardResourceResolvers* resourceResolvers, _In_ IResourceDictionary* overrideDictionary, _In_ IResourceDictionary* defaultActionSentimentStyles, - _In_ RenderedAdaptiveCard* renderResult) noexcept try + _In_ RenderedAdaptiveCard* renderResult) noexcept + try { m_hostConfig = hostConfig; m_featureRegistration = featureRegistration; diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp index 814aabf5d9..f9485b0b1e 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlock.cpp @@ -16,7 +16,8 @@ namespace AdaptiveNamespace { AdaptiveRichTextBlock::AdaptiveRichTextBlock() { m_inlines = Microsoft::WRL::Make>(); } - HRESULT AdaptiveRichTextBlock::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveRichTextBlock::RuntimeClassInitialize() noexcept + try { std::shared_ptr richTextBlock = std::make_shared(); @@ -24,7 +25,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveRichTextBlock::RuntimeClassInitialize(const std::shared_ptr& sharedRichTextBlock) noexcept try + HRESULT AdaptiveRichTextBlock::RuntimeClassInitialize(const std::shared_ptr& sharedRichTextBlock) noexcept + try { if (sharedRichTextBlock == nullptr) { @@ -64,7 +66,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveRichTextBlock::GetSharedModel(std::shared_ptr& sharedRichTextBlock) noexcept try + HRESULT AdaptiveRichTextBlock::GetSharedModel(std::shared_ptr& sharedRichTextBlock) noexcept + try { std::shared_ptr richTextBlock = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp index 9f0f737346..de2941cc3d 100644 --- a/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveRichTextBlockRenderer.cpp @@ -19,7 +19,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveRichTextBlockRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveRichTextBlockRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -28,7 +29,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveRichTextBlockRenderer::Render(_In_ IAdaptiveCardElement* cardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { // Create the top level rich text block and set it's properties ComPtr xamlRichTextBlock = @@ -173,7 +175,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveSeparator.cpp b/source/uwp/Renderer/lib/AdaptiveSeparator.cpp index bb5ff0f359..12fbc54fff 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparator.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSeparator.cpp @@ -13,7 +13,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveSeparator::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveSeparator::RuntimeClassInitialize() noexcept + try { m_sharedSeparator = std::make_shared(); return S_OK; diff --git a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp index 2a6a5f3d85..54d3a3afa4 100644 --- a/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSeparatorConfig.cpp @@ -9,14 +9,16 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveSeparatorConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveSeparatorConfig::RuntimeClassInitialize() noexcept + try { SeparatorConfig separatorConfig; return RuntimeClassInitialize(separatorConfig); } CATCH_RETURN; - HRESULT AdaptiveSeparatorConfig::RuntimeClassInitialize(SeparatorConfig sharedSeparatorConfig) noexcept try + HRESULT AdaptiveSeparatorConfig::RuntimeClassInitialize(SeparatorConfig sharedSeparatorConfig) noexcept + try { RETURN_IF_FAILED(GetColorFromString(sharedSeparatorConfig.lineColor, &m_lineColor)); m_lineThickness = sharedSeparatorConfig.lineThickness; diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp index 50877b81e1..da5b419316 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardAction.cpp @@ -10,7 +10,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveShowCardAction::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveShowCardAction::RuntimeClassInitialize() noexcept + try { std::shared_ptr showCardAction = std::make_shared(); @@ -18,7 +19,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveShowCardAction::RuntimeClassInitialize(const std::shared_ptr& sharedShowCardAction) try + HRESULT AdaptiveShowCardAction::RuntimeClassInitialize(const std::shared_ptr& sharedShowCardAction) + try { if (sharedShowCardAction == nullptr) { @@ -53,7 +55,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveShowCardAction::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveShowCardAction::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr showCardAction = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardAction.h b/source/uwp/Renderer/lib/AdaptiveShowCardAction.h index 314891f33c..c0026c140b 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardAction.h +++ b/source/uwp/Renderer/lib/AdaptiveShowCardAction.h @@ -63,14 +63,8 @@ namespace AdaptiveNamespace } IFACEMETHODIMP put_IconUrl(_In_ HSTRING iconUrl) { return AdaptiveActionElementBase::put_IconUrl(iconUrl); } - IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) - { - return AdaptiveActionElementBase::get_Style(style); - } - IFACEMETHODIMP put_Style(_In_ HSTRING style) - { - return AdaptiveActionElementBase::put_Style(style); - } + IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) { return AdaptiveActionElementBase::get_Style(style); } + IFACEMETHODIMP put_Style(_In_ HSTRING style) { return AdaptiveActionElementBase::put_Style(style); } IFACEMETHODIMP get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp index 31a0c9bf10..2c3f943213 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionConfig.cpp @@ -10,7 +10,8 @@ using namespace ABI::Windows::UI; namespace AdaptiveNamespace { - HRESULT AdaptiveShowCardActionConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveShowCardActionConfig::RuntimeClassInitialize() noexcept + try { ShowCardActionConfig showCardActionConfig; return RuntimeClassInitialize(showCardActionConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp index 297d2f1c73..fee5d0fb9f 100644 --- a/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveShowCardActionRenderer.cpp @@ -15,7 +15,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveShowCardActionRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveShowCardActionRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -24,7 +25,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveShowCardActionRenderer::Render(_In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } @@ -35,7 +37,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); @@ -46,7 +49,8 @@ namespace AdaptiveNamespace _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, bool isBottomActionBar, - _Outptr_ IUIElement** uiShowCard) noexcept try + _Outptr_ IUIElement** uiShowCard) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -65,7 +69,8 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(renderArgs->put_IsInShowCard(true)); ComPtr localUiShowCard; - RETURN_IF_FAILED(XamlBuilder::BuildXamlTreeFromAdaptiveCard(showCard, localUiShowCard.GetAddressOf(), renderContext, nullptr, showCardConfigStyle)); + RETURN_IF_FAILED( + XamlBuilder::BuildXamlTreeFromAdaptiveCard(showCard, localUiShowCard.GetAddressOf(), renderContext, nullptr, showCardConfigStyle)); RETURN_IF_FAILED(renderArgs->put_IsInShowCard(wasInShowCard)); diff --git a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp index c1273a523b..b5806be831 100644 --- a/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSpacingConfig.cpp @@ -9,14 +9,16 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveSpacingConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveSpacingConfig::RuntimeClassInitialize() noexcept + try { SpacingConfig spacingConfig; return RuntimeClassInitialize(spacingConfig); } CATCH_RETURN; - HRESULT AdaptiveSpacingConfig::RuntimeClassInitialize(SpacingConfig spacingConfig) noexcept try + HRESULT AdaptiveSpacingConfig::RuntimeClassInitialize(SpacingConfig spacingConfig) noexcept + try { m_small = spacingConfig.smallSpacing; m_medium = spacingConfig.mediumSpacing; diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp index 3a9756d850..1ad5f07cc7 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp @@ -10,7 +10,8 @@ using namespace ABI::Windows::Data::Json; namespace AdaptiveNamespace { - HRESULT AdaptiveSubmitAction::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveSubmitAction::RuntimeClassInitialize() noexcept + try { std::shared_ptr submitAction = std::make_shared(); @@ -18,7 +19,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveSubmitAction::RuntimeClassInitialize(const std::shared_ptr& sharedSubmitAction) try + HRESULT AdaptiveSubmitAction::RuntimeClassInitialize(const std::shared_ptr& sharedSubmitAction) + try { if (sharedSubmitAction == nullptr) { @@ -64,7 +66,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveSubmitAction::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveSubmitAction::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr submitAction = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h index ae4a2dcb53..a4097c9445 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h @@ -66,14 +66,8 @@ namespace AdaptiveNamespace } IFACEMETHODIMP put_IconUrl(_In_ HSTRING iconUrl) { return AdaptiveActionElementBase::put_IconUrl(iconUrl); } - IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) - { - return AdaptiveActionElementBase::get_Style(style); - } - IFACEMETHODIMP put_Style(_In_ HSTRING style) - { - return AdaptiveActionElementBase::put_Style(style); - } + IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) { return AdaptiveActionElementBase::get_Style(style); } + IFACEMETHODIMP put_Style(_In_ HSTRING style) { return AdaptiveActionElementBase::put_Style(style); } IFACEMETHODIMP get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp index 163051e28f..e1081f730d 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSubmitActionRenderer.cpp @@ -12,7 +12,8 @@ using namespace Microsoft::WRL; namespace AdaptiveNamespace { - HRESULT AdaptiveSubmitActionRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveSubmitActionRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -21,7 +22,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveSubmitActionRenderer::Render(_In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } @@ -32,7 +34,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp b/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp index 9f190fdf8e..3bf1133309 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextBlock.cpp @@ -14,14 +14,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTextBlock::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextBlock::RuntimeClassInitialize() noexcept + try { std::shared_ptr textBlock = std::make_shared(); return RuntimeClassInitialize(textBlock); } CATCH_RETURN; - HRESULT AdaptiveTextBlock::RuntimeClassInitialize(const std::shared_ptr& sharedTextBlock) try + HRESULT AdaptiveTextBlock::RuntimeClassInitialize(const std::shared_ptr& sharedTextBlock) + try { if (sharedTextBlock == nullptr) { @@ -80,7 +82,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveTextBlock::GetSharedModel(std::shared_ptr& sharedTextBlock) try + HRESULT AdaptiveTextBlock::GetSharedModel(std::shared_ptr& sharedTextBlock) + try { std::shared_ptr textBlock = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp index 0d5c434992..68b2a505bb 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextBlockRenderer.cpp @@ -18,7 +18,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTextBlockRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextBlockRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -27,7 +28,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveTextBlockRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** textBlockControl) noexcept try + _COM_Outptr_ IUIElement** textBlockControl) noexcept + try { ComPtr cardElement(adaptiveCardElement); ComPtr adaptiveTextBlock; @@ -66,7 +68,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp b/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp index b6e5335ade..48a49c76ec 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextConfig.cpp @@ -9,7 +9,8 @@ using namespace ABI::AdaptiveNamespace; namespace AdaptiveNamespace { - HRESULT AdaptiveTextConfig::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextConfig::RuntimeClassInitialize() noexcept + try { TextConfig textConfig; return RuntimeClassInitialize(textConfig); diff --git a/source/uwp/Renderer/lib/AdaptiveTextElement.h b/source/uwp/Renderer/lib/AdaptiveTextElement.h index bd387e5f92..49e3728bea 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextElement.h +++ b/source/uwp/Renderer/lib/AdaptiveTextElement.h @@ -31,9 +31,8 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_Underline(_Out_ boolean* underline); IFACEMETHODIMP put_Underline(_In_ boolean underline); - protected : template - HRESULT - InitializeTextElement(const std::shared_ptr& sharedModel) + protected: + template HRESULT InitializeTextElement(const std::shared_ptr& sharedModel) { m_subtle = sharedModel->GetIsSubtle(); m_fontType = static_cast(sharedModel->GetFontType()); diff --git a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp index dfa21ea7c9..796528e732 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp @@ -13,14 +13,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTextInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr textInput = std::make_shared(); return RuntimeClassInitialize(textInput); } CATCH_RETURN; - HRESULT AdaptiveTextInput::RuntimeClassInitialize(const std::shared_ptr& sharedTextInput) try + HRESULT AdaptiveTextInput::RuntimeClassInitialize(const std::shared_ptr& sharedTextInput) + try { if (sharedTextInput == nullptr) { @@ -109,7 +111,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveTextInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveTextInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr textInput = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp index 73a53a85e6..83453d9875 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextInputRenderer.cpp @@ -18,7 +18,8 @@ using namespace ABI::Windows::UI::Xaml::Input; namespace AdaptiveNamespace { - HRESULT AdaptiveTextInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextInputRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -27,7 +28,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveTextInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ IUIElement** textInputControl) noexcept try + _COM_Outptr_ IUIElement** textInputControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -135,7 +137,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveTextRun.cpp b/source/uwp/Renderer/lib/AdaptiveTextRun.cpp index d38b640828..d2aef56e9f 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextRun.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextRun.cpp @@ -13,14 +13,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTextRun::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTextRun::RuntimeClassInitialize() noexcept + try { RuntimeClassInitialize(std::make_shared()); return S_OK; } CATCH_RETURN; - HRESULT AdaptiveTextRun::RuntimeClassInitialize(const std::shared_ptr& sharedTextRun) noexcept try + HRESULT AdaptiveTextRun::RuntimeClassInitialize(const std::shared_ptr& sharedTextRun) noexcept + try { m_highlight = sharedTextRun->GetHighlight(); m_italic = sharedTextRun->GetItalic(); @@ -92,7 +94,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveTextRun::GetSharedModel(std::shared_ptr& sharedModel) noexcept try + HRESULT AdaptiveTextRun::GetSharedModel(std::shared_ptr& sharedModel) noexcept + try { std::shared_ptr textRun = std::make_shared(); RETURN_IF_FAILED(AdaptiveTextElement::SetTextElementProperties(textRun)); diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp b/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp index 0d778679ed..41f395244a 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTimeInput.cpp @@ -13,14 +13,16 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTimeInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveTimeInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr timeInput = std::make_shared(); return RuntimeClassInitialize(timeInput); } CATCH_RETURN; - HRESULT AdaptiveTimeInput::RuntimeClassInitialize(const std::shared_ptr& sharedTimeInput) try + HRESULT AdaptiveTimeInput::RuntimeClassInitialize(const std::shared_ptr& sharedTimeInput) + try { if (sharedTimeInput == nullptr) { @@ -63,7 +65,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveTimeInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveTimeInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr timeInput = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp index d6ff3be308..b43bc05cbe 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTimeInputRenderer.cpp @@ -16,15 +16,13 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveTimeInputRenderer::RuntimeClassInitialize() noexcept - { - return S_OK; - } + HRESULT AdaptiveTimeInputRenderer::RuntimeClassInitialize() noexcept { return S_OK; } HRESULT AdaptiveTimeInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** timeInputControl) noexcept try + _COM_Outptr_ IUIElement** timeInputControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -77,7 +75,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp b/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp index 58226e9a8c..18da289825 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleInput.cpp @@ -13,7 +13,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveToggleInput::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveToggleInput::RuntimeClassInitialize() noexcept + try { std::shared_ptr toggleInput = std::make_shared(); @@ -21,7 +22,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveToggleInput::RuntimeClassInitialize(const std::shared_ptr& sharedToggleInput) try + HRESULT AdaptiveToggleInput::RuntimeClassInitialize(const std::shared_ptr& sharedToggleInput) + try { if (sharedToggleInput == nullptr) { @@ -73,7 +75,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveToggleInput::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveToggleInput::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr toggleInput = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp index b659053e81..4af51a19b2 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleInputRenderer.cpp @@ -17,7 +17,8 @@ using namespace ABI::Windows::UI::Xaml::Controls::Primitives; namespace AdaptiveNamespace { - HRESULT AdaptiveToggleInputRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveToggleInputRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -26,7 +27,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveToggleInputRenderer::Render(_In_ IAdaptiveCardElement* adaptiveCardElement, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* /*renderArgs*/, - _COM_Outptr_ IUIElement** toggleInputControl) noexcept try + _COM_Outptr_ IUIElement** toggleInputControl) noexcept + try { ComPtr hostConfig; RETURN_IF_FAILED(renderContext->get_HostConfig(&hostConfig)); @@ -85,7 +87,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveCardElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp index 9cf3e42f27..5bee2ca457 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.cpp @@ -11,7 +11,8 @@ using namespace ABI::Windows::Foundation::Collections; namespace AdaptiveNamespace { - HRESULT AdaptiveToggleVisibilityAction::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveToggleVisibilityAction::RuntimeClassInitialize() noexcept + try { std::shared_ptr toggleVisibilityAction = std::make_shared(); @@ -19,8 +20,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveToggleVisibilityAction::RuntimeClassInitialize( - const std::shared_ptr& sharedToggleVisibilityAction) try + HRESULT AdaptiveToggleVisibilityAction::RuntimeClassInitialize(const std::shared_ptr& sharedToggleVisibilityAction) + try { if (sharedToggleVisibilityAction == nullptr) { @@ -46,7 +47,8 @@ namespace AdaptiveNamespace return m_targetElements.CopyTo(targetElements); } - HRESULT AdaptiveToggleVisibilityAction::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveToggleVisibilityAction::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr toggleVisibilityAction = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h index 94f9bbd162..bc9e7c7d9d 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityAction.h @@ -63,14 +63,8 @@ namespace AdaptiveNamespace } IFACEMETHODIMP put_IconUrl(_In_ HSTRING iconUrl) { return AdaptiveActionElementBase::put_IconUrl(iconUrl); } - IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) - { - return AdaptiveActionElementBase::get_Style(style); - } - IFACEMETHODIMP put_Style(_In_ HSTRING style) - { - return AdaptiveActionElementBase::put_Style(style); - } + IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) { return AdaptiveActionElementBase::get_Style(style); } + IFACEMETHODIMP put_Style(_In_ HSTRING style) { return AdaptiveActionElementBase::put_Style(style); } IFACEMETHODIMP get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp index b0774cf1de..4a38f97afd 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityActionRenderer.cpp @@ -12,7 +12,8 @@ using namespace Microsoft::WRL; namespace AdaptiveNamespace { - HRESULT AdaptiveToggleVisibilityActionRenderer::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveToggleVisibilityActionRenderer::RuntimeClassInitialize() noexcept + try { return S_OK; } @@ -21,7 +22,8 @@ namespace AdaptiveNamespace HRESULT AdaptiveToggleVisibilityActionRenderer::Render(_In_ IAdaptiveActionElement* action, _In_ IAdaptiveRenderContext* renderContext, _In_ IAdaptiveRenderArgs* renderArgs, - _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept try + _COM_Outptr_ ABI::Windows::UI::Xaml::IUIElement** result) noexcept + try { return ActionHelpers::BuildAction(action, renderContext, renderArgs, result); } @@ -32,7 +34,8 @@ namespace AdaptiveNamespace _In_ ABI::AdaptiveNamespace::IAdaptiveElementParserRegistration* elementParserRegistration, _In_ ABI::AdaptiveNamespace::IAdaptiveActionParserRegistration* actionParserRegistration, _In_ ABI::Windows::Foundation::Collections::IVector* adaptiveWarnings, - _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept try + _COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** element) noexcept + try { return AdaptiveNamespace::FromJson( jsonObject, elementParserRegistration, actionParserRegistration, adaptiveWarnings, element); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp index 894b15ca21..7d29e82642 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp +++ b/source/uwp/Renderer/lib/AdaptiveToggleVisibilityTarget.cpp @@ -14,7 +14,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveToggleVisibilityTarget::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveToggleVisibilityTarget::RuntimeClassInitialize() noexcept + try { RuntimeClassInitialize(std::make_shared()); return S_OK; @@ -44,7 +45,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveToggleVisibilityTarget::GetSharedModel(std::shared_ptr& sharedModel) try + HRESULT AdaptiveToggleVisibilityTarget::GetSharedModel(std::shared_ptr& sharedModel) + try { std::shared_ptr toggleTarget = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp index cb5dd7443d..eadcf2e3ff 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.cpp @@ -8,7 +8,8 @@ using namespace Microsoft::WRL::Wrappers; namespace AdaptiveNamespace { - HRESULT AdaptiveUnsupportedAction::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveUnsupportedAction::RuntimeClassInitialize() noexcept + try { std::shared_ptr unknownAction = std::make_shared(); @@ -16,7 +17,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveUnsupportedAction::RuntimeClassInitialize(const std::shared_ptr& sharedUnknown) try + HRESULT AdaptiveUnsupportedAction::RuntimeClassInitialize(const std::shared_ptr& sharedUnknown) + try { if (sharedUnknown == nullptr) { @@ -34,7 +36,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveUnsupportedAction::GetSharedModel(std::shared_ptr& sharedUnknown) try + HRESULT AdaptiveUnsupportedAction::GetSharedModel(std::shared_ptr& sharedUnknown) + try { std::shared_ptr unknownAction = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h index 8a56f8cdd9..c9c5292a8c 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedAction.h @@ -58,14 +58,8 @@ namespace AdaptiveNamespace } IFACEMETHODIMP put_IconUrl(_In_ HSTRING iconUrl) { return AdaptiveActionElementBase::put_IconUrl(iconUrl); } - IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) - { - return AdaptiveActionElementBase::get_Style(style); - } - IFACEMETHODIMP put_Style(_In_ HSTRING style) - { - return AdaptiveActionElementBase::put_Style(style); - } + IFACEMETHODIMP get_Style(_Outptr_ HSTRING* style) { return AdaptiveActionElementBase::get_Style(style); } + IFACEMETHODIMP put_Style(_In_ HSTRING style) { return AdaptiveActionElementBase::put_Style(style); } IFACEMETHODIMP get_AdditionalProperties(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result) { diff --git a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp index 26fe5a7d7e..a7ba4d905d 100644 --- a/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveUnsupportedElement.cpp @@ -13,7 +13,8 @@ using namespace ABI::Windows::UI::Xaml::Controls; namespace AdaptiveNamespace { - HRESULT AdaptiveUnsupportedElement::RuntimeClassInitialize() noexcept try + HRESULT AdaptiveUnsupportedElement::RuntimeClassInitialize() noexcept + try { std::shared_ptr unknownElement = std::make_shared(); @@ -21,7 +22,8 @@ namespace AdaptiveNamespace } CATCH_RETURN; - HRESULT AdaptiveUnsupportedElement::RuntimeClassInitialize(const std::shared_ptr& sharedUnknown) try + HRESULT AdaptiveUnsupportedElement::RuntimeClassInitialize(const std::shared_ptr& sharedUnknown) + try { if (sharedUnknown == nullptr) { @@ -40,7 +42,8 @@ namespace AdaptiveNamespace return S_OK; } - HRESULT AdaptiveUnsupportedElement::GetSharedModel(std::shared_ptr& sharedUnknown) try + HRESULT AdaptiveUnsupportedElement::GetSharedModel(std::shared_ptr& sharedUnknown) + try { std::shared_ptr unknownElement = std::make_shared(); diff --git a/source/uwp/Renderer/lib/AsyncOperations.h b/source/uwp/Renderer/lib/AsyncOperations.h index 5338915844..38a6670e0d 100644 --- a/source/uwp/Renderer/lib/AsyncOperations.h +++ b/source/uwp/Renderer/lib/AsyncOperations.h @@ -104,9 +104,9 @@ class RenderAsyncBase m_renderResult.Get())); AdaptiveNamespace::XamlBuilder::BuildXamlTreeFromAdaptiveCard(m_card.Get(), - &m_rootXamlElement, - renderContext.Get(), - m_renderer->GetXamlBuilder()); + &m_rootXamlElement, + renderContext.Get(), + m_renderer->GetXamlBuilder()); } catch (...) { @@ -114,8 +114,7 @@ class RenderAsyncBase return XamlBuilderHadError(); } return S_OK; - }) - .Get(), + }).Get(), &dispatcherAsyncAction); dispatcherAsyncAction->put_Completed( diff --git a/source/uwp/Renderer/lib/DefaultResourceDictionary.h b/source/uwp/Renderer/lib/DefaultResourceDictionary.h index 5edfdd2ead..bb62118816 100644 --- a/source/uwp/Renderer/lib/DefaultResourceDictionary.h +++ b/source/uwp/Renderer/lib/DefaultResourceDictionary.h @@ -68,7 +68,6 @@ const PCWSTR c_defaultResourceDictionary = L"\ \ " - "