@@ -14,6 +14,7 @@ namespace winrt::DrawingIslandComponents::implementation
1414 const winrt::Compositor& compositor)
1515 {
1616 m_output.Compositor = compositor;
17+ m_output.TextRenderer = std::make_shared<TextRenderer>(m_output.Compositor );
1718
1819 // Create the Compositor and the Content:
1920 // - The Bridge's connection to the Window will keep everything alive, and perform an
@@ -75,7 +76,8 @@ namespace winrt::DrawingIslandComponents::implementation
7576 m_background.Visual = nullptr ;
7677
7778 m_items.Visuals = nullptr ;
78- m_items.SelectedVisual = nullptr ;
79+ m_items.Items .clear ();
80+ m_items.SelectedItem = nullptr ;
7981
8082 // TODO: Enable Mica on Win 11
8183#if FALSE
@@ -234,11 +236,13 @@ namespace winrt::DrawingIslandComponents::implementation
234236 winrt::Windows::Graphics::RectInt32 screenRect{ static_cast <int >(x + 0.5 ), static_cast <int >(y + 0.5 ), 0 , 0 };
235237 auto logicalRect = m_island.CoordinateConverter ().ConvertScreenToLocal (screenRect);
236238 float2 localPoint{ logicalRect.X , logicalRect.Y };
237- auto hitTestVisual = HitTestVisual (localPoint);
239+ auto hitTestElement = HitTestItem (localPoint);
238240
239241 // Find the automation peer for the hit test visual if any.
240- if (nullptr != hitTestVisual )
242+ if (nullptr != hitTestElement )
241243 {
244+ auto & hitTestVisual = hitTestElement->GetVisual ();
245+
242246 auto iterator = std::find_if (
243247 m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [&hitTestVisual](auto const & automationPeer)
244248 {
@@ -259,30 +263,36 @@ namespace winrt::DrawingIslandComponents::implementation
259263 winrt::com_ptr<IRawElementProviderFragment>
260264 DrawingIsland::GetFragmentInFocus () const
261265 {
262- // Find the currently selected visual's automation peer.
263- auto iterator = std::find_if (
264- m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [visual = m_items.SelectedVisual ](auto const & automationPeer)
265- {
266- return automationPeer.Match (visual);
267- });
268-
269- if (m_uia.AutomationPeers .end () != iterator)
266+ if (m_items.SelectedItem != nullptr )
270267 {
271- // Return the automation provider if we found an automation peer for the selected visual.
272- return iterator->GetAutomationProvider ().as <IRawElementProviderFragment>();
268+ auto & visual = m_items.SelectedItem ->GetVisual ();
269+
270+ // Find the currently selected visual's automation peer.
271+ auto iterator = std::find_if (
272+ m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [visual](auto const & automationPeer)
273+ {
274+ return automationPeer.Match (visual);
275+ });
276+
277+ if (m_uia.AutomationPeers .end () != iterator)
278+ {
279+ // Return the automation provider if we found an automation peer for the selected visual.
280+ return iterator->GetAutomationProvider ().as <IRawElementProviderFragment>();
281+ }
273282 }
274283
275284 return nullptr ;
276285 }
277286
278287
279- winrt::Visual
280- DrawingIsland::HitTestVisual (
281- float2 const & point) const
288+ Item* DrawingIsland::HitTestItem (float2 const & point) const
282289 {
283- winrt::Visual selectedVisual{ nullptr };
284- for (winrt::Visual visual : m_items.Visuals )
290+ // Iterate from the end of the vector, i.e., from front to back.
291+ for (size_t i = m_items.Items . size (); i != 0 ; i-- )
285292 {
293+ Item* item = m_items.Items [i - 1 ].get ();
294+ auto & visual = item->GetVisual ();
295+
286296 winrt::float3 const offset = visual.Offset ();
287297 float2 const size = visual.Size ();
288298
@@ -291,11 +301,10 @@ namespace winrt::DrawingIslandComponents::implementation
291301 point.y >= offset.y &&
292302 point.y < offset.y + size.y )
293303 {
294- selectedVisual = visual ;
304+ return item ;
295305 }
296306 }
297-
298- return selectedVisual;
307+ return nullptr ;
299308 }
300309
301310
@@ -507,6 +516,7 @@ namespace winrt::DrawingIslandComponents::implementation
507516 case winrt::Windows::System::VirtualKey::Escape:
508517 {
509518 m_items.Visuals .RemoveAll ();
519+ m_items.Items .clear ();
510520
511521 // Update accessibility.
512522 m_uia.FragmentRoot ->RemoveAllChildren ();
@@ -581,7 +591,7 @@ namespace winrt::DrawingIslandComponents::implementation
581591 void
582592 DrawingIsland::Input_OnPointerReleased ()
583593 {
584- m_items.SelectedVisual = nullptr ;
594+ m_items.SelectedItem = nullptr ;
585595 }
586596
587597
@@ -608,22 +618,39 @@ namespace winrt::DrawingIslandComponents::implementation
608618 const float2 point,
609619 bool controlPressed)
610620 {
611- m_items.SelectedVisual = HitTestVisual (point);
621+ m_items.SelectedItem = HitTestItem (point);
612622
613- if (m_items.SelectedVisual )
623+ if (m_items.SelectedItem != nullptr )
614624 {
615- winrt::float3 const offset = m_items.SelectedVisual .Offset ();
625+ Item* item = m_items.SelectedItem ;
626+ auto & visual = m_items.SelectedItem ->GetVisual ();
627+ winrt::float3 const offset = visual.Offset ();
616628
617629 m_items.Offset .x = offset.x - point.x ;
618630 m_items.Offset .y = offset.y - point.y ;
619631
620- m_items.Visuals .Remove (m_items.SelectedVisual );
621- m_items.Visuals .InsertAtTop (m_items.SelectedVisual );
632+ // Move the visual to the top.
633+ m_items.Visuals .Remove (visual);
634+ m_items.Visuals .InsertAtTop (visual);
635+
636+ // Move the VisualElement to the end of the vector if it isn't already.
637+ if (!m_items.Items .empty () && m_items.Items .back ().get () != item)
638+ {
639+ auto i = std::find_if (
640+ m_items.Items .begin (),
641+ m_items.Items .end (),
642+ [item](auto & elem) { return elem.get () == item; }
643+ );
644+ if (i != m_items.Items .end ())
645+ {
646+ std::rotate (i, i + 1 , m_items.Items .end ());
647+ }
648+ }
622649
623650 // Update automation.
624651 // First find the existing automation peer.
625652 auto iterator = std::find_if (
626- m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [visual = m_items. SelectedVisual ](auto const & automationPeer)
653+ m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [visual](auto const & automationPeer)
627654 {
628655 return automationPeer.Match (visual);
629656 });
@@ -651,18 +678,21 @@ namespace winrt::DrawingIslandComponents::implementation
651678 void
652679 DrawingIsland::OnRightClick (const float2 point)
653680 {
654- winrt::Visual selectedVisual = HitTestVisual (point);
681+ // TODO - what is the purpose of this?
682+ UNREFERENCED_PARAMETER (point);
683+ // VisualElement* selectedVisual = HitTestVisual(point);
655684 }
656685
657686 void
658687 DrawingIsland::Input_OnPointerMoved (
659688 const winrt::PointerEventArgs& args)
660689 {
661- if (m_items.SelectedVisual )
690+ if (m_items.SelectedItem )
662691 {
692+ auto & visual = m_items.SelectedItem ->GetVisual ();
663693 float2 const point = args.CurrentPoint ().Position ();
664694
665- m_items. SelectedVisual .Offset (
695+ visual .Offset (
666696 { point.x + m_items.Offset .x ,
667697 point.y + m_items.Offset .y ,
668698 0 .0f });
@@ -682,7 +712,16 @@ namespace winrt::DrawingIslandComponents::implementation
682712 {
683713 if (m_prevState.RasterizationScale != m_island.RasterizationScale ())
684714 {
685- m_prevState.RasterizationScale = m_island.RasterizationScale ();
715+ float newScale = m_island.RasterizationScale ();
716+
717+ m_prevState.RasterizationScale = newScale;
718+
719+ m_output.TextRenderer ->SetDpiScale (newScale);
720+
721+ for (auto & item : m_items.Items )
722+ {
723+ item->OnDpiScaleChanged ();
724+ }
686725 }
687726
688727 if (m_prevState.LayoutDirection != m_island.LayoutDirection ())
@@ -746,20 +785,39 @@ namespace winrt::DrawingIslandComponents::implementation
746785 float2 const point,
747786 bool halfTransparent)
748787 {
749- winrt::SpriteVisual visual = m_output.Compositor .CreateSpriteVisual ();
750- visual.Brush (halfTransparent ?
751- m_output.HalfTransparentColorBrushes [m_output.CurrentColorIndex ] :
752- m_output.ColorBrushes [m_output.CurrentColorIndex ]);
788+ // Determine the visual background and text colors.
789+ Color backgroundColor = s_colors[m_output.CurrentColorIndex ];
790+ Color textColor = { 0xFF , 0 , 0 , 0 };
791+ if (halfTransparent)
792+ {
793+ backgroundColor.A /= 2 ;
794+ textColor.A /= 2 ;
795+ }
796+
797+ // Create a TextElement object.
798+ auto textItem = std::make_unique<TextItem>(
799+ m_output.TextRenderer ,
800+ backgroundColor,
801+ textColor,
802+ s_colorNames[m_output.CurrentColorIndex ]
803+ );
804+
805+ // Get the visual and its size in DIPs.
806+ auto & visual = textItem->GetVisual ();
807+ float2 size = visual.Size ();
808+
809+ // Set the visual's offset.
810+ visual.Offset ({ point.x - size.x / 2 .0f , point.y - size.y / 2 .0f , 0 .0f });
753811
754- float const BlockSize = 30 .0f ;
755- visual.Size ({ BlockSize, BlockSize });
756- visual.Offset ({ point.x - BlockSize / 2 .0f , point.y - BlockSize / 2 .0f , 0 .0f });
812+ // Add the new text element to the vector.
813+ m_items.Items .push_back (std::move (textItem));
757814
815+ // Add the visual as a child of the container visual.
758816 m_items.Visuals .InsertAtTop (visual);
759817
760- m_items.SelectedVisual = visual ;
761- m_items.Offset .x = -BlockSize / 2 .0f ;
762- m_items.Offset .y = -BlockSize / 2 .0f ;
818+ m_items.SelectedItem = m_items. Items . back (). get () ;
819+ m_items.Offset .x = -size. x / 2 .0f ;
820+ m_items.Offset .y = -size. y / 2 .0f ;
763821
764822 Accessibility_CreateItemFragment (visual);
765823 }
0 commit comments