You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
5.4 KiB

--========================================================--
-- Scorpio UI Reactive --
-- --
-- Author : kurapica125@outlook.com --
-- Create Date : 2020/12/22 --
--========================================================--
--========================================================--
Scorpio "Scorpio.UI.Reactive" "1.0.0"
--========================================================--
import "System.Reactive"
local isUIObject = UI.IsUIObject
local isObjectType = Class.IsObjectType
local isProperty = System.Property.Validate
local isIndexerProperty = System.Property.IsIndexer
local getCurrentTarget = Scorpio.UI.Style.GetCurrentTarget
local getFeature = Class.GetFeature
__Static__() __Arguments__{ NEString * 1 }
function Wow.FromUIProperty(...)
local name = select("#", ...) == 1 and name or { ... }
return Observable(function(observer)
local indicator = getCurrentTarget()
if indicator and isUIObject(indicator) then
local frame = indicator
local subject
if type(name) == "string" then
while frame do
subject = Observable.From(frame, name)
if subject then break end
frame = frame:GetParent()
end
else
local nsubject
for _, n in ipairs(name) do
frame = indicator
nsubject = nil
while frame do
nsubject= Observable.From(frame, n)
if nsubject then break end
frame = frame:GetParent()
end
if nsubject then
subject = subject and subject:CombineLatest(nsubject) or nsubject
else
return
end
end
end
if subject then return subject:Subscribe(observer) end
end
end)
end
__Static__() __Arguments__{ NEString * 1 }
function Wow.FromPanelProperty(...)
local name = select("#", ...) == 1 and name or { ... }
return Observable(function(observer)
local indicator = getCurrentTarget()
if indicator and isUIObject(indicator) then
local frame = indicator
local parent = indicator:GetParent()
local index
while parent do
if isObjectType(parent, ElementPanel) then
-- Only check the nearest element panel
index = frame:GetID()
break
end
frame = parent
parent = parent:GetParent()
end
if index then
if type(name) == "string" then
local prop = getFeature(getmetatable(parent), name, true)
local psub = prop and isIndexerProperty(prop) and Observable.From(parent, name)
if not psub then return end
local matchIdx = psub.__MatchIndex
if not matchIdx then
matchIdx = {}
psub.__MatchIndex = matchIdx
psub:Subscribe(function(idx, ...)
local s = matchIdx[idx]
return s and s:OnNext(...)
end)
end
local idxSub = matchIdx[index]
if not idxSub then
idxSub = Subject()
matchIdx[index] = idxSub
end
return idxSub:Subscribe(observer)
else
local subject
for _, n in ipairs(name) do
local prop = getFeature(getmetatable(parent), n, true)
local psub = prop and isIndexerProperty(prop) and Observable.From(parent, n)
if not psub then return end
local matchIdx = psub.__MatchIndex
if not matchIdx then
matchIdx = {}
psub.__MatchIndex = matchIdx
psub:Subscribe(function(idx, ...)
local s = matchIdx[idx]
return s and s:OnNext(...)
end)
end
local idxSub = matchIdx[index]
if not idxSub then
idxSub = Subject()
matchIdx[index] = idxSub
end
subject = subject and subject:CombineLatest(idxSub) or idxSub
end
if subject then subject:Subscribe(observer) end
end
end
end
end)
end