react-native-windows 0.0.0-canary.613 → 0.0.0-canary.614
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +247 -0
- package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +58 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/Color.cpp +5 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.h +1 -0
- package/PropertySheets/Generated/PackageVersion.g.props +1 -1
- package/Shared/Shared.vcxitems +1 -0
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
#include <Fabric/Composition/ImageComponentView.h>
|
|
25
25
|
#include <Fabric/Composition/ParagraphComponentView.h>
|
|
26
26
|
#include <Fabric/Composition/ScrollViewComponentView.h>
|
|
27
|
+
#include <Fabric/Composition/SwitchComponentView.h>
|
|
27
28
|
#include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
|
|
28
29
|
|
|
29
30
|
namespace Microsoft::ReactNative {
|
|
@@ -48,6 +49,8 @@ ComponentViewDescriptor const &ComponentViewRegistry::dequeueComponentViewWithCo
|
|
|
48
49
|
view = std::make_shared<ImageComponentView>(compContext, tag, m_context);
|
|
49
50
|
} else if (componentHandle == facebook::react::WindowsTextInputShadowNode::Handle()) {
|
|
50
51
|
view = std::make_shared<WindowsTextInputComponentView>(compContext, tag, m_context);
|
|
52
|
+
} else if (componentHandle == facebook::react::SwitchShadowNode::Handle()) {
|
|
53
|
+
view = std::make_shared<SwitchComponentView>(compContext, tag, m_context);
|
|
51
54
|
} else {
|
|
52
55
|
view = std::make_shared<CompositionViewComponentView>(compContext, tag);
|
|
53
56
|
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include "SwitchComponentView.h"
|
|
8
|
+
|
|
9
|
+
namespace Microsoft::ReactNative {
|
|
10
|
+
|
|
11
|
+
SwitchComponentView::SwitchComponentView(
|
|
12
|
+
const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext,
|
|
13
|
+
facebook::react::Tag tag,
|
|
14
|
+
winrt::Microsoft::ReactNative::ReactContext const &reactContext)
|
|
15
|
+
: Super(compContext, tag), m_context(reactContext) {
|
|
16
|
+
m_props = std::make_shared<facebook::react::SwitchProps const>();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
std::vector<facebook::react::ComponentDescriptorProvider>
|
|
20
|
+
SwitchComponentView::supplementalComponentDescriptorProviders() noexcept {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void SwitchComponentView::mountChildComponentView(const IComponentView &childComponentView, uint32_t index) noexcept {
|
|
25
|
+
assert(false);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void SwitchComponentView::unmountChildComponentView(const IComponentView &childComponentView, uint32_t index) noexcept {
|
|
29
|
+
assert(false);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void SwitchComponentView::handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept {
|
|
33
|
+
if (commandName == "setValue") {
|
|
34
|
+
// TODO - Current implementation always aligns with JS value
|
|
35
|
+
// This will be needed when we move to using WinUI controls
|
|
36
|
+
} else {
|
|
37
|
+
Super::handleCommand(commandName, arg);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void SwitchComponentView::updateProps(
|
|
42
|
+
facebook::react::Props::Shared const &props,
|
|
43
|
+
facebook::react::Props::Shared const &oldProps) noexcept {
|
|
44
|
+
const auto &oldViewProps = *std::static_pointer_cast<const facebook::react::SwitchProps>(m_props);
|
|
45
|
+
const auto &newViewProps = *std::static_pointer_cast<const facebook::react::SwitchProps>(props);
|
|
46
|
+
|
|
47
|
+
ensureVisual();
|
|
48
|
+
|
|
49
|
+
if (oldViewProps.backgroundColor != newViewProps.backgroundColor ||
|
|
50
|
+
oldViewProps.thumbTintColor != newViewProps.thumbTintColor || oldViewProps.value != newViewProps.value ||
|
|
51
|
+
oldViewProps.disabled != newViewProps.disabled) {
|
|
52
|
+
m_drawingSurface = nullptr;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
m_props = std::static_pointer_cast<facebook::react::ViewProps const>(props);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void SwitchComponentView::updateState(
|
|
59
|
+
facebook::react::State::Shared const &state,
|
|
60
|
+
facebook::react::State::Shared const &oldState) noexcept {}
|
|
61
|
+
|
|
62
|
+
void SwitchComponentView::updateLayoutMetrics(
|
|
63
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
64
|
+
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
|
|
65
|
+
// Set Position & Size Properties
|
|
66
|
+
ensureVisual();
|
|
67
|
+
|
|
68
|
+
if ((layoutMetrics.displayType != m_layoutMetrics.displayType)) {
|
|
69
|
+
m_visual.IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
m_layoutMetrics = layoutMetrics;
|
|
73
|
+
|
|
74
|
+
UpdateCenterPropertySet();
|
|
75
|
+
m_visual.Size(
|
|
76
|
+
{layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
|
|
77
|
+
layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
|
|
78
|
+
m_visual.Offset({
|
|
79
|
+
layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
|
|
80
|
+
layoutMetrics.frame.origin.y * layoutMetrics.pointScaleFactor,
|
|
81
|
+
0.0f,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void SwitchComponentView::finalizeUpdates(RNComponentViewUpdateMask updateMask) noexcept {
|
|
86
|
+
ensureDrawingSurface();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void SwitchComponentView::Draw() noexcept {
|
|
90
|
+
// Begin our update of the surface pixels. If this is our first update, we are required
|
|
91
|
+
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
|
|
92
|
+
// any time we make an update we touch the entire surface, so we always pass nullptr).
|
|
93
|
+
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
|
94
|
+
POINT offset;
|
|
95
|
+
|
|
96
|
+
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
|
97
|
+
m_drawingSurface.as(drawingSurfaceInterop);
|
|
98
|
+
|
|
99
|
+
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
|
100
|
+
const auto switchProps = std::static_pointer_cast<const facebook::react::SwitchProps>(m_props);
|
|
101
|
+
|
|
102
|
+
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
|
103
|
+
if (m_props->backgroundColor) {
|
|
104
|
+
d2dDeviceContext->Clear(m_props->backgroundColor.AsD2DColor());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
|
|
108
|
+
float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
|
|
109
|
+
|
|
110
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/ToggleSwitch_themeresources.xaml
|
|
111
|
+
constexpr float thumbMargin = 3.0f;
|
|
112
|
+
constexpr float thumbRadius = 7.0f;
|
|
113
|
+
constexpr float trackWidth = 40.0f;
|
|
114
|
+
constexpr float trackHeight = 20.0f;
|
|
115
|
+
constexpr float trackCornerRadius = 10.0f;
|
|
116
|
+
|
|
117
|
+
auto frame{m_layoutMetrics.frame.size};
|
|
118
|
+
float trackMarginX = (frame.width - trackWidth) / 2;
|
|
119
|
+
float trackMarginY = (frame.height - trackHeight) / 2;
|
|
120
|
+
|
|
121
|
+
D2D1_RECT_F trackRect = D2D1::RectF(
|
|
122
|
+
offsetX + trackMarginX,
|
|
123
|
+
offsetY + trackMarginY,
|
|
124
|
+
offsetX + trackMarginX + trackWidth,
|
|
125
|
+
offsetY + trackMarginY + trackHeight);
|
|
126
|
+
|
|
127
|
+
// switchProps->value = false
|
|
128
|
+
float thumbX = trackRect.left + thumbMargin + thumbRadius;
|
|
129
|
+
|
|
130
|
+
if (switchProps->value) {
|
|
131
|
+
thumbX = trackRect.right - thumbMargin - thumbRadius;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
winrt::com_ptr<ID2D1SolidColorBrush> defaultBrush;
|
|
135
|
+
|
|
136
|
+
D2D1_COLOR_F defaultColor =
|
|
137
|
+
switchProps->disabled ? facebook::react::greyColor().AsD2DColor() : facebook::react::blackColor().AsD2DColor();
|
|
138
|
+
|
|
139
|
+
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(defaultColor, defaultBrush.put()));
|
|
140
|
+
|
|
141
|
+
winrt::com_ptr<ID2D1SolidColorBrush> thumbBrush;
|
|
142
|
+
if (!switchProps->disabled && switchProps->thumbTintColor) {
|
|
143
|
+
winrt::check_hresult(
|
|
144
|
+
d2dDeviceContext->CreateSolidColorBrush(switchProps->thumbTintColor.AsD2DColor(), thumbBrush.put()));
|
|
145
|
+
} else {
|
|
146
|
+
thumbBrush = defaultBrush;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
|
150
|
+
float oldDpiX, oldDpiY;
|
|
151
|
+
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
|
152
|
+
d2dDeviceContext->SetDpi(dpi, dpi);
|
|
153
|
+
|
|
154
|
+
// switch thumb
|
|
155
|
+
D2D1_POINT_2F thumbCenter = D2D1 ::Point2F(thumbX, (trackRect.top + trackRect.bottom) / 2);
|
|
156
|
+
D2D1_ELLIPSE thumb = D2D1::Ellipse(thumbCenter, thumbRadius, thumbRadius);
|
|
157
|
+
d2dDeviceContext->FillEllipse(thumb, thumbBrush.get());
|
|
158
|
+
|
|
159
|
+
// switch track
|
|
160
|
+
D2D1_ROUNDED_RECT track = D2D1::RoundedRect(trackRect, trackCornerRadius, trackCornerRadius);
|
|
161
|
+
d2dDeviceContext->DrawRoundedRectangle(track, defaultBrush.get());
|
|
162
|
+
|
|
163
|
+
// Restore old dpi setting
|
|
164
|
+
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
|
165
|
+
|
|
166
|
+
// Our update is done. EndDraw never indicates rendering device removed, so any
|
|
167
|
+
// failure here is unexpected and, therefore, fatal.
|
|
168
|
+
winrt::check_hresult(drawingSurfaceInterop->EndDraw());
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
void SwitchComponentView::prepareForRecycle() noexcept {}
|
|
173
|
+
|
|
174
|
+
facebook::react::Props::Shared SwitchComponentView::props() noexcept {
|
|
175
|
+
return m_props;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void SwitchComponentView::ensureVisual() noexcept {
|
|
179
|
+
if (!m_visual) {
|
|
180
|
+
m_visual = m_compContext.CreateSpriteVisual();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void SwitchComponentView::ensureDrawingSurface() noexcept {
|
|
185
|
+
if (!m_drawingSurface) {
|
|
186
|
+
winrt::Windows::Foundation::Size surfaceSize = {
|
|
187
|
+
m_layoutMetrics.frame.size.width * m_layoutMetrics.pointScaleFactor,
|
|
188
|
+
m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor};
|
|
189
|
+
m_drawingSurface = m_compContext.CreateDrawingSurface(
|
|
190
|
+
surfaceSize,
|
|
191
|
+
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
|
192
|
+
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
|
193
|
+
|
|
194
|
+
Draw();
|
|
195
|
+
|
|
196
|
+
auto surfaceBrush = m_compContext.CreateSurfaceBrush(m_drawingSurface);
|
|
197
|
+
|
|
198
|
+
m_visual.Brush(surfaceBrush);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
facebook::react::Tag SwitchComponentView::hitTest(facebook::react::Point pt, facebook::react::Point &localPt)
|
|
203
|
+
const noexcept {
|
|
204
|
+
facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
|
|
205
|
+
|
|
206
|
+
if ((m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
|
|
207
|
+
m_props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
|
|
208
|
+
ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
|
|
209
|
+
ptLocal.y <= m_layoutMetrics.frame.size.height) {
|
|
210
|
+
localPt = ptLocal;
|
|
211
|
+
return tag();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return -1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
facebook::react::SharedTouchEventEmitter SwitchComponentView::touchEventEmitter() noexcept {
|
|
218
|
+
return m_eventEmitter;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
winrt::Microsoft::ReactNative::Composition::IVisual SwitchComponentView::Visual() const noexcept {
|
|
222
|
+
return m_visual;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
int64_t SwitchComponentView::SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept {
|
|
226
|
+
switch (msg) {
|
|
227
|
+
case WM_LBUTTONDOWN:
|
|
228
|
+
case WM_POINTERDOWN: {
|
|
229
|
+
const auto switchProps = std::static_pointer_cast<const facebook::react::SwitchProps>(m_props);
|
|
230
|
+
|
|
231
|
+
if (!switchProps->disabled && m_eventEmitter) {
|
|
232
|
+
auto switchEventEmitter = std::static_pointer_cast<facebook::react::SwitchEventEmitter const>(m_eventEmitter);
|
|
233
|
+
|
|
234
|
+
facebook::react::SwitchEventEmitter::OnChange args;
|
|
235
|
+
args.value = !(switchProps->value);
|
|
236
|
+
args.target = tag();
|
|
237
|
+
|
|
238
|
+
switchEventEmitter->onChange(args);
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include <Fabric/ComponentView.h>
|
|
8
|
+
#include <Microsoft.ReactNative.Cxx/ReactContext.h>
|
|
9
|
+
|
|
10
|
+
#include "CompositionViewComponentView.h"
|
|
11
|
+
|
|
12
|
+
#include <react/components/rnwcore/ShadowNodes.h>
|
|
13
|
+
|
|
14
|
+
namespace Microsoft::ReactNative {
|
|
15
|
+
|
|
16
|
+
struct SwitchComponentView;
|
|
17
|
+
|
|
18
|
+
struct SwitchComponentView : CompositionBaseComponentView {
|
|
19
|
+
using Super = CompositionBaseComponentView;
|
|
20
|
+
SwitchComponentView(
|
|
21
|
+
const winrt::Microsoft::ReactNative::Composition::ICompositionContext &compContext,
|
|
22
|
+
facebook::react::Tag tag,
|
|
23
|
+
winrt::Microsoft::ReactNative::ReactContext const &reactContext);
|
|
24
|
+
|
|
25
|
+
std::vector<facebook::react::ComponentDescriptorProvider> supplementalComponentDescriptorProviders() noexcept
|
|
26
|
+
override;
|
|
27
|
+
void mountChildComponentView(const IComponentView &childComponentView, uint32_t index) noexcept override;
|
|
28
|
+
void unmountChildComponentView(const IComponentView &childComponentView, uint32_t index) noexcept override;
|
|
29
|
+
void handleCommand(std::string const &commandName, folly::dynamic const &arg) noexcept override;
|
|
30
|
+
void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept
|
|
31
|
+
override;
|
|
32
|
+
void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept
|
|
33
|
+
override;
|
|
34
|
+
void updateLayoutMetrics(
|
|
35
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
36
|
+
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
|
|
37
|
+
void finalizeUpdates(RNComponentViewUpdateMask updateMask) noexcept override;
|
|
38
|
+
void prepareForRecycle() noexcept override;
|
|
39
|
+
facebook::react::Props::Shared props() noexcept override;
|
|
40
|
+
facebook::react::SharedTouchEventEmitter touchEventEmitter() noexcept override;
|
|
41
|
+
|
|
42
|
+
facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt) const noexcept override;
|
|
43
|
+
winrt::Microsoft::ReactNative::Composition::IVisual Visual() const noexcept override;
|
|
44
|
+
int64_t SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept override;
|
|
45
|
+
|
|
46
|
+
private:
|
|
47
|
+
void ensureVisual() noexcept;
|
|
48
|
+
void Draw() noexcept;
|
|
49
|
+
void ensureDrawingSurface() noexcept;
|
|
50
|
+
|
|
51
|
+
facebook::react::Size m_contentSize;
|
|
52
|
+
winrt::Microsoft::ReactNative::Composition::SpriteVisual m_visual{nullptr};
|
|
53
|
+
winrt::Microsoft::ReactNative::ReactContext m_context;
|
|
54
|
+
facebook::react::SharedViewProps m_props;
|
|
55
|
+
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface m_drawingSurface;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.0.0-canary.
|
|
13
|
+
<ReactNativeWindowsVersion>0.0.0-canary.614</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>0</ReactNativeWindowsMinor>
|
|
16
16
|
<ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
|
package/Shared/Shared.vcxitems
CHANGED
|
@@ -270,6 +270,7 @@
|
|
|
270
270
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\CompositionEventHandler.cpp" />
|
|
271
271
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\CompositionHelpers.cpp" />
|
|
272
272
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\ImageComponentView.cpp" />
|
|
273
|
+
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\SwitchComponentView.cpp" />
|
|
273
274
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\ParagraphComponentView.cpp" />
|
|
274
275
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\ScrollViewComponentView.cpp" />
|
|
275
276
|
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Fabric\Composition\CompositionViewComponentView.cpp" />
|