rotor-framework 0.7.3 β 0.7.5
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/README.md
CHANGED
|
@@ -96,7 +96,7 @@ You can find [π±](./docs/ai/readme.opt.yaml) symbols in all documentation page
|
|
|
96
96
|
|
|
97
97
|
## π Learn More
|
|
98
98
|
|
|
99
|
-

|
|
100
100
|
|
|
101
101
|
### Framework Core
|
|
102
102
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rotor-framework",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Roku toolkit library providing a ViewBuilder, full UI lifecycle with focus handling and many core features, plus MVI-based state management.",
|
|
5
5
|
"author": "BalΓ‘zs MolnΓ‘r",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
' βββββββ ββ β ββ βββββββ βββββββββββββββββ βββββββββ ββββ βββββββββββ
|
|
5
5
|
' ββ βββββββ β βββββββ ββ ββ ββ ββββ ββββ βββββββββββββββββββ ββββ ββ
|
|
6
6
|
' Rotor Frameworkβ’
|
|
7
|
-
' Version 0.7.
|
|
7
|
+
' Version 0.7.5
|
|
8
8
|
' Β© 2025 BalΓ‘zs MolnΓ‘r β Apache License 2.0
|
|
9
9
|
' =========================================================================
|
|
10
10
|
|
|
@@ -86,7 +86,7 @@ namespace Rotor
|
|
|
86
86
|
class Framework
|
|
87
87
|
|
|
88
88
|
name = "Rotor Framework"
|
|
89
|
-
version = "0.7.
|
|
89
|
+
version = "0.7.5"
|
|
90
90
|
|
|
91
91
|
config = {
|
|
92
92
|
tasks: invalid, ' @array (optional)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
' βββββββ ββ β ββ βββββββ βββββββββββββββββ βββββββββ ββββ βββββββββββ
|
|
5
5
|
' ββ βββββββ β βββββββ ββ ββ ββ ββββ ββββ βββββββββββββββββββ ββββ ββ
|
|
6
6
|
' Rotor Frameworkβ’
|
|
7
|
-
' Version 0.7.
|
|
7
|
+
' Version 0.7.5
|
|
8
8
|
' Β© 2025 BalΓ‘zs MolnΓ‘r β Apache License 2.0
|
|
9
9
|
' =========================================================================
|
|
10
10
|
|
|
@@ -70,7 +70,7 @@ namespace Rotor
|
|
|
70
70
|
class FrameworkTask
|
|
71
71
|
|
|
72
72
|
name = "Rotor Framework"
|
|
73
|
-
version = "0.7.
|
|
73
|
+
version = "0.7.5"
|
|
74
74
|
|
|
75
75
|
config = {
|
|
76
76
|
tasks: invalid, ' optional
|
|
@@ -24,6 +24,7 @@ namespace Rotor
|
|
|
24
24
|
' =============================================================
|
|
25
25
|
|
|
26
26
|
id as string ' Widget identifier
|
|
27
|
+
HID as string ' Hierarchical unique ID
|
|
27
28
|
children as object ' Child widgets collection
|
|
28
29
|
|
|
29
30
|
' =============================================================
|
|
@@ -100,7 +101,6 @@ namespace Rotor
|
|
|
100
101
|
' PRIVATE PROPERTIES (Engine Use Only)
|
|
101
102
|
' =============================================================
|
|
102
103
|
|
|
103
|
-
private HID as string ' Hierarchical ID (e.g., "0.header.logo")
|
|
104
104
|
private vmHID as string ' Owning ViewModel's HID
|
|
105
105
|
private isRootChild as boolean ' True if direct child of root
|
|
106
106
|
private childrenHIDhash as object ' Hash of child HIDs for fast lookup
|
|
@@ -290,10 +290,18 @@ namespace Rotor.ViewBuilder
|
|
|
290
290
|
index = rootChildCount - 1
|
|
291
291
|
|
|
292
292
|
while index >= 0 and inserted = false
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
293
|
+
siblingNode = siblingNodes[index]
|
|
294
|
+
' Find matching widget by node reference
|
|
295
|
+
matchingWidget = invalid
|
|
296
|
+
for each childId in widget.parent.children
|
|
297
|
+
child = widget.parent.children[childId]
|
|
298
|
+
if child.node <> invalid and child.node.isSameNode(siblingNode)
|
|
299
|
+
matchingWidget = child
|
|
300
|
+
exit for
|
|
301
|
+
end if
|
|
302
|
+
end for
|
|
303
|
+
if Rotor.Utils.isInteger(matchingWidget?.zIndex) and matchingWidget?.zIndex <= zIndex
|
|
304
|
+
inserted = true
|
|
297
305
|
else
|
|
298
306
|
index--
|
|
299
307
|
end if
|
|
@@ -325,7 +333,4 @@ namespace Rotor.ViewBuilder
|
|
|
325
333
|
|
|
326
334
|
end class
|
|
327
335
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
336
|
end namespace
|
|
@@ -121,6 +121,13 @@ namespace Rotor
|
|
|
121
121
|
' 2. group.defaultFocusId [CONFIGURED]
|
|
122
122
|
' 3. Deep search (if defaultFocusId not found immediately)
|
|
123
123
|
'
|
|
124
|
+
' RULE #11b: Deep Focus Tracking (trackDescendantFocus: true)
|
|
125
|
+
' When a FocusGroup has trackDescendantFocus: true, it stores lastFocusedHID
|
|
126
|
+
' for ANY descendant FocusItem (not just direct children).
|
|
127
|
+
' - Immediate parent ALWAYS stores lastFocusedHID (default behavior)
|
|
128
|
+
' - Ancestor groups with trackDescendantFocus: true ALSO store it
|
|
129
|
+
' - Enables "deep focus memory" - returning to deeply nested items
|
|
130
|
+
'
|
|
124
131
|
' RULE #12: DefaultFocusId Targets
|
|
125
132
|
' - FocusItem node ID β Focus goes directly to it
|
|
126
133
|
' - Group node ID β Capturing continues on that group
|
|
@@ -636,6 +643,7 @@ namespace Rotor
|
|
|
636
643
|
' Record the last focused item within its parent group for potential future use (e.g., returning focus)
|
|
637
644
|
lastFocusChainingGroups = m.findAncestorGroups(m.globalFocusHID)
|
|
638
645
|
if lastFocusChainingGroups.Count() > 0
|
|
646
|
+
' Always set on immediate parent (index 0)
|
|
639
647
|
parentGroupHID = lastFocusChainingGroups[0]
|
|
640
648
|
if parentGroupHID <> invalid and parentGroupHID <> ""
|
|
641
649
|
group = m.groupStack.get(parentGroupHID)
|
|
@@ -652,9 +660,20 @@ namespace Rotor
|
|
|
652
660
|
for each groupHID in focusChainGroups
|
|
653
661
|
allAffectedGroups.unshift(groupHID) ' Add in reverse order (highest ancestor first)
|
|
654
662
|
end for
|
|
655
|
-
for
|
|
663
|
+
for i = 0 to lastFocusChainingGroups.Count() - 1
|
|
664
|
+
groupHID = lastFocusChainingGroups[i]
|
|
665
|
+
|
|
666
|
+
' Add to allAffectedGroups if not present
|
|
656
667
|
if -1 = Rotor.Utils.findInArray(allAffectedGroups, groupHID)
|
|
657
|
-
allAffectedGroups.unshift(groupHID)
|
|
668
|
+
allAffectedGroups.unshift(groupHID)
|
|
669
|
+
end if
|
|
670
|
+
|
|
671
|
+
' Deep remember (skip index 0 - immediate parent is handled separately)
|
|
672
|
+
if i > 0 and lastFocused <> invalid
|
|
673
|
+
ancestorGroup = m.groupStack.get(groupHID)
|
|
674
|
+
if ancestorGroup <> invalid and ancestorGroup.trackDescendantFocus = true
|
|
675
|
+
ancestorGroup.setLastFocusedHID(m.globalFocusHID)
|
|
676
|
+
end if
|
|
658
677
|
end if
|
|
659
678
|
end for
|
|
660
679
|
|
|
@@ -1279,11 +1298,13 @@ namespace Rotor
|
|
|
1279
1298
|
m.defaultFocusId = config.defaultFocusId ?? ""
|
|
1280
1299
|
m.lastFocusedHID = config.lastFocusedHID ?? ""
|
|
1281
1300
|
m.enableSpatialEnter = config.enableSpatialEnter ?? false
|
|
1301
|
+
m.trackDescendantFocus = config.trackDescendantFocus ?? false
|
|
1282
1302
|
end sub
|
|
1283
1303
|
|
|
1284
1304
|
defaultFocusId as string
|
|
1285
1305
|
lastFocusedHID as string
|
|
1286
1306
|
enableSpatialEnter as boolean
|
|
1307
|
+
trackDescendantFocus as boolean
|
|
1287
1308
|
focusItemsRef as object
|
|
1288
1309
|
groupsRef as object
|
|
1289
1310
|
|