Skip to content

Commit 4509434

Browse files
tiberiu2Tiberiu Chiorean
andauthored
ContentIsland sample (#232)
* ContentIsland sample This sample demonstrates the usage of the Content related API's part of the WindowsAppSdk 1.2 experimental release. For more detailed information, checkout Samples/Content/cpp-win32/Squares/readme.md. Co-authored-by: Tiberiu Chiorean <[email protected]>
1 parent d8fffa2 commit 4509434

14 files changed

+1753
-0
lines changed
Lines changed: 397 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,397 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
#include "pch.h"
5+
6+
#include "DrawingIsland.h"
7+
#include "NodeSimpleFragment.h"
8+
#include "IslandFragmentRoot.h"
9+
10+
namespace Squares
11+
{
12+
DrawingIsland::DrawingIsland(
13+
const winrt::Compositor& compositor)
14+
{
15+
m_compositor = compositor;
16+
17+
m_island = winrt::ContentIsland::Create(compositor);
18+
19+
Output_Initialize();
20+
Input_Initialize();
21+
Accessibility_Initialize();
22+
Window_Initialize();
23+
}
24+
25+
26+
DrawingIsland::~DrawingIsland()
27+
{
28+
m_fragmentRoot = nullptr;
29+
m_fragmentFactory = nullptr;
30+
m_compositor = nullptr;
31+
}
32+
33+
34+
void
35+
DrawingIsland::Close()
36+
{
37+
m_visuals = nullptr;
38+
m_selectedVisual = nullptr;
39+
m_backgroundBrushDefault = nullptr;
40+
m_backgroundBrushA = nullptr;
41+
m_backgroundBrushB = nullptr;
42+
m_backgroundBrushC = nullptr;
43+
m_backgroundVisual = nullptr;
44+
45+
// Destroy Content:
46+
m_island.Close();
47+
m_island = nullptr;
48+
}
49+
50+
51+
void
52+
DrawingIsland::Output_Initialize()
53+
{
54+
for (int i = 0; i < _countof(m_colorBrushes); i++)
55+
{
56+
m_colorBrushes[i] = m_compositor.CreateColorBrush(s_colors[i]);
57+
58+
winrt::Color halfTransparent = s_colors[i];
59+
halfTransparent.A = 0x80;
60+
m_halfTransparentColorBrushes[i] = m_compositor.CreateColorBrush(halfTransparent);
61+
}
62+
63+
// Create the background parent Visual that the individual square will be added into.
64+
m_backgroundBrushDefault = m_compositor.CreateColorBrush(winrt::Color{ 0x99, 0x20, 0x20, 0x20 });
65+
m_backgroundBrushA = m_compositor.CreateColorBrush(winrt::Color{ 0x99, 0x99, 0x20, 0x20 });
66+
m_backgroundBrushB = m_compositor.CreateColorBrush(winrt::Color{ 0x99, 0x20, 0x99, 0x20 });
67+
m_backgroundBrushC = m_compositor.CreateColorBrush(winrt::Color{ 0x99, 0x20, 0x20, 0x99 });
68+
69+
m_backgroundVisual = m_compositor.CreateSpriteVisual();
70+
m_backgroundVisual.Brush(m_backgroundBrushDefault);
71+
m_backgroundVisual.RelativeSizeAdjustment(winrt::float2(1, 1));
72+
m_island.Root(m_backgroundVisual);
73+
74+
winrt::ContainerVisual drawingVisualsRoot = m_compositor.CreateContainerVisual();
75+
m_visuals = drawingVisualsRoot.Children();
76+
m_backgroundVisual.Children().InsertAtTop(drawingVisualsRoot);
77+
}
78+
79+
80+
void
81+
DrawingIsland::Output_AddVisual(
82+
winrt::float2 const point,
83+
bool halfTransparent)
84+
{
85+
winrt::SpriteVisual visual = m_compositor.CreateSpriteVisual();
86+
visual.Brush(halfTransparent ?
87+
m_halfTransparentColorBrushes[m_currentColorIndex] :
88+
m_colorBrushes[m_currentColorIndex]);
89+
90+
m_currentColorIndex = (m_currentColorIndex + 1) % 4;
91+
92+
float const BlockSize = 30.0f;
93+
visual.Size({ BlockSize, BlockSize });
94+
visual.Offset({ point.x - BlockSize / 2.0f, point.y - BlockSize / 2.0f, 0.0f });
95+
96+
m_visuals.InsertAtTop(visual);
97+
98+
m_selectedVisual = visual;
99+
m_offset.x = -BlockSize / 2.0f;
100+
m_offset.y = -BlockSize / 2.0f;
101+
102+
CreateUIAProviderForVisual();
103+
104+
Accessibility_UpdateScreenCoordinates(m_selectedVisual);
105+
}
106+
107+
108+
void
109+
DrawingIsland::Input_Initialize()
110+
{
111+
auto pointerSource = winrt::InputPointerSource::GetForIsland(m_island);
112+
113+
pointerSource.PointerPressed(
114+
[this](winrt::InputPointerSource const&,
115+
winrt::PointerEventArgs const& args)
116+
{
117+
auto currentPoint = args.CurrentPoint();
118+
auto properties = currentPoint.Properties();
119+
120+
if (properties.IsLeftButtonPressed())
121+
{
122+
Input_OnLeftButtonPressed(args);
123+
}
124+
});
125+
126+
pointerSource.PointerMoved(
127+
[this](winrt::InputPointerSource const&,
128+
winrt::PointerEventArgs const& args)
129+
{
130+
Input_OnPointerMoved(args);
131+
});
132+
133+
pointerSource.PointerReleased(
134+
[&](auto&& ...)
135+
{
136+
Input_OnPointerReleased();
137+
});
138+
139+
// Set up the keyboard source. We store this in a member variable so we can easily call
140+
// TrySetFocus() in response to left clicks in the content later on.
141+
m_keyboardSource = winrt::InputKeyboardSource::GetForIsland(m_island);
142+
143+
m_keyboardSource.KeyDown(
144+
[this](winrt::InputKeyboardSource const&,
145+
winrt::KeyEventArgs const& args)
146+
{
147+
bool handled = Input_OnKeyDown(args.VirtualKey());
148+
149+
// Mark the event as handled
150+
if (handled)
151+
{
152+
args.Handled(true);
153+
}
154+
});
155+
156+
auto activationListener = winrt::InputActivationListener::GetForIsland(m_island);
157+
(void)activationListener.InputActivationChanged(
158+
[this, activationListener](
159+
winrt::InputActivationListener const&,
160+
winrt::InputActivationListenerActivationChangedEventArgs const&)
161+
{
162+
switch (activationListener.State())
163+
{
164+
case winrt::InputActivationState::Activated:
165+
m_backgroundVisual.Opacity(1.0f);
166+
break;
167+
168+
default:
169+
m_backgroundVisual.Opacity(0.5f);
170+
break;
171+
}
172+
});
173+
}
174+
175+
176+
bool
177+
DrawingIsland::Input_OnKeyDown(
178+
winrt::Windows::System::VirtualKey virtualKey)
179+
{
180+
bool handled = false;
181+
182+
switch (virtualKey)
183+
{
184+
case winrt::VirtualKey::A:
185+
{
186+
m_backgroundVisual.Brush(m_backgroundBrushA);
187+
handled = true;
188+
break;
189+
}
190+
191+
case winrt::VirtualKey::B:
192+
{
193+
m_backgroundVisual.Brush(m_backgroundBrushB);
194+
handled = true;
195+
break;
196+
}
197+
198+
case winrt::VirtualKey::C:
199+
{
200+
m_backgroundVisual.Brush(m_backgroundBrushC);
201+
handled = true;
202+
break;
203+
}
204+
205+
case winrt::VirtualKey::Space:
206+
{
207+
m_backgroundVisual.Brush(m_backgroundBrushDefault);
208+
break;
209+
}
210+
}
211+
212+
return handled;
213+
}
214+
215+
winrt::Visual
216+
DrawingIsland::HitTestVisual(
217+
winrt::float2 const point)
218+
{
219+
winrt::Visual selectedVisual{ nullptr };
220+
for (winrt::Visual visual : m_visuals)
221+
{
222+
winrt::float3 const offset = visual.Offset();
223+
winrt::float2 const size = visual.Size();
224+
225+
if (point.x >= offset.x &&
226+
point.x < offset.x + size.x &&
227+
point.y >= offset.y &&
228+
point.y < offset.y + size.y)
229+
{
230+
selectedVisual = visual;
231+
}
232+
}
233+
234+
return selectedVisual;
235+
}
236+
237+
238+
void
239+
DrawingIsland::Input_OnLeftButtonPressed(
240+
const winrt::PointerEventArgs& args)
241+
{
242+
// Left button manipulates the custom-drawn content
243+
winrt::float2 const point = args.CurrentPoint().Position();
244+
245+
bool controlPressed = WI_IsFlagSet(
246+
args.KeyModifiers(),
247+
winrt::Windows::System::VirtualKeyModifiers::Control);
248+
249+
OnLeftClick(point, controlPressed);
250+
}
251+
252+
253+
void
254+
DrawingIsland::Input_OnPointerReleased()
255+
{
256+
m_selectedVisual = nullptr;
257+
}
258+
259+
260+
void
261+
DrawingIsland::OnLeftClick(
262+
const winrt::float2 point,
263+
bool controlPressed)
264+
{
265+
m_selectedVisual = HitTestVisual(point);
266+
267+
if (m_selectedVisual)
268+
{
269+
winrt::float3 const offset = m_selectedVisual.Offset();
270+
271+
m_offset.x = offset.x - point.x;
272+
m_offset.y = offset.y - point.y;
273+
274+
m_visuals.Remove(m_selectedVisual);
275+
m_visuals.InsertAtTop(m_selectedVisual);
276+
}
277+
else
278+
{
279+
Output_AddVisual(point, controlPressed);
280+
}
281+
282+
m_keyboardSource.TrySetFocus();
283+
}
284+
285+
286+
void
287+
DrawingIsland::Input_OnPointerMoved(
288+
const winrt::PointerEventArgs& args)
289+
{
290+
if (m_selectedVisual)
291+
{
292+
winrt::float2 const point = args.CurrentPoint().Position();
293+
m_selectedVisual.Offset({ point.x + m_offset.x, point.y + m_offset.y, 0.0f });
294+
}
295+
}
296+
297+
298+
void
299+
DrawingIsland::Accessibility_Initialize()
300+
{
301+
m_fragmentRoot = winrt::make_self<IslandFragmentRoot>(m_island);
302+
m_fragmentRoot->SetName(L"Content Island");
303+
304+
m_fragmentFactory = winrt::make_self<NodeSimpleFragmentFactory>();
305+
306+
307+
(void)m_island.AutomationProviderRequested(
308+
[this](winrt::ContentIsland const& sender,
309+
winrt::ContentIslandAutomationProviderRequestedEventArgs const& args)
310+
{
311+
return Accessibility_OnAutomationProviderRequested(sender, args);
312+
});
313+
}
314+
315+
316+
void
317+
DrawingIsland::Accessibility_OnAutomationProviderRequested(
318+
const winrt::ContentIsland& /*island*/,
319+
const winrt::ContentIslandAutomationProviderRequestedEventArgs& args)
320+
{
321+
IInspectable providerAsIInspectable;
322+
m_fragmentRoot->QueryInterface(winrt::guid_of<IInspectable>(), winrt::put_abi(providerAsIInspectable));
323+
args.AutomationProvider(std::move(providerAsIInspectable));
324+
325+
args.Handled(true);
326+
}
327+
328+
329+
void
330+
DrawingIsland::Accessibility_UpdateScreenCoordinates(winrt::Visual visual)
331+
{
332+
winrt::Rect logicalRect;
333+
logicalRect.X = visual.Offset().x;
334+
logicalRect.Y = visual.Offset().y;
335+
logicalRect.Width = visual.Size().x;
336+
logicalRect.Height = visual.Size().y;
337+
338+
auto fragment = m_visualToFragmentMap[visual];
339+
340+
// This will convert from the logical coordinate space of the ContentIsland to
341+
// Win32 screen coordinates that are needed by Accesibility.
342+
auto screenRect = m_island.Coordinates().ComputeScreenCoordinates(logicalRect);
343+
344+
UiaRect uiaRect;
345+
uiaRect.left = screenRect.X;
346+
uiaRect.top = screenRect.Y;
347+
uiaRect.width = screenRect.Width;
348+
uiaRect.height = screenRect.Height;
349+
350+
fragment->SetBoundingRects(uiaRect);
351+
}
352+
353+
354+
void
355+
DrawingIsland::CreateUIAProviderForVisual()
356+
{
357+
winrt::com_ptr<NodeSimpleFragment> fragment = m_fragmentFactory->Create(s_colorNames[m_currentColorIndex].c_str(), m_fragmentRoot);
358+
359+
m_visualToFragmentMap[m_selectedVisual] = fragment;
360+
361+
// Set up children roots.
362+
m_fragmentRoot->AddChild(fragment);
363+
364+
// Finally set up parent chain.
365+
fragment->SetParent(m_fragmentRoot);
366+
}
367+
368+
void
369+
DrawingIsland::Window_Initialize()
370+
{
371+
auto window = m_island.Window();
372+
373+
(void)window.StateChanged(
374+
[this](winrt::IContentWindow const&, winrt::IInspectable const&)
375+
{
376+
return Window_StateChanged();
377+
});
378+
}
379+
380+
void
381+
DrawingIsland::Window_StateChanged()
382+
{
383+
bool isLandscapeOrientation =
384+
(m_island.Window().CurrentOrientation() == winrt::ContentDisplayOrientations::Landscape ||
385+
m_island.Window().CurrentOrientation() == winrt::ContentDisplayOrientations::LandscapeFlipped);
386+
if (isLandscapeOrientation)
387+
{
388+
m_backgroundBrushDefault = m_compositor.CreateColorBrush(winrt::Colors::DarkOrange());
389+
m_backgroundVisual.Brush(m_backgroundBrushDefault);
390+
}
391+
else
392+
{
393+
m_backgroundBrushDefault = m_compositor.CreateColorBrush(winrt::Colors::DarkGray());
394+
m_backgroundVisual.Brush(m_backgroundBrushDefault);
395+
}
396+
}
397+
}

0 commit comments

Comments
 (0)