@@ -14,6 +14,7 @@ namespace winrt::DrawingIslandComponents::implementation
14
14
const winrt::Compositor& compositor)
15
15
{
16
16
m_output.Compositor = compositor;
17
+ m_output.TextRenderer = std::make_shared<TextRenderer>(m_output.Compositor );
17
18
18
19
// Create the Compositor and the Content:
19
20
// - The Bridge's connection to the Window will keep everything alive, and perform an
@@ -75,7 +76,8 @@ namespace winrt::DrawingIslandComponents::implementation
75
76
m_background.Visual = nullptr ;
76
77
77
78
m_items.Visuals = nullptr ;
78
- m_items.SelectedVisual = nullptr ;
79
+ m_items.Items .clear ();
80
+ m_items.SelectedItem = nullptr ;
79
81
80
82
// TODO: Enable Mica on Win 11
81
83
#if FALSE
@@ -234,11 +236,13 @@ namespace winrt::DrawingIslandComponents::implementation
234
236
winrt::Windows::Graphics::RectInt32 screenRect{ static_cast <int >(x + 0.5 ), static_cast <int >(y + 0.5 ), 0 , 0 };
235
237
auto logicalRect = m_island.CoordinateConverter ().ConvertScreenToLocal (screenRect);
236
238
float2 localPoint{ logicalRect.X , logicalRect.Y };
237
- auto hitTestVisual = HitTestVisual (localPoint);
239
+ auto hitTestElement = HitTestItem (localPoint);
238
240
239
241
// Find the automation peer for the hit test visual if any.
240
- if (nullptr != hitTestVisual )
242
+ if (nullptr != hitTestElement )
241
243
{
244
+ auto & hitTestVisual = hitTestElement->GetVisual ();
245
+
242
246
auto iterator = std::find_if (
243
247
m_uia.AutomationPeers .begin (), m_uia.AutomationPeers .end (), [&hitTestVisual](auto const & automationPeer)
244
248
{
@@ -259,30 +263,36 @@ namespace winrt::DrawingIslandComponents::implementation
259
263
winrt::com_ptr<IRawElementProviderFragment>
260
264
DrawingIsland::GetFragmentInFocus () const
261
265
{
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 )
270
267
{
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
+ }
273
282
}
274
283
275
284
return nullptr ;
276
285
}
277
286
278
287
279
- winrt::Visual
280
- DrawingIsland::HitTestVisual (
281
- float2 const & point) const
288
+ Item* DrawingIsland::HitTestItem (float2 const & point) const
282
289
{
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-- )
285
292
{
293
+ Item* item = m_items.Items [i - 1 ].get ();
294
+ auto & visual = item->GetVisual ();
295
+
286
296
winrt::float3 const offset = visual.Offset ();
287
297
float2 const size = visual.Size ();
288
298
@@ -291,11 +301,10 @@ namespace winrt::DrawingIslandComponents::implementation
291
301
point.y >= offset.y &&
292
302
point.y < offset.y + size.y )
293
303
{
294
- selectedVisual = visual ;
304
+ return item ;
295
305
}
296
306
}
297
-
298
- return selectedVisual;
307
+ return nullptr ;
299
308
}
300
309
301
310
@@ -507,6 +516,7 @@ namespace winrt::DrawingIslandComponents::implementation
507
516
case winrt::Windows::System::VirtualKey::Escape:
508
517
{
509
518
m_items.Visuals .RemoveAll ();
519
+ m_items.Items .clear ();
510
520
511
521
// Update accessibility.
512
522
m_uia.FragmentRoot ->RemoveAllChildren ();
@@ -581,7 +591,7 @@ namespace winrt::DrawingIslandComponents::implementation
581
591
void
582
592
DrawingIsland::Input_OnPointerReleased ()
583
593
{
584
- m_items.SelectedVisual = nullptr ;
594
+ m_items.SelectedItem = nullptr ;
585
595
}
586
596
587
597
@@ -608,22 +618,39 @@ namespace winrt::DrawingIslandComponents::implementation
608
618
const float2 point,
609
619
bool controlPressed)
610
620
{
611
- m_items.SelectedVisual = HitTestVisual (point);
621
+ m_items.SelectedItem = HitTestItem (point);
612
622
613
- if (m_items.SelectedVisual )
623
+ if (m_items.SelectedItem != nullptr )
614
624
{
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 ();
616
628
617
629
m_items.Offset .x = offset.x - point.x ;
618
630
m_items.Offset .y = offset.y - point.y ;
619
631
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
+ }
622
649
623
650
// Update automation.
624
651
// First find the existing automation peer.
625
652
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)
627
654
{
628
655
return automationPeer.Match (visual);
629
656
});
@@ -651,18 +678,21 @@ namespace winrt::DrawingIslandComponents::implementation
651
678
void
652
679
DrawingIsland::OnRightClick (const float2 point)
653
680
{
654
- winrt::Visual selectedVisual = HitTestVisual (point);
681
+ // TODO - what is the purpose of this?
682
+ UNREFERENCED_PARAMETER (point);
683
+ // VisualElement* selectedVisual = HitTestVisual(point);
655
684
}
656
685
657
686
void
658
687
DrawingIsland::Input_OnPointerMoved (
659
688
const winrt::PointerEventArgs& args)
660
689
{
661
- if (m_items.SelectedVisual )
690
+ if (m_items.SelectedItem )
662
691
{
692
+ auto & visual = m_items.SelectedItem ->GetVisual ();
663
693
float2 const point = args.CurrentPoint ().Position ();
664
694
665
- m_items. SelectedVisual .Offset (
695
+ visual .Offset (
666
696
{ point.x + m_items.Offset .x ,
667
697
point.y + m_items.Offset .y ,
668
698
0 .0f });
@@ -682,7 +712,16 @@ namespace winrt::DrawingIslandComponents::implementation
682
712
{
683
713
if (m_prevState.RasterizationScale != m_island.RasterizationScale ())
684
714
{
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
+ }
686
725
}
687
726
688
727
if (m_prevState.LayoutDirection != m_island.LayoutDirection ())
@@ -746,20 +785,39 @@ namespace winrt::DrawingIslandComponents::implementation
746
785
float2 const point,
747
786
bool halfTransparent)
748
787
{
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 });
753
811
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));
757
814
815
+ // Add the visual as a child of the container visual.
758
816
m_items.Visuals .InsertAtTop (visual);
759
817
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 ;
763
821
764
822
Accessibility_CreateItemFragment (visual);
765
823
}
0 commit comments