diff --git a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/CarouselTest.cpp b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/CarouselTest.cpp index 4972b59a25..c493dca817 100644 --- a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/CarouselTest.cpp +++ b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/CarouselTest.cpp @@ -190,7 +190,7 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual(carousel->GetElementTypeString(), CardElementTypeToString(CardElementType::Carousel)); Assert::AreEqual(carousel->GetAutoLoop().value(), false); Assert::AreEqual(carousel->GetInitialPage().value(), static_cast(1)); - Assert::AreEqual(carousel->GetHeightInPixels(), "100px"); + Assert::AreEqual(carousel->GetHeightInPixels(), 100); Assert::AreEqual(carousel->GetTimer().value(), 5000); auto carouselPage = std::dynamic_pointer_cast(carousel->GetPages()[0]); @@ -300,7 +300,7 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual(carousel->GetElementTypeString(), CardElementTypeToString(CardElementType::Carousel)); Assert::AreEqual(carousel->GetAutoLoop().value(), false); Assert::AreEqual(carousel->GetInitialPage().value(), static_cast(1)); - Assert::AreEqual(carousel->GetHeightInPixels(), "100px"); + Assert::AreEqual(carousel->GetHeightInPixels(), 100); Assert::AreEqual(carousel->GetTimer().value(), 5000); auto carouselPage = std::dynamic_pointer_cast(carousel->GetPages()[0]); diff --git a/source/shared/cpp/ObjectModel/Carousel.cpp b/source/shared/cpp/ObjectModel/Carousel.cpp index 1016020f47..ddd7c5de3a 100644 --- a/source/shared/cpp/ObjectModel/Carousel.cpp +++ b/source/shared/cpp/ObjectModel/Carousel.cpp @@ -1,3 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. #include "pch.h" #include "Carousel.h" @@ -5,7 +7,7 @@ using namespace AdaptiveCards; namespace AdaptiveCards { -Carousel::Carousel() : CollectionCoreElement(CardElementType::Carousel) +Carousel::Carousel() : StyledCollectionElement(CardElementType::Carousel) { PopulateKnownPropertiesSet(); } @@ -26,10 +28,12 @@ Json::Value Carousel::SerializeToJsonValue() const { Json::Value root = CollectionCoreElement::SerializeToJsonValue(); - if (!m_heightInPixels.empty()) - { - root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::HeightInPixels)] = m_heightInPixels; - } + if (m_heightInPixels) + { + std::ostringstream stringStream; + stringStream << m_heightInPixels; + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::HeightInPixels)] = stringStream.str() + "px"; + } if (m_initialPage.has_value()) { @@ -62,6 +66,11 @@ Json::Value Carousel::SerializeToJsonValue() const root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Timer)] = m_timer.value_or(0); } + if (m_rtl.has_value()) + { + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Rtl)] = m_rtl.value_or(""); + } + return root; } @@ -80,12 +89,12 @@ void Carousel::SetPages(const std::vector& value) m_autoLoop = value; } +std::optional Carousel::GetRtl() const +{ + return m_rtl; +} + +void Carousel::SetRtl(const std::optional& value) +{ + m_rtl = value; +} + void Carousel::DeserializeChildren(ParseContext& context, const Json::Value& value) { if (auto deserializedPages = @@ -146,9 +165,15 @@ std::shared_ptr CarouselParser::Deserialize(ParseContext& conte context.AddProhibitedElementType(m_prohibitedTypesList); - std::shared_ptr carousel = CollectionCoreElement::Deserialize(context, value); + std::shared_ptr carousel = StyledCollectionElement::Deserialize(context, value); + + const auto& optionalPixelHeight = + ParseSizeForPixelSize(ParseUtil::GetString(value, AdaptiveCardSchemaKey::HeightInPixels), &context.warnings); - carousel->SetHeightInPixels(ParseUtil::GetString(value, AdaptiveCardSchemaKey::HeightInPixels)); + if (optionalPixelHeight.has_value()) + { + carousel->SetHeightInPixels(optionalPixelHeight.value_or(0)); + } carousel->SetInitialPage(ParseUtil::GetOptionalUnsignedInt(value, AdaptiveCardSchemaKey::InitialPage)); @@ -159,6 +184,10 @@ std::shared_ptr CarouselParser::Deserialize(ParseContext& conte carousel->SetOrientation(ParseUtil::GetOptionalEnumValue( value, AdaptiveCardSchemaKey::Orientation, CarouselOrientationFromString)); + carousel->SetRtl(ParseUtil::GetOptionalBool(value, AdaptiveCardSchemaKey::Rtl)); + + context.RemoveProhibitedElementType(m_prohibitedTypesList); + return carousel; } diff --git a/source/shared/cpp/ObjectModel/Carousel.h b/source/shared/cpp/ObjectModel/Carousel.h index 1c08538a85..3670776d98 100644 --- a/source/shared/cpp/ObjectModel/Carousel.h +++ b/source/shared/cpp/ObjectModel/Carousel.h @@ -1,12 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. #pragma once #include "pch.h" -#include "CollectionCoreElement.h" +#include "StyledCollectionElement.h" #include "CarouselPage.h" namespace AdaptiveCards { -class Carousel : public CollectionCoreElement +class Carousel : public StyledCollectionElement { public: Carousel(); @@ -23,8 +25,8 @@ class Carousel : public CollectionCoreElement const std::vector>& GetPages() const; void SetPages(const std::vector>& value); - std::string GetHeightInPixels() const; - void SetHeightInPixels(const std::string& value); + unsigned int GetHeightInPixels() const; + void SetHeightInPixels(const unsigned int value); std::optional GetTimer() const; void SetTimer(const std::optional& value); @@ -38,15 +40,19 @@ class Carousel : public CollectionCoreElement std::optional GetAutoLoop() const; void setAutoLoop(const std::optional& value); + std::optional GetRtl() const; + void SetRtl(const std::optional& value); + private: void PopulateKnownPropertiesSet(); std::vector> m_pages; - std::string m_heightInPixels; + unsigned int m_heightInPixels{0}; std::optional m_timer; std::optional m_initialPage; std::optional m_orientation; std::optional m_autoLoop; + std::optional m_rtl; }; class CarouselParser : public BaseCardElementParser diff --git a/source/shared/cpp/ObjectModel/CarouselPage.cpp b/source/shared/cpp/ObjectModel/CarouselPage.cpp index c75df70442..8ef1c7dc2c 100644 --- a/source/shared/cpp/ObjectModel/CarouselPage.cpp +++ b/source/shared/cpp/ObjectModel/CarouselPage.cpp @@ -1,3 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. #include "pch.h" #include "CarouselPage.h" diff --git a/source/shared/cpp/ObjectModel/CarouselPage.h b/source/shared/cpp/ObjectModel/CarouselPage.h index 49b00f4e97..497b89641f 100644 --- a/source/shared/cpp/ObjectModel/CarouselPage.h +++ b/source/shared/cpp/ObjectModel/CarouselPage.h @@ -1,3 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. #pragma once #include "Container.h" diff --git a/source/shared/cpp/ObjectModel/ParseContext.cpp b/source/shared/cpp/ObjectModel/ParseContext.cpp index 08242006cf..ad5cbaa4b0 100644 --- a/source/shared/cpp/ObjectModel/ParseContext.cpp +++ b/source/shared/cpp/ObjectModel/ParseContext.cpp @@ -330,6 +330,17 @@ void ParseContext::AddProhibitedElementType(const std::vector& list m_prohibitedElementTypes.insert(list.begin(), list.end()); } +void ParseContext::RemoveProhibitedElementType(const std::vector& list) +{ + for (const auto& type : list) + { + if (const auto itr = m_prohibitedElementTypes.find(type); itr != m_prohibitedElementTypes.end()) + { + m_prohibitedElementTypes.erase(itr); + } + } +} + void ParseContext::ShouldParse(const std::string& typeString) { if (m_prohibitedElementTypes.find(typeString) != m_prohibitedElementTypes.end()) diff --git a/source/shared/cpp/ObjectModel/ParseContext.h b/source/shared/cpp/ObjectModel/ParseContext.h index a7f23d4585..c734a52103 100644 --- a/source/shared/cpp/ObjectModel/ParseContext.h +++ b/source/shared/cpp/ObjectModel/ParseContext.h @@ -49,6 +49,7 @@ class ParseContext void PopBleedDirection(); void AddProhibitedElementType(const std::vector& list); + void RemoveProhibitedElementType(const std::vector& list); void ShouldParse(const std::string& type); private: diff --git a/source/shared/cpp/ObjectModel/pch.h b/source/shared/cpp/ObjectModel/pch.h index 74608d07f6..47afb41508 100644 --- a/source/shared/cpp/ObjectModel/pch.h +++ b/source/shared/cpp/ObjectModel/pch.h @@ -44,5 +44,5 @@ namespace AdaptiveCards { -constexpr const char* const c_sharedModelVersion = "1.5"; +constexpr const char* const c_sharedModelVersion = "1.6"; } diff --git a/source/uwp/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.Uwp.idl b/source/uwp/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.Uwp.idl index cdd9d21151..a5dd54b4ac 100644 --- a/source/uwp/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.Uwp.idl +++ b/source/uwp/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.Uwp.idl @@ -63,6 +63,8 @@ namespace AdaptiveCards.ObjectModel.Uwp AdaptiveCard, TextBlock, Image, + Carousel, + CarouselPage, Container, Column, ColumnSet, @@ -258,6 +260,12 @@ namespace AdaptiveCards.ObjectModel.Uwp MenuItem }; + enum CarouselOrientation + { + Horizontal = 0, + Vertical, + }; + declare { interface Windows.Foundation.Collections.IVector; } interface IAdaptiveCardElement @@ -593,6 +601,25 @@ namespace AdaptiveCards.ObjectModel.Uwp Windows.Foundation.Collections.IVector Columns { get; }; }; + [default_interface] runtimeclass AdaptiveCarouselPage : IAdaptiveContainer, IAdaptiveContainerBase, IAdaptiveCardElement + { + AdaptiveCarouselPage(); + }; + + runtimeclass AdaptiveCarousel : IAdaptiveContainerBase, IAdaptiveCardElement + { + AdaptiveCarousel(); + Windows.Foundation.Collections.IVector Pages { get; }; + CarouselOrientation Orientation; + Windows.Foundation.IReference Timer; + Windows.Foundation.IReference InitialPage; + Windows.Foundation.IReference AutoLoop; + Windows.Foundation.IReference VerticalContentAlignment; + Windows.Foundation.IReference Rtl; + AdaptiveBackgroundImage BackgroundImage; + UInt32 HeightInPixels; + }; + runtimeclass AdaptiveFact { AdaptiveFact(); diff --git a/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl b/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl index dd1bf2db65..10f53987bc 100644 --- a/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl +++ b/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl @@ -556,6 +556,16 @@ namespace AdaptiveCards AdaptiveImageSetRenderer(); } + [default_interface] runtimeclass AdaptiveCarouselRenderer : IAdaptiveElementRenderer + { + AdaptiveCarouselRenderer(); + } + + [default_interface] runtimeclass AdaptiveCarouselPageRenderer : IAdaptiveElementRenderer + { + AdaptiveCarouselPageRenderer(); + } + [default_interface] runtimeclass AdaptiveContainerRenderer : IAdaptiveElementRenderer { AdaptiveContainerRenderer(); diff --git a/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems b/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems index dec64e69f0..c54ad103d0 100644 --- a/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems +++ b/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems @@ -14,9 +14,13 @@ + + Create + + diff --git a/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems.filters b/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems.filters index 88190feb51..ad59ef46fa 100644 --- a/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems.filters +++ b/source/uwp/SharedObjectModel/SharedObjectModel.vcxitems.filters @@ -240,6 +240,12 @@ lib + + lib + + + lib + @@ -473,5 +479,11 @@ lib + + lib + + + lib + \ No newline at end of file diff --git a/source/uwp/SharedObjectModel/lib/AdaptiveCard.cpp b/source/uwp/SharedObjectModel/lib/AdaptiveCard.cpp index ef33548c8e..6969125eeb 100644 --- a/source/uwp/SharedObjectModel/lib/AdaptiveCard.cpp +++ b/source/uwp/SharedObjectModel/lib/AdaptiveCard.cpp @@ -36,7 +36,7 @@ namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::implementation try { ::AdaptiveCards::ParseContext context(sharedModelElementParserRegistration, sharedModelActionParserRegistration); - const std::string c_rendererVersion = "1.5"; + const std::string c_rendererVersion = "1.6"; auto sharedParseResult = ::AdaptiveCards::AdaptiveCard::DeserializeFromString(jsonString, c_rendererVersion, context); adaptiveParseResult->AdaptiveCard = *winrt::make_self(sharedParseResult->GetAdaptiveCard()); diff --git a/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.cpp b/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.cpp new file mode 100644 index 0000000000..e1bf9a59ce --- /dev/null +++ b/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.cpp @@ -0,0 +1,71 @@ +#include "pch.h" +#include "AdaptiveCarousel.h" +#include "AdaptiveCarousel.g.cpp" + +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::implementation +{ + AdaptiveCarousel::AdaptiveCarousel(const std::shared_ptr<::AdaptiveCards::Carousel>& sharedCarousel) + { + Pages = GenerateVectorProjection(sharedCarousel->GetPages()); + Rtl = sharedCarousel->GetRtl(); + + Orientation = static_cast( + sharedCarousel->GetOrientation().value_or(::AdaptiveCards::CarouselOrientation::Horizontal)); + Timer = sharedCarousel->GetTimer(); + HeightInPixels = sharedCarousel->GetHeightInPixels(); + InitialPage = sharedCarousel->GetInitialPage(); + AutoLoop = sharedCarousel->GetAutoLoop(); + + MinHeight = sharedCarousel->GetMinHeight(); + Rtl = sharedCarousel->GetRtl(); + Bleed = sharedCarousel->GetBleed(); + BleedDirection = static_cast(sharedCarousel->GetBleedDirection()); + SelectAction = GenerateActionProjection(sharedCarousel->GetSelectAction()); + Style = static_cast(sharedCarousel->GetStyle()); + VerticalContentAlignment = opt_cast(sharedCarousel->GetVerticalContentAlignment()); + + auto backgroundImage = sharedCarousel->GetBackgroundImage(); + if (backgroundImage && !backgroundImage->GetUrl().empty()) + { + BackgroundImage = winrt::make(backgroundImage); + } + + InitializeBaseElement(sharedCarousel); + } + + std::shared_ptr<::AdaptiveCards::BaseCardElement> AdaptiveCarousel::GetSharedModel() + { + auto carousel = std::make_shared<::AdaptiveCards::Carousel>(); + CopySharedElementProperties(*carousel); + + carousel->GetPages() = GenerateSharedVector(Pages.get()); + carousel->SetRtl(Rtl); + carousel->SetOrientation(static_cast<::AdaptiveCards::CarouselOrientation>(Orientation.get())); + carousel->SetTimer(Timer); + carousel->SetHeightInPixels(HeightInPixels); + carousel->SetInitialPage(InitialPage); + carousel->setAutoLoop(AutoLoop); + carousel->SetBleed(Bleed); + carousel->SetMinHeight(MinHeight); + + if (SelectAction.get()) + { + carousel->SetSelectAction(GenerateSharedAction(SelectAction.get())); + } + + if (VerticalContentAlignment) + { + carousel->SetVerticalContentAlignment(VerticalContentAlignment.get<::AdaptiveCards::VerticalContentAlignment>()); + } + + if (auto adaptiveBackgroundImage = peek_innards(BackgroundImage.get())) + { + if (auto sharedBackgroundImage = adaptiveBackgroundImage->GetSharedModel()) + { + carousel->SetBackgroundImage(sharedBackgroundImage); + } + } + + return carousel; + } +} diff --git a/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.h b/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.h new file mode 100644 index 0000000000..d3e2b4a675 --- /dev/null +++ b/source/uwp/SharedObjectModel/lib/AdaptiveCarousel.h @@ -0,0 +1,45 @@ +#pragma once +#include "AdaptiveCarousel.g.h" +#include "AdaptiveCarouselPage.h" +#include "AdaptiveBackgroundImage.h" +#include "Carousel.h" + +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::implementation +{ + struct DECLSPEC_UUID("BF10C7E9-E525-4EFB-9F1E-CCE6ABB1C226") AdaptiveCarousel : AdaptiveCarouselT, AdaptiveCardElementBase + { + AdaptiveCarousel(const std::shared_ptr<::AdaptiveCards::Carousel>& + sharedcontainer = std::make_shared<::AdaptiveCards::Carousel>()); + + property> Pages; + + property Orientation; + property HeightInPixels; + property_opt Timer; + property_opt InitialPage; + property_opt AutoLoop; + property MinHeight; + + property_opt Rtl; + property Bleed; + property BleedDirection; + property SelectAction; + property Style; + property BackgroundImage{nullptr}; + property_opt VerticalContentAlignment; + + // IAdaptiveCardElement + auto ElementType() { return Xaml_OM::ElementType::Carousel; } + + virtual std::shared_ptr<::AdaptiveCards::BaseCardElement> GetSharedModel() override; + + // ITypePeek method + void* PeekAt(REFIID riid) override { return PeekHelper(riid, this); } + }; +} +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::factory_implementation +{ + struct AdaptiveCarousel : AdaptiveCarouselT + { + }; +} diff --git a/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.cpp b/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.cpp new file mode 100644 index 0000000000..0d9ee81866 --- /dev/null +++ b/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.cpp @@ -0,0 +1,59 @@ +#include "pch.h" +#include "AdaptiveCarouselPage.h" +#include "AdaptiveCarouselPage.g.cpp" + +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::implementation +{ + AdaptiveCarouselPage::AdaptiveCarouselPage(const std::shared_ptr<::AdaptiveCards::CarouselPage>& sharedCarouselPage) + { + VerticalContentAlignment = opt_cast(sharedCarouselPage->GetVerticalContentAlignment()); + Items = GenerateContainedElementsProjection(sharedCarouselPage->GetItems()); + SelectAction = GenerateActionProjection(sharedCarouselPage->GetSelectAction()); + Style = static_cast(sharedCarouselPage->GetStyle()); + MinHeight = sharedCarouselPage->GetMinHeight(); + Bleed = sharedCarouselPage->GetBleed(); + BleedDirection = static_cast(sharedCarouselPage->GetBleedDirection()); + Rtl = sharedCarouselPage->GetRtl(); + + auto backgroundImage = sharedCarouselPage->GetBackgroundImage(); + if (backgroundImage && !backgroundImage->GetUrl().empty()) + { + BackgroundImage = winrt::make(backgroundImage); + } + + InitializeBaseElement(sharedCarouselPage); + } + + std::shared_ptr<::AdaptiveCards::BaseCardElement> AdaptiveCarouselPage::GetSharedModel() + { + auto carouselPage = std::make_shared<::AdaptiveCards::Container>(); + CopySharedElementProperties(*carouselPage); + + if (SelectAction.get()) + { + carouselPage->SetSelectAction(GenerateSharedAction(SelectAction.get())); + } + + if (VerticalContentAlignment) + { + carouselPage->SetVerticalContentAlignment(VerticalContentAlignment.get<::AdaptiveCards::VerticalContentAlignment>()); + } + + carouselPage->SetStyle(static_cast<::AdaptiveCards::ContainerStyle>(Style.get())); + carouselPage->SetMinHeight(MinHeight); + + if (auto adaptiveBackgroundImage = peek_innards(BackgroundImage.get())) + { + if (auto sharedBackgroundImage = adaptiveBackgroundImage->GetSharedModel()) + { + carouselPage->SetBackgroundImage(sharedBackgroundImage); + } + } + + carouselPage->SetBleed(Bleed); + carouselPage->SetRtl(Rtl); + carouselPage->GetItems() = GenerateSharedElements(Items.get()); + + return carouselPage; + } +} diff --git a/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.h b/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.h new file mode 100644 index 0000000000..92b21dbcbe --- /dev/null +++ b/source/uwp/SharedObjectModel/lib/AdaptiveCarouselPage.h @@ -0,0 +1,42 @@ +#pragma once + +#include "AdaptiveBackgroundImage.h" +#include "AdaptiveCarouselPage.g.h" +#include "Carousel.h" + +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::implementation +{ + struct DECLSPEC_UUID("4DFACDD1-355B-40E0-AC89-5919022784D7") AdaptiveCarouselPage : + AdaptiveCarouselPageT, AdaptiveCardElementBase + { + AdaptiveCarouselPage(const std::shared_ptr<::AdaptiveCards::CarouselPage>& + sharedCarouselPage = std::make_shared<::AdaptiveCards::CarouselPage>()); + + // IAdaptiveCardElement + auto ElementType() + { + return ElementType::CarouselPage; + } + + virtual std::shared_ptr<::AdaptiveCards::BaseCardElement> GetSharedModel() override; + + // ITypePeek method + void* PeekAt(REFIID riid) override { return PeekHelper(riid, this); } + + property> Items; + property SelectAction; + property Style; + property_opt VerticalContentAlignment; + property BackgroundImage{nullptr}; + property MinHeight; + property Bleed; + property BleedDirection; + property_opt Rtl; + }; +} +namespace winrt::AdaptiveCards::ObjectModel::Xaml_OM::factory_implementation +{ + struct AdaptiveCarouselPage : AdaptiveCarouselPageT + { + }; +} diff --git a/source/uwp/SharedObjectModel/lib/ObjectModelUtil.cpp b/source/uwp/SharedObjectModel/lib/ObjectModelUtil.cpp index 0284bd0fde..08ec6d160d 100644 --- a/source/uwp/SharedObjectModel/lib/ObjectModelUtil.cpp +++ b/source/uwp/SharedObjectModel/lib/ObjectModelUtil.cpp @@ -4,6 +4,8 @@ #include "AdaptiveActionParserRegistration.h" #include "AdaptiveActionSet.h" +#include "AdaptiveCarousel.h" +#include "AdaptiveCarouselPage.h" #include "AdaptiveColumn.h" #include "AdaptiveColumnSet.h" #include "AdaptiveContainer.h" @@ -125,6 +127,10 @@ std::shared_ptr GenerateSharedElement(winrt::Ada { case winrt::AdaptiveCards::ObjectModel::Xaml_OM::ElementType::ActionSet: return GetSharedModel(item); + case winrt::AdaptiveCards::ObjectModel::Xaml_OM::ElementType::Carousel: + return GetSharedModel(item); + case winrt::AdaptiveCards::ObjectModel::Xaml_OM::ElementType::CarouselPage: + return GetSharedModel(item); case winrt::AdaptiveCards::ObjectModel::Xaml_OM::ElementType::ChoiceSetInput: return GetSharedModel(item); case winrt::AdaptiveCards::ObjectModel::Xaml_OM::ElementType::Column: @@ -262,6 +268,12 @@ winrt::AdaptiveCards::ObjectModel::Xaml_OM::IAdaptiveCardElement GenerateElement case CardElementType::Image: return winrt::make( std::AdaptivePointerCast(baseElement)); + case CardElementType::Carousel: + return winrt::make( + std::AdaptivePointerCast(baseElement)); + case CardElementType::CarouselPage: + return winrt::make( + std::AdaptivePointerCast(baseElement)); case CardElementType::Container: return winrt::make( std::AdaptivePointerCast(baseElement)); diff --git a/source/uwp/SharedRenderer/SharedRenderer.vcxitems b/source/uwp/SharedRenderer/SharedRenderer.vcxitems index d5488e7713..15e1132bd1 100644 --- a/source/uwp/SharedRenderer/SharedRenderer.vcxitems +++ b/source/uwp/SharedRenderer/SharedRenderer.vcxitems @@ -25,6 +25,8 @@ + + @@ -110,6 +112,8 @@ + + diff --git a/source/uwp/SharedRenderer/SharedRenderer.vcxitems.filters b/source/uwp/SharedRenderer/SharedRenderer.vcxitems.filters index 43a15d6694..dd325372e4 100644 --- a/source/uwp/SharedRenderer/SharedRenderer.vcxitems.filters +++ b/source/uwp/SharedRenderer/SharedRenderer.vcxitems.filters @@ -261,6 +261,12 @@ lib + + lib + + + lib + @@ -504,5 +510,11 @@ lib + + lib + + + lib + \ No newline at end of file diff --git a/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.cpp new file mode 100644 index 0000000000..457fd0dc66 --- /dev/null +++ b/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.cpp @@ -0,0 +1,22 @@ +#include "pch.h" + +#include "ActionHelpers.h" +#include "AdaptiveCarouselPageRenderer.h" +#include "AdaptiveCarouselPageRenderer.g.cpp" +#include "AdaptiveRenderArgs.h" + +#include "WholeItemsPanel.h" + +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation +{ + winrt::UIElement AdaptiveCarouselPageRenderer::Render( + winrt::IAdaptiveCardElement const& cardElement, + winrt::AdaptiveRenderContext const& renderContext, + winrt::AdaptiveRenderArgs const& renderArgs) + { + // Carousel Page is just a Container + // Added the renderer here anyway for future bifurcation + auto containerRenderer = renderContext.ElementRenderers().Get(L"Container"); + return containerRenderer.Render(cardElement, renderContext, renderArgs); + } +} diff --git a/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.h b/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.h new file mode 100644 index 0000000000..e19e2e5b2c --- /dev/null +++ b/source/uwp/SharedRenderer/lib/AdaptiveCarouselPageRenderer.h @@ -0,0 +1,21 @@ +#pragma once +#include "AdaptiveCarouselPageRenderer.g.h" + +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation +{ + struct AdaptiveCarouselPageRenderer : AdaptiveCarouselPageRendererT + { + AdaptiveCarouselPageRenderer() = default; + + winrt::UIElement Render( + winrt::AdaptiveCards::ObjectModel::Xaml_Rendering::IAdaptiveCardElement const& element, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderContext const& context, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderArgs const& renderArgs); + }; +} +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::factory_implementation +{ + struct AdaptiveCarouselPageRenderer : AdaptiveCarouselPageRendererT + { + }; +} diff --git a/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.cpp new file mode 100644 index 0000000000..64cb0a3ede --- /dev/null +++ b/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.cpp @@ -0,0 +1,221 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#include "pch.h" +#include "ActionHelpers.h" +#include "AdaptiveCarouselRenderer.h" +#include "AdaptiveCarouselRenderer.g.cpp" +#include "AdaptiveRenderArgs.h" +#include "WholeItemsPanel.h" +#include "XamlBuilder.h" +#include + +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation +{ + winrt::UIElement AdaptiveCarouselRenderer::Render( + winrt::AdaptiveCards::ObjectModel::Xaml_Rendering::IAdaptiveCardElement const& element, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderContext const& context, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderArgs const& renderArgs) + { + auto carousel = element.as(); + auto styledCollection = element.as(); + + StackPanel stackPanel{}; + FlipView carouselUI{}; + bool loopEnabled{false}; + + if (carousel.AutoLoop()) + { + loopEnabled = carousel.AutoLoop().GetBoolean(); + } + +// WinUI3 is currently the primary target for Carousel. +// Carousel is compatible with UWP; however, pagination is not supported. +#ifdef USE_WINUI3 + PipsPager pipsPager{}; + pipsPager.HorizontalAlignment(winrt::HorizontalAlignment::Center); + pipsPager.NumberOfPages(carousel.Pages().Size()); +#endif + auto hostConfig = context.HostConfig(); + + // FlipView has its own background color property, so we need to clear the background color + carouselUI.Background(winrt::SolidColorBrush{GetColorFromString("#00FFFFFF")}); + + //auto adaptiveCarouselContainer = element.as(); + // Get any RTL setting set on either the current context or on this container. Any value set on the + // container should be set on the context to apply to all children + auto previousContextRtl = context.Rtl(); + auto currentRtl = previousContextRtl; + auto containerRtl = carousel.Rtl(); + + bool updatedRtl = false; + if (containerRtl) + { + currentRtl = containerRtl; + context.Rtl(currentRtl); + updatedRtl = true; + } + + if (currentRtl) + { + carouselUI.FlowDirection(currentRtl.GetBoolean() ? winrt::FlowDirection::RightToLeft : winrt::FlowDirection::LeftToRight); +#ifdef USE_WINUI3 + pipsPager.FlowDirection(currentRtl.GetBoolean() ? winrt::FlowDirection::RightToLeft : winrt::FlowDirection::LeftToRight); +#endif + } + +#ifdef USE_WINUI3 + carouselUI.SelectionChanged([carouselUI, pipsPager, loopEnabled](auto &&, auto &&) { + auto val = carouselUI.SelectedIndex(); + if (loopEnabled && + static_cast(val) == carouselUI.Items().Size()) + { + pipsPager.SelectedPageIndex(0); + carouselUI.SelectedIndex(0); + } + else + { + pipsPager.SelectedPageIndex(carouselUI.SelectedIndex()); + } + }); + + pipsPager.SelectedIndexChanged([carouselUI](winrt::PipsPager pager, winrt::IPipsPagerSelectedIndexChangedEventArgs) { + carouselUI.SelectedIndex(pager.SelectedPageIndex()); + }); +#endif + + stackPanel.Children().Append(carouselUI); + +#ifdef USE_WINUI3 + stackPanel.Children().Append(pipsPager); +#endif + + winrt::AdaptiveFeatureRegistration featureRegistration = context.FeatureRegistration(); + boolean ancestorHasFallback = renderArgs.AncestorHasFallback(); + + try + { + winrt::Border carouselBorder{}; + + auto gridContainer = winrt::make(); + + // Assign vertical alignment to strech so column will stretch and respect vertical content alignment + auto containerHeightType = element.Height(); + if (containerHeightType == winrt::HeightType::Auto) + { + gridContainer.VerticalAlignment(winrt::VerticalAlignment::Stretch); + } + + uint32_t carouselMinHeight = styledCollection.MinHeight(); + + if (carouselMinHeight > 0) + { + gridContainer.MinHeight(carouselMinHeight); + } + + auto fixedHeightInPixel = carousel.HeightInPixels(); + if (fixedHeightInPixel) + { + carouselUI.MaxHeight(static_cast(fixedHeightInPixel)); + } + + auto containerStyle = + XamlHelpers::HandleStylingAndPadding(styledCollection, carouselBorder, context, renderArgs); + + auto newRenderArgs = + winrt::make(containerStyle, renderArgs.ParentElement(), renderArgs); + + for (auto page : carousel.Pages()) + { + auto [carouselPageUI, carouselPage] = + ::AdaptiveCards::Rendering::Xaml_Rendering::XamlBuilder::RenderAsUIElement( + page, context, newRenderArgs, featureRegistration, ancestorHasFallback); + + if (carouselPageUI != nullptr) + { + carouselUI.Items().Append(carouselPageUI); + + if (fixedHeightInPixel == 0) + { + carouselPageUI.try_as().LayoutUpdated( + [carouselUI](auto&&, auto&&) { SetFlipViewMaxHeight(carouselUI); }); + } + } + } + + if (carousel.InitialPage()) + { + carouselUI.SelectedIndex(carousel.InitialPage().GetUInt32()); + } + + auto verticalContentAlignmentReference = carousel.VerticalContentAlignment(); + winrt::VerticalContentAlignment verticalContentAlignment = + GetValueFromRef(verticalContentAlignmentReference, winrt::VerticalContentAlignment::Top); + XamlHelpers::SetVerticalContentAlignmentToChildren(gridContainer, verticalContentAlignment); + + // Check if backgroundImage defined + auto backgroundImage = carousel.BackgroundImage(); + if (IsBackgroundImageValid(backgroundImage)) + { + winrt::Grid rootElement{}; + XamlHelpers::ApplyBackgroundToRoot(rootElement, backgroundImage, context); + + // Add rootElement to containerBorder + carouselBorder.Child(rootElement); + + // Add containerPanel to rootElement + XamlHelpers::AppendXamlElementToPanel(gridContainer, rootElement, containerHeightType); + } + else + { + // instead, directly add containerPanel to containerBorder + carouselBorder.Child(gridContainer); + } + + // If we changed the context's rtl setting, set it back after rendering the children + if (updatedRtl) + { + context.Rtl(previousContextRtl); + } + + XamlHelpers::SetStyleFromResourceDictionary(context, L"Adaptive.Carousel", carouselUI); + + auto adaptiveBaseElement = element.try_as(); + auto heightType = adaptiveBaseElement.Height(); + XamlHelpers::AppendXamlElementToPanel(stackPanel, gridContainer, heightType); + + auto selectAction = styledCollection.SelectAction(); + return ::AdaptiveCards::Rendering::Xaml_Rendering::ActionHelpers::HandleSelectAction( + element, selectAction, context, carouselBorder, XamlHelpers::SupportsInteractivity(hostConfig), true); + } + catch (winrt::hresult_error const& ex) + { + // In case we need to perform fallback, propagate it up to the parent + if (ex.code() == E_PERFORM_FALLBACK) + { + throw ex; + } + + XamlHelpers::ErrForRenderFailedForElement(context, element.ElementTypeString(), ex.message()); + } + return nullptr; + } + + void SetFlipViewMaxHeight(FlipView const& flipView) + { + auto selectIndex = flipView.SelectedIndex(); + auto carouselPageUI = flipView.Items().GetAt(selectIndex).try_as(); + + if (flipView.IsLoaded()) + { + float width = static_cast(flipView.ActualWidth()); + const winrt::Size noVerticalLimit{width, std::numeric_limits::infinity()}; + carouselPageUI.Measure(noVerticalLimit); + auto maxHeight = carouselPageUI.DesiredSize().Height; + auto previousMaxHeight = flipView.MaxHeight(); + if ((std::numeric_limits::infinity() == previousMaxHeight) || previousMaxHeight < maxHeight) + { + flipView.MaxHeight(maxHeight); + } + } + } +} diff --git a/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.h b/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.h new file mode 100644 index 0000000000..9b02932c02 --- /dev/null +++ b/source/uwp/SharedRenderer/lib/AdaptiveCarouselRenderer.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#pragma once +#include "AdaptiveCarouselRenderer.g.h" + +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation +{ + struct AdaptiveCarouselRenderer : AdaptiveCarouselRendererT + { + AdaptiveCarouselRenderer() = default; + AdaptiveCarouselRenderer(winrt::com_ptr<::AdaptiveCards::Rendering::Xaml_Rendering::XamlBuilder> xamlBuilder) : + m_xamlBuilder(xamlBuilder){}; + + winrt::UIElement Render( + winrt::AdaptiveCards::ObjectModel::Xaml_Rendering::IAdaptiveCardElement const& element, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderContext const& context, + winrt::AdaptiveCards::Rendering::Xaml_Rendering::AdaptiveRenderArgs const& renderArgs); + + winrt::com_ptr<::AdaptiveCards::Rendering::Xaml_Rendering::XamlBuilder> GetXamlBuilder() { return m_xamlBuilder; } + + private: + winrt::com_ptr<::AdaptiveCards::Rendering::Xaml_Rendering::XamlBuilder> m_xamlBuilder; + }; +} +namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::factory_implementation +{ + struct AdaptiveCarouselRenderer : AdaptiveCarouselRendererT + { + }; +} diff --git a/source/uwp/SharedRenderer/lib/ImageLoadTracker.cpp b/source/uwp/SharedRenderer/lib/ImageLoadTracker.cpp index 86f8b22fc3..b6fc0eebfa 100644 --- a/source/uwp/SharedRenderer/lib/ImageLoadTracker.cpp +++ b/source/uwp/SharedRenderer/lib/ImageLoadTracker.cpp @@ -34,7 +34,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering auto trackedImageDetails = winrt::make_self(); trackedImageDetails->imageOpenedRevoker = - bitmapImage.ImageOpened(winrt::auto_revoke, {this, &ImageLoadTracker::TrackedImage_BitmapImageLoaded}); + bitmapImage.ImageOpened(winrt::auto_revoke, {get_weak(), &ImageLoadTracker::TrackedImage_BitmapImageLoaded}); trackedImageDetails->imageFailedRevoker = bitmapImage.ImageFailed(winrt::auto_revoke, {this, &ImageLoadTracker::TrackedImage_BitmapImageFailed}); diff --git a/source/uwp/SharedRenderer/lib/Util.cpp b/source/uwp/SharedRenderer/lib/Util.cpp index f185b0e2f9..9a02c6dfde 100644 --- a/source/uwp/SharedRenderer/lib/Util.cpp +++ b/source/uwp/SharedRenderer/lib/Util.cpp @@ -5,6 +5,8 @@ #include #include "AdaptiveActionSetRenderer.h" +#include "AdaptiveCarouselRenderer.h" +#include "AdaptiveCarouselPageRenderer.h" #include "AdaptiveColumnRenderer.h" #include "AdaptiveColumnSetRenderer.h" #include "AdaptiveContainerRenderer.h" @@ -610,6 +612,8 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering winrt::com_ptr xamlBuilder) { registration->Set(L"ActionSet", winrt::make()); + registration->Set(L"Carousel", winrt::make(xamlBuilder)); + registration->Set(L"CarouselPage", winrt::make()); registration->Set(L"Column", winrt::make()); registration->Set(L"ColumnSet", winrt::make()); registration->Set(L"Container", winrt::make()); diff --git a/source/uwp/SharedRenderer/lib/XamlBuilder.cpp b/source/uwp/SharedRenderer/lib/XamlBuilder.cpp index 788cf60eaa..3f4f8bdefe 100644 --- a/source/uwp/SharedRenderer/lib/XamlBuilder.cpp +++ b/source/uwp/SharedRenderer/lib/XamlBuilder.cpp @@ -259,66 +259,91 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering } } - void XamlBuilder::BuildPanelChildren(winrt::IVector const& children, - winrt::Panel parentPanel, - winrt::AdaptiveRenderContext renderContext, - winrt::AdaptiveRenderArgs renderArgs, - std::function childCreatedCallback) + void XamlBuilder::ShouldFallback( + winrt::IAdaptiveCardElement const& element, + winrt::IAdaptiveElementRenderer const& elementRenderer, + winrt::AdaptiveRenderArgs const& renderArgs, + winrt::AdaptiveFeatureRegistration const& featureRegistration, + boolean ancestorHasFallback) { - int iElement = 0; - boolean ancestorHasFallback = renderArgs.AncestorHasFallback(); - winrt::AdaptiveFeatureRegistration featureRegistration = renderContext.FeatureRegistration(); - for (auto element : children) + winrt::FallbackType elementFallback = element.FallbackType(); + bool elementHasFallback = elementFallback != winrt::FallbackType::None || ancestorHasFallback; + renderArgs.AncestorHasFallback(elementHasFallback); + // Check to see if element's requirements are being met + bool shouldFallback = featureRegistration && !MeetsRequirements(element, featureRegistration); + if (!elementRenderer || shouldFallback) { - // Get fallback state - winrt::FallbackType elementFallback = element.FallbackType(); - bool elementHasFallback = elementFallback != winrt::FallbackType::None || ancestorHasFallback; - renderArgs.AncestorHasFallback(elementHasFallback); - - // Check to see if element's requirements are being met - bool shouldFallback = featureRegistration && !MeetsRequirements(element, featureRegistration); - auto elementRenderers = renderContext.ElementRenderers(); - winrt::hstring elementType = element.ElementTypeString(); - auto elementRenderer = elementRenderers.Get(elementType); - auto hostConfig = renderContext.HostConfig(); + throw winrt::hresult_error(E_PERFORM_FALLBACK); + } + } - winrt::UIElement newControl{nullptr}; - winrt::IAdaptiveCardElement renderedElement{nullptr}; - try + RenderedElementStruct XamlBuilder::RenderAsUIElement( + winrt::IAdaptiveCardElement const& element, + winrt::AdaptiveRenderContext const&renderContext, + winrt::AdaptiveRenderArgs const&renderArgs, + winrt::AdaptiveFeatureRegistration const& featureRegistration, + bool ancestorHasFallback) + { + winrt::UIElement newControl{nullptr}; + winrt::IAdaptiveCardElement renderedElement{nullptr}; + + try + { + auto elementRenderer = renderContext.ElementRenderers().Get(element.ElementTypeString()); + + ShouldFallback( + element, + elementRenderer, + renderArgs, + featureRegistration, + ancestorHasFallback); + + return {elementRenderer.Render(element, renderContext, renderArgs), element}; + + } + catch (winrt::hresult_error const& ex) + { + // We're only interested in fallback exception + if (ex.code() != E_PERFORM_FALLBACK) { - if (!elementRenderer || shouldFallback) - { - throw winrt::hresult_error(E_PERFORM_FALLBACK); - } + throw ex; + } - newControl = elementRenderer.Render(element, renderContext, renderArgs); - renderedElement = element; + try + { + std::tie(newControl, renderedElement) = XamlHelpers::RenderFallback(element, renderContext, renderArgs); } catch (winrt::hresult_error const& ex) { - // We're only interested in fallback exception - if (ex.code() != E_PERFORM_FALLBACK) + // if we get an E_PERFORM_FALLBACK error again, we should only throw it if `ancestorHasFallBack` + if (ex.code() != E_PERFORM_FALLBACK || (ex.code() == E_PERFORM_FALLBACK && ancestorHasFallback)) { throw ex; } - - try - { - std::tie(newControl, renderedElement) = XamlHelpers::RenderFallback(element, renderContext, renderArgs); - } - catch (winrt::hresult_error const& ex) - { - // if we get an E_PERFORM_FALLBACK error again, we should only throw it if `ancestorHasFallBack` - if (ex.code() != E_PERFORM_FALLBACK || (ex.code() == E_PERFORM_FALLBACK && ancestorHasFallback)) - { - throw ex; - } - } } + } + + return {}; + } + + void XamlBuilder::BuildPanelChildren(winrt::IVector const& children, + winrt::Panel parentPanel, + winrt::AdaptiveRenderContext renderContext, + winrt::AdaptiveRenderArgs renderArgs, + std::function childCreatedCallback) + { + int iElement = 0; + boolean ancestorHasFallback = renderArgs.AncestorHasFallback(); + winrt::AdaptiveFeatureRegistration featureRegistration = renderContext.FeatureRegistration(); + for (auto element : children) + { + auto [newControl, renderedElement] = + RenderAsUIElement(element, renderContext, renderArgs, featureRegistration, ancestorHasFallback); // If we got a control, add a separator if needed and the control to the parent panel if (newControl) { + auto hostConfig = renderContext.HostConfig(); auto separator = XamlHelpers::AddSeparatorIfNeeded(iElement, element, hostConfig, renderContext, parentPanel); // If the renderedElement was an input, render the label and error message diff --git a/source/uwp/SharedRenderer/lib/XamlBuilder.h b/source/uwp/SharedRenderer/lib/XamlBuilder.h index e4cffc56a7..0a65717491 100644 --- a/source/uwp/SharedRenderer/lib/XamlBuilder.h +++ b/source/uwp/SharedRenderer/lib/XamlBuilder.h @@ -8,6 +8,12 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering { + struct RenderedElementStruct + { + winrt::UIElement renderedUI {nullptr}; + winrt::IAdaptiveCardElement adaptiveElement {nullptr}; + }; + struct XamlBuilder : winrt::implements { public: @@ -49,7 +55,15 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering winrt::AdaptiveRenderContext const& renderContext, winrt::AdaptiveRenderArgs const& renderArgs); + static RenderedElementStruct RenderAsUIElement( + winrt::IAdaptiveCardElement const& element, + winrt::AdaptiveRenderContext const& renderContext, + winrt::AdaptiveRenderArgs const& renderArgs, + winrt::AdaptiveFeatureRegistration const& featureRegistration, + bool ancestorHasFallback); + private: + winrt::com_ptr m_imageLoadTracker; std::set m_listeners; std::vector> m_getStreamOperations; @@ -117,5 +131,11 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering void SetRasterizedPixelHeight(winrt::ImageSource const& imageSource, double const& imageSize); void SetRasterizedPixelWidth(winrt::ImageSource const& imageSource, double const& imageSize); + + static void ShouldFallback(winrt::IAdaptiveCardElement const& element, + winrt::IAdaptiveElementRenderer const& elementRenderer, + winrt::AdaptiveRenderArgs const& renderArgs, + winrt::AdaptiveFeatureRegistration const& featureRegistration, + boolean ancestorHasFallback); }; } diff --git a/source/uwp/SharedVisualizer/ViewModel/DocumentViewModel.cs b/source/uwp/SharedVisualizer/ViewModel/DocumentViewModel.cs index ab41d6f8f6..d15027a0a3 100644 --- a/source/uwp/SharedVisualizer/ViewModel/DocumentViewModel.cs +++ b/source/uwp/SharedVisualizer/ViewModel/DocumentViewModel.cs @@ -263,7 +263,7 @@ public static void InitializeRenderer(AdaptiveHostConfig hostConfig) if (Settings.UseFixedDimensions) { - _renderer.SetFixedDimensions(320, 180); + _renderer.SetFixedDimensions(320, 220); } // Custom resource resolvers diff --git a/source/uwp/SharedVisualizer/Views/DocumentView.xaml b/source/uwp/SharedVisualizer/Views/DocumentView.xaml index d05f22cb90..7fb512771f 100644 --- a/source/uwp/SharedVisualizer/Views/DocumentView.xaml +++ b/source/uwp/SharedVisualizer/Views/DocumentView.xaml @@ -13,7 +13,7 @@ - + diff --git a/source/uwp/winui3/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.WinUI3.idl b/source/uwp/winui3/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.WinUI3.idl index 7104fddf22..52a9d6d48c 100644 --- a/source/uwp/winui3/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.WinUI3.idl +++ b/source/uwp/winui3/AdaptiveCardsObjectModel/idl/AdaptiveCards.ObjectModel.WinUI3.idl @@ -60,6 +60,8 @@ namespace AdaptiveCards.ObjectModel.WinUI3 AdaptiveCard, TextBlock, Image, + Carousel, + CarouselPage, Container, Column, ColumnSet, @@ -255,6 +257,12 @@ namespace AdaptiveCards.ObjectModel.WinUI3 MenuItem }; + enum CarouselOrientation + { + Horizontal = 0, + Vertical, + }; + declare { interface Windows.Foundation.Collections.IVector; } interface IAdaptiveCardElement @@ -590,6 +598,25 @@ namespace AdaptiveCards.ObjectModel.WinUI3 Windows.Foundation.Collections.IVector Columns { get; }; }; + [default_interface] runtimeclass AdaptiveCarouselPage : IAdaptiveContainer, IAdaptiveContainerBase, IAdaptiveCardElement + { + AdaptiveCarouselPage(); + }; + + runtimeclass AdaptiveCarousel : IAdaptiveContainerBase, IAdaptiveCardElement + { + AdaptiveCarousel(); + Windows.Foundation.Collections.IVector Pages { get; }; + CarouselOrientation Orientation; + Windows.Foundation.IReference Timer; + Windows.Foundation.IReference InitialPage; + Windows.Foundation.IReference AutoLoop; + Windows.Foundation.IReference VerticalContentAlignment; + Windows.Foundation.IReference Rtl; + AdaptiveBackgroundImage BackgroundImage; + UInt32 HeightInPixels; + }; + runtimeclass AdaptiveFact { AdaptiveFact(); @@ -871,4 +898,4 @@ namespace AdaptiveCards.ObjectModel.WinUI3 WarningStatusCode StatusCode; String Message; }; -} \ No newline at end of file +} diff --git a/source/uwp/winui3/Renderer/idl/AdaptiveCards.Rendering.WinUI3.idl b/source/uwp/winui3/Renderer/idl/AdaptiveCards.Rendering.WinUI3.idl index ae50a342a8..4672530676 100644 --- a/source/uwp/winui3/Renderer/idl/AdaptiveCards.Rendering.WinUI3.idl +++ b/source/uwp/winui3/Renderer/idl/AdaptiveCards.Rendering.WinUI3.idl @@ -550,6 +550,16 @@ namespace AdaptiveCards AdaptiveImageSetRenderer(); } + [default_interface] runtimeclass AdaptiveCarouselRenderer : IAdaptiveElementRenderer + { + AdaptiveCarouselRenderer(); + } + + [default_interface] runtimeclass AdaptiveCarouselPageRenderer : IAdaptiveElementRenderer + { + AdaptiveCarouselPageRenderer(); + } + [default_interface] runtimeclass AdaptiveContainerRenderer : IAdaptiveElementRenderer { AdaptiveContainerRenderer(); diff --git a/source/uwp/winui3/Visualizer/Properties/launchSettings.json b/source/uwp/winui3/Visualizer/Properties/launchSettings.json index 4da1a4fc07..98c20e9344 100644 --- a/source/uwp/winui3/Visualizer/Properties/launchSettings.json +++ b/source/uwp/winui3/Visualizer/Properties/launchSettings.json @@ -1,7 +1,8 @@ { "profiles": { "AdaptiveCardVisualizer (Package)": { - "commandName": "MsixPackage" + "commandName": "MsixPackage", + "nativeDebugging": true }, "AdaptiveCardVisualizer (Unpackaged)": { "commandName": "Project"