Skip to content

Commit 256af52

Browse files
committed
add portal component for uitoolkit
1 parent b0b4b0d commit 256af52

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
using UnityEngine.UIElements;
2+
3+
namespace ReactUnity.UIToolkit
4+
{
5+
public class PortalComponent : UIToolkitComponent<VisualElement>, IShadowComponent
6+
{
7+
VisualElement DefaultTarget => (Context.Host as UIToolkitComponent<VisualElement>).TargetElement;
8+
public IReactComponent ShadowParent { get; private set; }
9+
10+
VisualElement currentTarget;
11+
12+
public bool Detached { get; private set; }
13+
public VisualElement ReplacedLayout { get; } = new VisualElement();
14+
15+
public PortalComponent(UIToolkitContext context, string tag = "portal") : base(context, tag)
16+
{
17+
ShadowParent = Context.Host;
18+
currentTarget = DefaultTarget;
19+
ReplacedLayout.style.display = DisplayStyle.None;
20+
ReplacedLayout.userData = this;
21+
}
22+
23+
void SetTarget(VisualElement target, IReactComponent shadowParent)
24+
{
25+
VisualElement newTarget;
26+
27+
if (target != null)
28+
{
29+
newTarget = target;
30+
ShadowParent = shadowParent;
31+
}
32+
else
33+
{
34+
newTarget = DefaultTarget;
35+
ShadowParent = Context.Host;
36+
}
37+
if (currentTarget == newTarget) return;
38+
39+
if (currentTarget != null)
40+
{
41+
FireEvent("onUnmount", currentTarget);
42+
currentTarget = null;
43+
}
44+
45+
currentTarget = newTarget;
46+
47+
if (currentTarget != null)
48+
{
49+
FireEvent("onMount", currentTarget);
50+
}
51+
52+
Attach();
53+
}
54+
55+
public override void SetParent(IContainerComponent newParent, IReactComponent relativeTo = null, bool insertAfter = false)
56+
{
57+
if (Parent is UIToolkitComponent<VisualElement> pp)
58+
{
59+
pp.Element?.Remove(ReplacedLayout);
60+
}
61+
62+
base.SetParent(newParent, relativeTo, insertAfter);
63+
64+
if (Parent is UIToolkitComponent<VisualElement> p)
65+
{
66+
var oldParent = p.Element;
67+
if (oldParent != null)
68+
{
69+
var layoutIndex = oldParent.IndexOf(Element);
70+
71+
if (layoutIndex >= 0)
72+
{
73+
oldParent.RemoveAt(layoutIndex);
74+
oldParent.Insert(layoutIndex, ReplacedLayout);
75+
}
76+
}
77+
}
78+
79+
Attach();
80+
}
81+
82+
void Attach()
83+
{
84+
if (Parent == null || Destroyed)
85+
{
86+
if (Element?.parent != null)
87+
{
88+
Element.RemoveFromHierarchy();
89+
90+
ReplacedLayout.RemoveFromHierarchy();
91+
Context.DetachedRoots.Remove(this);
92+
}
93+
return;
94+
}
95+
96+
if (Element != null && Element.parent != currentTarget)
97+
{
98+
if (currentTarget != null) currentTarget.Add(Element);
99+
else Element.RemoveFromHierarchy();
100+
101+
if (ShadowParent is UIToolkitComponent<VisualElement> sp)
102+
{
103+
sp.Element.Add(Element);
104+
Detached = false;
105+
Context.DetachedRoots.Remove(this);
106+
}
107+
else
108+
{
109+
Detached = true;
110+
Context.DetachedRoots.Add(this);
111+
}
112+
113+
ResolveStyle(true);
114+
}
115+
}
116+
117+
(VisualElement, IReactComponent) FindTarget(object value)
118+
{
119+
if (value == null) return (null, null);
120+
if (value is VisualElement t) return (t, null);
121+
if (value is UIToolkitComponent<VisualElement> u) return (u.Element, u);
122+
return (null, null);
123+
}
124+
125+
public override void SetProperty(string propertyName, object value)
126+
{
127+
switch (propertyName)
128+
{
129+
case "target":
130+
var tg = FindTarget(value);
131+
SetTarget(tg.Item1, tg.Item2?.Context == Context ? tg.Item2 : null);
132+
break;
133+
default:
134+
base.SetProperty(propertyName, value);
135+
break;
136+
}
137+
}
138+
139+
protected override void DestroySelf()
140+
{
141+
SetTarget(null, null);
142+
base.DestroySelf();
143+
}
144+
145+
public override bool Pool()
146+
{
147+
SetTarget(null, null);
148+
if (!base.Pool()) return false;
149+
return true;
150+
}
151+
152+
public override bool Revive()
153+
{
154+
if (!base.Revive()) return false;
155+
Element.RemoveFromHierarchy();
156+
return true;
157+
}
158+
}
159+
}

Runtime/Frameworks/UIToolkit/Components/PortalComponent.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Frameworks/UIToolkit/General/UIToolkitContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class UIToolkitContext : ReactContext
2828
public static Dictionary<string, Func<string, string, UIToolkitContext, IReactComponent>> ComponentCreators
2929
= new Dictionary<string, Func<string, string, UIToolkitContext, IReactComponent>>()
3030
{
31+
{ "portal", (tag, text, context) => new PortalComponent(context, tag) },
3132
{ "text", (tag, text, context) => new TextComponent<TextElement>(text, context, tag, false) },
3233
{ "br", (tag, text, context) => new BrComponent(context, tag) },
3334
{ "richtext", (tag, text, context) => new TextComponent<TextElement>(text, context, tag, false, true) },

0 commit comments

Comments
 (0)