-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds test native module project for Playground (#10838)
* Adds test native module project for Playground The GitHub repo Playground projects are missing examples that exercise 3rd party APIs. While there are examples that use 3rd party extensions from NPM, there are some 3rd party APIs that are not used in ecosystem packages (yet). This native modules project gives us a place to prototype custom view managers and native modules. * Use LayoutService in NativeModule example Adds example that uses the LayoutService API that will be available in v0.71 * yarn format * Remove unnecessary NuGet package reference * Add PlaygroundNativeModules project to playground.sln * yarn lint:fix
- Loading branch information
Showing
26 changed files
with
774 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* Copyright (c) Microsoft Corporation. | ||
* Licensed under the MIT License. | ||
* @format | ||
*/ | ||
import React from 'react'; | ||
import {AppRegistry, View, Text, requireNativeComponent} from 'react-native'; | ||
|
||
const GridView: any = requireNativeComponent('PlaygroundGridView'); | ||
const GridItemView: any = requireNativeComponent('PlaygroundGridItemView'); | ||
|
||
function Bootstrap() { | ||
return ( | ||
<GridView | ||
style={{width: 200, height: 200}} | ||
columns={['*', '*']} | ||
rows={['*', '*']}> | ||
<GridItemView gridRow={0} gridColumn={0}> | ||
<View | ||
style={{ | ||
backgroundColor: '#F25022', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}}> | ||
<Text>1</Text> | ||
</View> | ||
</GridItemView> | ||
<GridItemView gridRow={0} gridColumn={1}> | ||
<View | ||
style={{ | ||
backgroundColor: '#7FBA00', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}}> | ||
<Text>2</Text> | ||
</View> | ||
</GridItemView> | ||
<GridItemView gridRow={1} gridColumn={0}> | ||
<View | ||
style={{ | ||
backgroundColor: '#00A4EF', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}}> | ||
<Text>3</Text> | ||
</View> | ||
</GridItemView> | ||
<GridItemView gridRow={1} gridColumn={1}> | ||
<View | ||
style={{ | ||
backgroundColor: '#FFB900', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}}> | ||
<Text>4</Text> | ||
</View> | ||
</GridItemView> | ||
</GridView> | ||
); | ||
} | ||
|
||
AppRegistry.registerComponent('Bootstrap', () => Bootstrap); |
30 changes: 30 additions & 0 deletions
30
packages/playground/windows/PlaygroundNativeModules/GridItemView.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "GridItemView.h" | ||
#include "GridItemView.g.cpp" | ||
|
||
namespace winrt { | ||
using namespace Microsoft::ReactNative; | ||
using namespace Windows::Foundation; | ||
using namespace xaml; | ||
using namespace xaml::Controls; | ||
} // namespace winrt | ||
|
||
namespace winrt::PlaygroundNativeModules::implementation { | ||
|
||
winrt::Size GridItemView::ArrangeOverride(winrt::Size availableSize) { | ||
const auto desiredSize = Super::ArrangeOverride(availableSize); | ||
if (Children().Size() > 0) { | ||
if (const auto child = Children().GetAt(0).try_as<xaml::FrameworkElement>()) { | ||
const auto reactTag = React::XamlHelper::GetReactTag(child); | ||
if (reactTag != -1) { | ||
React::LayoutService::FromContext(m_reactContext).ApplyLayout(reactTag, desiredSize.Width, desiredSize.Height); | ||
} | ||
} | ||
} | ||
return desiredSize; | ||
} | ||
|
||
} // namespace winrt::PlaygroundNativeModules::implementation |
26 changes: 26 additions & 0 deletions
26
packages/playground/windows/PlaygroundNativeModules/GridItemView.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#pragma once | ||
|
||
#include "GridItemView.g.h" | ||
#include "NativeModules.h" | ||
#include "winrt/Microsoft.ReactNative.h" | ||
|
||
namespace winrt::PlaygroundNativeModules::implementation { | ||
|
||
class GridItemView : public GridItemViewT<GridItemView> { | ||
using Super = GridItemViewT<GridItemView>; | ||
|
||
public: | ||
GridItemView(Microsoft::ReactNative::IReactContext const &reactContext) : m_reactContext{reactContext} {} | ||
virtual winrt::Windows::Foundation::Size ArrangeOverride(winrt::Windows::Foundation::Size availableSize); | ||
|
||
private: | ||
Microsoft::ReactNative::IReactContext m_reactContext{nullptr}; | ||
}; | ||
} // namespace winrt::PlaygroundNativeModules::implementation | ||
|
||
namespace winrt::PlaygroundNativeModules::factory_implementation { | ||
struct GridItemView : GridItemViewT<GridItemView, implementation::GridItemView> {}; | ||
} // namespace winrt::PlaygroundNativeModules::factory_implementation |
9 changes: 9 additions & 0 deletions
9
packages/playground/windows/PlaygroundNativeModules/GridItemView.idl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include <NamespaceRedirect.h> | ||
|
||
namespace PlaygroundNativeModules { | ||
|
||
[default_interface] | ||
runtimeclass GridItemView : XAML_NAMESPACE.Controls.Grid { | ||
GridItemView(Microsoft.ReactNative.IReactContext context); | ||
}; | ||
} // namespace PlaygroundNativeModules |
97 changes: 97 additions & 0 deletions
97
packages/playground/windows/PlaygroundNativeModules/GridItemViewManager.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "GridItemViewManager.h" | ||
#include "GridItemView.h" | ||
#include "JSValue.h" | ||
#include "JSValueXaml.h" | ||
|
||
namespace winrt { | ||
using namespace Windows::Foundation::Collections; | ||
} // namespace winrt | ||
|
||
namespace winrt::PlaygroundNativeModules { | ||
|
||
winrt::hstring GridItemViewManager::Name() noexcept { | ||
return L"PlaygroundGridItemView"; | ||
} | ||
|
||
xaml::FrameworkElement GridItemViewManager::CreateView() noexcept { | ||
return winrt::PlaygroundNativeModules::GridItemView(m_reactContext.Handle()); | ||
} | ||
|
||
React::IReactContext GridItemViewManager::ReactContext() noexcept { | ||
return m_reactContext.Handle(); | ||
} | ||
|
||
void GridItemViewManager::ReactContext(React::IReactContext reactContext) noexcept { | ||
m_reactContext = reactContext; | ||
} | ||
|
||
void GridItemViewManager::AddView( | ||
xaml::FrameworkElement const &parent, | ||
xaml::UIElement const &child, | ||
int64_t index) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
if (grid.Children().Size() > 0 || index != 0) { | ||
m_reactContext.CallJSFunction(L"RCTLog", L"logToConsole", "warn", "GridItem only supports one child."); | ||
} else { | ||
grid.Children().InsertAt(static_cast<uint32_t>(index), child); | ||
} | ||
} | ||
} | ||
|
||
void GridItemViewManager::RemoveAllChildren(xaml::FrameworkElement const &parent) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
grid.Children().Clear(); | ||
} | ||
} | ||
|
||
void GridItemViewManager::RemoveChildAt(xaml::FrameworkElement const &parent, int64_t index) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
if (index == 0) { | ||
grid.Children().RemoveAt(static_cast<uint32_t>(index)); | ||
} | ||
} | ||
} | ||
|
||
void GridItemViewManager::ReplaceChild( | ||
xaml::FrameworkElement const &parent, | ||
xaml::UIElement const &oldChild, | ||
xaml::UIElement const &newChild) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
uint32_t index; | ||
if (grid.Children().IndexOf(oldChild, index)) { | ||
grid.Children().RemoveAt(index); | ||
grid.Children().InsertAt(index, newChild); | ||
} | ||
} | ||
} | ||
|
||
winrt::IMapView<winrt::hstring, React::ViewManagerPropertyType> GridItemViewManager::NativeProps() noexcept { | ||
auto nativeProps = winrt::single_threaded_map<winrt::hstring, React::ViewManagerPropertyType>(); | ||
nativeProps.Insert(L"gridRow", React::ViewManagerPropertyType::Number); | ||
nativeProps.Insert(L"gridColumn", React::ViewManagerPropertyType::Number); | ||
return nativeProps.GetView(); | ||
} | ||
|
||
void GridItemViewManager::UpdateProperties( | ||
xaml::FrameworkElement const &view, | ||
winrt::Microsoft::ReactNative::IJSValueReader const &propertyMapReader) noexcept { | ||
React::JSValueObject propertyMap = React::JSValueObject::ReadFrom(propertyMapReader); | ||
for (const auto &pair : propertyMap) { | ||
const auto &propertyName = winrt::to_hstring(pair.first); | ||
const auto &propertyValue = pair.second; | ||
|
||
if (propertyName == L"gridRow") { | ||
xaml::Controls::Grid::SetRow(view, propertyValue.AsInt32()); | ||
} else if (propertyName == L"gridColumn") { | ||
xaml::Controls::Grid::SetColumn(view, propertyValue.AsInt32()); | ||
} else if (propertyName == L"backgroundColor") { | ||
view.as<xaml::Controls::Grid>().Background(propertyValue.To<xaml::Media::Brush>()); | ||
} | ||
} | ||
} | ||
|
||
} // namespace winrt::PlaygroundNativeModules |
51 changes: 51 additions & 0 deletions
51
packages/playground/windows/PlaygroundNativeModules/GridItemViewManager.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#pragma once | ||
#include "NativeModules.h" | ||
#include "winrt/Microsoft.ReactNative.h" | ||
|
||
namespace winrt::PlaygroundNativeModules { | ||
|
||
class GridItemViewManager : public winrt::implements< | ||
GridItemViewManager, | ||
React::IViewManager, | ||
React::IViewManagerWithReactContext, | ||
React::IViewManagerWithChildren, | ||
React::IViewManagerWithNativeProperties, | ||
React::IViewManagerRequiresNativeLayout> { | ||
public: | ||
// IViewManager | ||
winrt::hstring Name() noexcept; | ||
|
||
xaml::FrameworkElement CreateView() noexcept; | ||
|
||
// IViewManagerWithReactContext | ||
React::IReactContext ReactContext() noexcept; | ||
void ReactContext(React::IReactContext reactContext) noexcept; | ||
|
||
// IViewManagerWithChildren | ||
void AddView(xaml::FrameworkElement const &parent, xaml::UIElement const &child, int64_t index) noexcept; | ||
void RemoveAllChildren(xaml::FrameworkElement const &parent) noexcept; | ||
void RemoveChildAt(xaml::FrameworkElement const &parent, int64_t index) noexcept; | ||
void ReplaceChild( | ||
xaml::FrameworkElement const &parent, | ||
xaml::UIElement const &oldChild, | ||
xaml::UIElement const &newChild) noexcept; | ||
|
||
// IViewManagerWithNativeProperties | ||
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, React::ViewManagerPropertyType> | ||
NativeProps() noexcept; | ||
|
||
void UpdateProperties(xaml::FrameworkElement const &view, React::IJSValueReader const &propertyMapReader) noexcept; | ||
|
||
// IViewManagerRequiresNativeLayout | ||
bool RequiresNativeLayout() const noexcept { | ||
return true; | ||
} | ||
|
||
private: | ||
winrt::Microsoft::ReactNative::ReactContext m_reactContext{nullptr}; | ||
}; | ||
|
||
} // namespace winrt::PlaygroundNativeModules |
107 changes: 107 additions & 0 deletions
107
packages/playground/windows/PlaygroundNativeModules/GridViewManager.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "GridViewManager.h" | ||
|
||
namespace winrt::PlaygroundNativeModules { | ||
|
||
winrt::hstring GridViewManager::Name() noexcept { | ||
return L"PlaygroundGridView"; | ||
} | ||
|
||
xaml::FrameworkElement GridViewManager::CreateView() noexcept { | ||
return xaml::Controls::Grid(); | ||
} | ||
|
||
void GridViewManager::AddView( | ||
xaml::FrameworkElement const &parent, | ||
xaml::UIElement const &child, | ||
int64_t index) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
grid.Children().InsertAt(static_cast<uint32_t>(index), child); | ||
} | ||
} | ||
|
||
void GridViewManager::RemoveAllChildren(xaml::FrameworkElement const &parent) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
grid.Children().Clear(); | ||
} | ||
} | ||
|
||
void GridViewManager::RemoveChildAt(xaml::FrameworkElement const &parent, int64_t index) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
grid.Children().RemoveAt(static_cast<uint32_t>(index)); | ||
} | ||
} | ||
|
||
void GridViewManager::ReplaceChild( | ||
xaml::FrameworkElement const &parent, | ||
xaml::UIElement const &oldChild, | ||
xaml::UIElement const &newChild) noexcept { | ||
if (auto const &grid = parent.try_as<xaml::Controls::Grid>()) { | ||
uint32_t index; | ||
if (grid.Children().IndexOf(oldChild, index)) { | ||
grid.Children().RemoveAt(index); | ||
grid.Children().InsertAt(index, newChild); | ||
} | ||
} | ||
} | ||
|
||
winrt::IMapView<winrt::hstring, React::ViewManagerPropertyType> GridViewManager::NativeProps() noexcept { | ||
auto nativeProps = winrt::single_threaded_map<winrt::hstring, React::ViewManagerPropertyType>(); | ||
nativeProps.Insert(L"rows", React::ViewManagerPropertyType::Array); | ||
nativeProps.Insert(L"columns", React::ViewManagerPropertyType::Array); | ||
return nativeProps.GetView(); | ||
} | ||
|
||
xaml::GridLength GetGridLength(const winrt::Microsoft::ReactNative::JSValue &v) { | ||
if (v.Type() == React::JSValueType::Double || v.Type() == React::JSValueType::Int64) { | ||
return xaml::GridLengthHelper::FromValueAndType(v.AsDouble(), xaml::GridUnitType::Pixel); | ||
} else if (v.Type() == React::JSValueType::String) { | ||
auto str = v.AsString(); | ||
double units = 1; | ||
xaml::GridUnitType unitType = xaml::GridUnitType::Pixel; | ||
if (str.back() == '*') { | ||
unitType = xaml::GridUnitType::Star; | ||
str.pop_back(); | ||
if (str.length() > 0) { | ||
units = std::stod(str); | ||
} | ||
} else if (str == "auto") { | ||
unitType = xaml::GridUnitType::Auto; | ||
} else { | ||
units = std::stod(str); | ||
} | ||
return xaml::GridLengthHelper::FromValueAndType(units, unitType); | ||
} | ||
return xaml::GridLengthHelper::FromValueAndType(1, xaml::GridUnitType::Auto); | ||
} | ||
|
||
void GridViewManager::UpdateProperties( | ||
xaml::FrameworkElement const &view, | ||
winrt::Microsoft::ReactNative::IJSValueReader const &propertyMapReader) noexcept { | ||
React::JSValueObject propertyMap = React::JSValueObject::ReadFrom(propertyMapReader); | ||
for (const auto &pair : propertyMap) { | ||
const auto &propertyName = winrt::to_hstring(pair.first); | ||
const auto &propertyValue = pair.second; | ||
|
||
if (propertyName == L"rows") { | ||
const auto grid = view.as<xaml::Controls::Grid>(); | ||
for (const auto &row : propertyValue.AsArray()) { | ||
xaml::Controls::RowDefinition rowDefinition{}; | ||
rowDefinition.Height(GetGridLength(row)); | ||
grid.RowDefinitions().Append(rowDefinition); | ||
} | ||
} else if (propertyName == L"columns") { | ||
const auto grid = view.as<xaml::Controls::Grid>(); | ||
for (const auto &column : propertyValue.AsArray()) { | ||
xaml::Controls::ColumnDefinition columnDefinition{}; | ||
columnDefinition.Width(GetGridLength(column)); | ||
grid.ColumnDefinitions().Append(columnDefinition); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // namespace winrt::PlaygroundNativeModules |
Oops, something went wrong.