This commit is contained in:
Alexander Sklar 2021-02-15 17:25:19 -08:00
Родитель cd02c4f5c8
Коммит 132f89ac04
4 изменённых файлов: 51 добавлений и 46 удалений

Просмотреть файл

@ -6,7 +6,7 @@ using namespace winrt::Microsoft::ReactNative;
#define MAKE_GET_DP(type, prop) IsType<type>, []() { return type::prop(); }
//ctx.DispatchEvent(sender.as<xaml::FrameworkElement>(), L"top" L#evtName, [](auto const& evtDataWriter) noexcept {}); \
//ctx.DispatchEvent(sender.as<xaml::FrameworkElement>(), L"top" L#evtName, [](auto const& evtDataWriter) noexcept {}); \
#define MAKE_EVENT(evtName, xamlType) \
{ #evtName, { [](IInspectable o, IReactContext reactContext) { \
@ -17,7 +17,11 @@ using namespace winrt::Microsoft::ReactNative;
} \
} } }
const std::map<std::string, std::function<void(IInspectable o, IReactContext context)> > XamlMetadata::xamlEventMap = {
#define CREATE_TYPE(T) [](){return T();}
XamlMetadata::XamlMetadata() {
xamlEventMap = {
MAKE_EVENT(Click, xaml::Controls::Primitives::ButtonBase),
// { "Click", { [](IInspectable o, IReactContext context) {
// if (auto c = o.try_as<xaml::Controls::Primitives::ButtonBase>()) {
@ -26,7 +30,7 @@ using namespace winrt::Microsoft::ReactNative;
//}} } }
};
const std::multimap<std::string, PropInfo> XamlMetadata::xamlPropertyMap = {
xamlPropertyMap = {
{ "width", { MAKE_GET_DP(FrameworkElement, WidthProperty), FromJSType::Double, XamlPropType::Double }},
{ "height", { MAKE_GET_DP(FrameworkElement, HeightProperty), FromJSType::Double, XamlPropType::Double }},
{ "text", { MAKE_GET_DP(ContentControl, ContentProperty), FromJSType::String, XamlPropType::Object }},
@ -36,19 +40,34 @@ using namespace winrt::Microsoft::ReactNative;
{ "backgroundColor", { MAKE_GET_DP(Control, BackgroundProperty), FromJSType::SolidColorBrush, XamlPropType::Object }},
};
const PropInfo* XamlMetadata::GetProp(const std::string& propertyName, const IInspectable& obj) {
auto propRange = xamlPropertyMap.equal_range(propertyName);
for (auto prop = propRange.first; prop != propRange.second; ++prop)
{
if (prop->second.isType(obj)) { return &(prop->second); }
}
return nullptr;
}
#define CREATE_TYPE(T) [](){return T();}
const std::map<std::string, std::function<xaml::DependencyObject()>> XamlMetadata::xamlTypeCreatorMap = {
{ "hyperlinkButton", CREATE_TYPE(HyperlinkButton)},
{ "textblock", CREATE_TYPE(TextBlock)},
xamlTypeCreatorMap = {
{ "hyperlinkButton", CREATE_TYPE(HyperlinkButton)},
{ "textblock", CREATE_TYPE(TextBlock)},
};
}
winrt::Windows::Foundation::IInspectable XamlMetadata::Create(const std::string& typeName, const winrt::Microsoft::ReactNative::IReactContext& context) {
if (xamlTypeCreatorMap.count(typeName) != 0) {
auto creator = xamlTypeCreatorMap.at(typeName);
auto e = creator();
// Register events
std::for_each(xamlEventMap.begin(), xamlEventMap.end(), [e, context](const auto& entry) {entry.second(e, context); });
return e;
}
else {
assert(false && "xaml type not found");
throw std::invalid_argument("xaml type not found");
}
}
const PropInfo* XamlMetadata::GetProp(const std::string& propertyName, const IInspectable& obj) {
auto propRange = xamlPropertyMap.equal_range(propertyName);
for (auto prop = propRange.first; prop != propRange.second; ++prop)
{
if (prop->second.isType(obj)) { return &(prop->second); }
}
return nullptr;
}

Просмотреть файл

@ -2,6 +2,7 @@
#include <pch.h>
#include <winrt/base.h>
#include <functional>
#include <string>
#include <JSValue.h>
#include <JSValueReader.h>
#include <JSValueXaml.h>
@ -107,8 +108,11 @@ private:
};
struct XamlMetadata {
static const std::map<std::string, std::function<xaml::DependencyObject()>> xamlTypeCreatorMap;
static const std::multimap<std::string, PropInfo> xamlPropertyMap;
static const std::map<std::string, std::function<void(IInspectable o, winrt::Microsoft::ReactNative::IReactContext context)> > xamlEventMap;
static const PropInfo* GetProp(const std::string& propertyName, const IInspectable& obj);
winrt::Windows::Foundation::IInspectable Create(const std::string& typeName, const winrt::Microsoft::ReactNative::IReactContext& context);
XamlMetadata();
const PropInfo* GetProp(const std::string& propertyName, const IInspectable& obj);
std::map<std::string, std::function<xaml::DependencyObject()>> xamlTypeCreatorMap;
std::multimap<std::string, PropInfo> xamlPropertyMap;
std::map<std::string, std::function<void(IInspectable o, winrt::Microsoft::ReactNative::IReactContext context)> > xamlEventMap;
};

Просмотреть файл

@ -39,19 +39,7 @@ namespace winrt::ReactNativeXaml {
winrt::IInspectable XamlViewManager::CreateViewWithProperties(winrt::Microsoft::ReactNative::IJSValueReader const& propertyMapReader) noexcept {
const JSValueObject& propertyMap = JSValue::ReadObjectFrom(propertyMapReader);
auto typeName = propertyMap["type"].AsString();
if (XamlMetadata::xamlTypeCreatorMap.count(typeName) != 0) {
auto creator = XamlMetadata::xamlTypeCreatorMap.at(typeName);
auto e = creator();
//e.as<FrameworkElement>().Tag(delegating.Tag()); // event dispatching needs to have the xaml event sender have a tag
// Register events
std::for_each(XamlMetadata::xamlEventMap.begin(), XamlMetadata::xamlEventMap.end(), [e, context = this->m_reactContext](const auto& entry) {entry.second(e, context); });
return e;
}
else {
assert(false && "xaml type not found");
VerifyElseCrash(false);
}
return xamlMetadata.Create(typeName, m_reactContext);
}
// IViewManagerWithNativeProperties
@ -79,17 +67,9 @@ namespace winrt::ReactNativeXaml {
if (!e) {
if (propertyMap.count("type") != 0) {
const auto typeName = propertyMap["type"].AsString();
if (XamlMetadata::xamlTypeCreatorMap.count(typeName) != 0) {
auto creator = XamlMetadata::xamlTypeCreatorMap.at(typeName);
e = creator();
e.as<FrameworkElement>().Tag(delegating.Tag()); // event dispatching needs to have the xaml event sender have a tag
// Register events
std::for_each(XamlMetadata::xamlEventMap.begin(), XamlMetadata::xamlEventMap.end(), [e, context = ReactContext()](const auto& entry) {entry.second(e, context); });
delegating.Content(e);
}
else {
assert(false && "xaml type not found");
}
e = xamlMetadata.Create(typeName, m_reactContext);
e.as<FrameworkElement>().Tag(delegating.Tag()); // event dispatching needs to have the xaml event sender have a tag
delegating.Content(e);
}
else {
assert(false && "xaml type not specified");
@ -102,7 +82,7 @@ namespace winrt::ReactNativeXaml {
auto const& propertyName = pair.first;
auto const& propertyValue = pair.second;
if (auto prop = XamlMetadata::GetProp(propertyName, control)) {
if (auto prop = xamlMetadata.GetProp(propertyName, control)) {
prop->SetValue(control, propertyValue);
}
else if (propertyName == "type") {}

Просмотреть файл

@ -3,6 +3,7 @@
#include "pch.h"
#include "CppWinRTIncludes.h"
#include "winrt/Microsoft.ReactNative.h"
#include "XamlMetadata.h"
// Required to avoid creating unnecessary ContentControls to hold dynamically-typed ui elements
// https://github.com/microsoft/react-native-windows/pull/7137
@ -63,6 +64,7 @@ namespace winrt::ReactNativeXaml {
bool RequiresNativeLayout() noexcept { return true; }
private:
winrt::Microsoft::ReactNative::IReactContext m_reactContext{ nullptr };
XamlMetadata xamlMetadata;
};
}