--========================================================-- -- 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