|
|
|
|
--========================================================--
|
|
|
|
|
-- Scorpio Secure UI Framework --
|
|
|
|
|
-- --
|
|
|
|
|
-- Author : kurapica125@outlook.com --
|
|
|
|
|
-- Create Date : 2020/06/04 --
|
|
|
|
|
--========================================================--
|
|
|
|
|
|
|
|
|
|
--========================================================--
|
|
|
|
|
Scorpio "Scorpio.Secure" "1.0.0"
|
|
|
|
|
--========================================================--
|
|
|
|
|
|
|
|
|
|
__Sealed__() __Final__() interface "Scorpio.Secure" {}
|
|
|
|
|
|
|
|
|
|
Environment.RegisterGlobalNamespace("Scorpio.Secure")
|
|
|
|
|
|
|
|
|
|
namespace "Scorpio.Secure"
|
|
|
|
|
|
|
|
|
|
import "Scorpio.UI"
|
|
|
|
|
|
|
|
|
|
-- We can't directly change the secure widgets to the Scorpio UI widget,
|
|
|
|
|
-- we can only use the wrapper/origin model, so to define the functions that
|
|
|
|
|
-- can be called in the secure snippets, we should use __SecureMethod__ attribute
|
|
|
|
|
-- to bind the class object method or the obect method to the secure ui objects
|
|
|
|
|
-- so the system can keep those functions defined in the wrapper/origin at the same time
|
|
|
|
|
_SecureCallMap = {}
|
|
|
|
|
|
|
|
|
|
--- The interface that provide the basic features for secure widgets
|
|
|
|
|
__Sealed__()__ObjFuncAttr__{ Inheritable= true }
|
|
|
|
|
interface "ISecureHandler" (function(_ENV)
|
|
|
|
|
|
|
|
|
|
local GetRawUI = Scorpio.UI.GetRawUI
|
|
|
|
|
local GetProxyUI = Scorpio.UI.GetProxyUI
|
|
|
|
|
local GetSuperClass = Class.GetSuperClass
|
|
|
|
|
|
|
|
|
|
local _RegisterAttributeDriver = RegisterAttributeDriver
|
|
|
|
|
local _UnregisterAttributeDriver = UnregisterAttributeDriver
|
|
|
|
|
local _RegisterStateDriver = RegisterStateDriver
|
|
|
|
|
local _UnregisterStateDriver = UnregisterStateDriver
|
|
|
|
|
local _RegisterUnitWatch = RegisterUnitWatch
|
|
|
|
|
local _UnregisterUnitWatch = UnregisterUnitWatch
|
|
|
|
|
local _UnitWatchRegistered = UnitWatchRegistered
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------
|
|
|
|
|
-- Method
|
|
|
|
|
------------------------------------------------------
|
|
|
|
|
--- Execute a snippet against a header frame
|
|
|
|
|
__Arguments__{ String }
|
|
|
|
|
function Execute(self, body)
|
|
|
|
|
return SecureHandlerExecute(GetRawUI(self), body)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Wrap the script on a frame to invoke snippets against a header
|
|
|
|
|
__Arguments__{ UI, ScriptsType, String/nil, String/nil }
|
|
|
|
|
function WrapScript(self, frame, script, preBody, postBody)
|
|
|
|
|
return SecureHandlerWrapScript(GetRawUI(frame), script, GetRawUI(self), preBody, postBody)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Remove previously applied wrapping, returning its details
|
|
|
|
|
__Arguments__{ UI, ScriptsType }
|
|
|
|
|
function UnwrapScript(self, frame, script)
|
|
|
|
|
return SecureHandlerUnwrapScript(GetRawUI(frame), script)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Create a frame handle reference and store it against a frame
|
|
|
|
|
__Arguments__{ String, UI }
|
|
|
|
|
function SetFrameRef(self, label, refFrame)
|
|
|
|
|
return SecureHandlerSetFrameRef(GetRawUI(self), label, GetRawUI(refFrame))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Register a frame attribute to be set automatically with changes in game state
|
|
|
|
|
__Arguments__{ String, Any }
|
|
|
|
|
function RegisterAttributeDriver(self, attribute, values)
|
|
|
|
|
return _RegisterAttributeDriver(GetRawUI(self), attribute, values)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Unregister a frame from the state driver manager
|
|
|
|
|
__Arguments__{ String }
|
|
|
|
|
function UnregisterAttributeDriver(self, attribute)
|
|
|
|
|
return _UnregisterAttributeDriver(GetRawUI(self), attribute)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Register a frame state to be set automatically with changes in game state
|
|
|
|
|
__Arguments__{ String, Any }
|
|
|
|
|
function RegisterStateDriver(self, state, values)
|
|
|
|
|
return _RegisterStateDriver(GetRawUI(self), state, values)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Unregister a frame from the state driver manager
|
|
|
|
|
__Arguments__{ String }
|
|
|
|
|
function UnregisterStateDriver(self, state)
|
|
|
|
|
return _UnregisterStateDriver(GetRawUI(self), state)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Register a frame to be notified when a unit's existence changes
|
|
|
|
|
__Arguments__{ Boolean/nil }
|
|
|
|
|
function RegisterUnitWatch(self, asState)
|
|
|
|
|
return _RegisterUnitWatch(GetRawUI(self), asState)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Unregister a frame from the unit existence monitor
|
|
|
|
|
function UnregisterUnitWatch(self)
|
|
|
|
|
return _UnregisterUnitWatch(GetRawUI(self))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Check to see if a frame is registered
|
|
|
|
|
function IsUnitWatchRegistered(self)
|
|
|
|
|
return _UnitWatchRegistered(GetRawUI(self))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
__Arguments__{ (String + struct { String })/nil } __NoCombat__()
|
|
|
|
|
function SetAutoHide(self, conds)
|
|
|
|
|
if not conds then
|
|
|
|
|
self:UnregisterStateDriver("visibility")
|
|
|
|
|
self:Show()
|
|
|
|
|
elseif type(conds) == "string" then
|
|
|
|
|
conds = conds:match("%b[]")
|
|
|
|
|
if conds then
|
|
|
|
|
self:RegisterStateDriver("visibility", (conds .. "hide;show"))
|
|
|
|
|
else
|
|
|
|
|
self:UnregisterStateDriver("visibility")
|
|
|
|
|
self:Show()
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
local str = ""
|
|
|
|
|
for _, cond in ipairs(conds) do
|
|
|
|
|
cond = cond:match("%b[]")
|
|
|
|
|
if cond then
|
|
|
|
|
str = str .. cond .. "hide;"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if str == "" then
|
|
|
|
|
self:UnregisterStateDriver("visibility")
|
|
|
|
|
self:Show()
|
|
|
|
|
else
|
|
|
|
|
self:RegisterStateDriver("visibility", str .. "show")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------
|
|
|
|
|
-- Initializer
|
|
|
|
|
------------------------------------------------------
|
|
|
|
|
function __init(self)
|
|
|
|
|
local cls = getmetatable(self)
|
|
|
|
|
self = GetRawUI(self)
|
|
|
|
|
while cls do
|
|
|
|
|
local map = _SecureCallMap[cls]
|
|
|
|
|
if map then
|
|
|
|
|
|
|
|
|
|
for name, func in pairs(map) do
|
|
|
|
|
self[name] = self[name] or func
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
cls = GetSuperClass(cls)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
--- The attribute used to bind functions that be be called by the secure environment
|
|
|
|
|
__Sealed__() __Final__()
|
|
|
|
|
class "__SecureMethod__" (function(_ENV)
|
|
|
|
|
extend "IAttachAttribute"
|
|
|
|
|
|
|
|
|
|
local GetRawUI = Scorpio.UI.GetRawUI
|
|
|
|
|
local GetProxyUI = Scorpio.UI.GetProxyUI
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- method --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
function AttachAttribute(self, target, targettype, owner, name, stack)
|
|
|
|
|
if targettype == AttributeTargets.Method then
|
|
|
|
|
if Class.IsSubType(owner, ISecureHandler) then
|
|
|
|
|
local map = _SecureCallMap[owner] or {}
|
|
|
|
|
_SecureCallMap[owner] = map
|
|
|
|
|
|
|
|
|
|
map[name] = function(self, ...)
|
|
|
|
|
return target(GetProxyUI(self), ...)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if Class.IsObjectType(owner, ISecureHandler) then
|
|
|
|
|
GetRawUI(owner)[name] = function(self, ...)
|
|
|
|
|
return target(owner, ...)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- property --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
--- the attribute target
|
|
|
|
|
property "AttributeTarget" { type = AttributeTargets, default = AttributeTargets.Method + AttributeTargets.Function }
|
|
|
|
|
|
|
|
|
|
--- the attribute's priority
|
|
|
|
|
property "Priority" { type = AttributePriority, default = AttributePriority.Lowest }
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
--- The attribute used to bind secure template for the class objects
|
|
|
|
|
__Sealed__() __Final__()
|
|
|
|
|
class "__SecureTemplate__" (function(_ENV)
|
|
|
|
|
extend "IAttachAttribute"
|
|
|
|
|
|
|
|
|
|
local _SecureTemplateMap = {}
|
|
|
|
|
local _TempList = List()
|
|
|
|
|
|
|
|
|
|
function _TempList:Distinct()
|
|
|
|
|
self:Sort()
|
|
|
|
|
|
|
|
|
|
for i = #self, 1, -1 do
|
|
|
|
|
if self[i] == self[i - 1] then
|
|
|
|
|
self:RemoveByIndex(i)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- method --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
function AttachAttribute(self, target, targettype, owner, name, stack)
|
|
|
|
|
if Class.IsSubType(target, ISecureHandler) then
|
|
|
|
|
_SecureTemplateMap[target] = self.template
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
__Static__() function GetTemplate(cls, template)
|
|
|
|
|
local default = _SecureTemplateMap[cls]
|
|
|
|
|
while cls and default == nil do
|
|
|
|
|
cls = Class.GetSuperClass(cls)
|
|
|
|
|
default = cls and _SecureTemplateMap[cls]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if default then
|
|
|
|
|
_TempList:Clear()
|
|
|
|
|
|
|
|
|
|
_TempList:Extend(default:gmatch("[%w_]+"))
|
|
|
|
|
if type(template) == "string" then
|
|
|
|
|
_TempList:Extend(template:gmatch("[%w_]+"))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return _TempList:Distinct():Join(",")
|
|
|
|
|
elseif type(template) == "string" then
|
|
|
|
|
return template
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- property --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
--- the attribute target
|
|
|
|
|
property "AttributeTarget" { type = AttributeTargets, default = AttributeTargets.Class }
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- constructor --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
__Arguments__{ String/nil }
|
|
|
|
|
function __ctor(self, template)
|
|
|
|
|
self.template = template or false
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
--- SecureFrame is a root widget class for secure frames
|
|
|
|
|
__Sealed__() __SecureTemplate__"SecureFrameTemplate"
|
|
|
|
|
class "SecureFrame" {
|
|
|
|
|
Frame, ISecureHandler,
|
|
|
|
|
|
|
|
|
|
__new = function(cls, name, parent, inherits)
|
|
|
|
|
local ui = CreateFrame("Frame", name, parent, __SecureTemplate__.GetTemplate(cls, inherits))
|
|
|
|
|
local self = { [0] = ui[0] }
|
|
|
|
|
UI.RegisterProxyUI(self)
|
|
|
|
|
UI.RegisterRawUI(ui)
|
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--- SecureButton is used as the root widget class for secure buttons
|
|
|
|
|
__Sealed__() __SecureTemplate__"SecureActionButtonTemplate"
|
|
|
|
|
class "SecureButton" {
|
|
|
|
|
Button, ISecureHandler,
|
|
|
|
|
|
|
|
|
|
__new = function(cls, name, parent, inherits)
|
|
|
|
|
local ui = CreateFrame("Button", name, parent, __SecureTemplate__.GetTemplate(cls, inherits))
|
|
|
|
|
local self = { [0] = ui[0] }
|
|
|
|
|
UI.RegisterProxyUI(self)
|
|
|
|
|
UI.RegisterRawUI(ui)
|
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--- SecureCheckButton is used as the root widget class for secure check buttons
|
|
|
|
|
__Sealed__() __SecureTemplate__"SecureActionButtonTemplate"
|
|
|
|
|
class "SecureCheckButton" {
|
|
|
|
|
CheckButton, ISecureHandler,
|
|
|
|
|
|
|
|
|
|
__new = function(cls, name, parent, inherits)
|
|
|
|
|
local ui = CreateFrame("CheckButton", name, parent, __SecureTemplate__.GetTemplate(cls, inherits))
|
|
|
|
|
local self = { [0] = ui[0] }
|
|
|
|
|
UI.RegisterProxyUI(self)
|
|
|
|
|
UI.RegisterRawUI(ui)
|
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
-- Style Property --
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
UI.Property {
|
|
|
|
|
name = "AutoHide",
|
|
|
|
|
type = String + struct { String },
|
|
|
|
|
require = { SecureFrame, SecureButton, SecureCheckButton },
|
|
|
|
|
set = function(self, val) self:SetAutoHide(val) end,
|
|
|
|
|
clear = function(self) self:SetAutoHide(nil) end,
|
|
|
|
|
}
|