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.
465 lines
16 KiB
465 lines
16 KiB
|
5 years ago
|
--========================================================--
|
||
|
|
-- Scorpio Secure Element Panel --
|
||
|
|
-- --
|
||
|
|
-- Author : kurapica125@outlook.com --
|
||
|
|
-- Create Date : 2020/11/12 --
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
--========================================================--
|
||
|
|
Scorpio "Scorpio.Secure.SecurePanel" "1.0.0"
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
-----------------------------------------------------------
|
||
|
|
-- Secure Element Panel Widget --
|
||
|
|
-----------------------------------------------------------
|
||
|
|
__Sealed__()
|
||
|
|
class "SecurePanel" (function(_ENV)
|
||
|
|
inherit "SecureFrame" extend "ICountable"
|
||
|
|
|
||
|
|
-------------------------------------
|
||
|
|
-- Secure Manager
|
||
|
|
-------------------------------------
|
||
|
|
-- Manager Frame
|
||
|
|
_ManagerFrame = SecureFrame("Scorpio_SecurePanel_LayoutMananger", UIParent, "SecureHandlerStateTemplate")
|
||
|
|
_ManagerFrame:Hide()
|
||
|
|
|
||
|
|
_ManagerFrame:Execute[[
|
||
|
|
Manager = self
|
||
|
|
|
||
|
|
_Panels = newtable()
|
||
|
|
_Cache = newtable()
|
||
|
|
_Map = newtable()
|
||
|
|
|
||
|
|
_Queue = newtable()
|
||
|
|
|
||
|
|
QueueUpdatePanel = [=[
|
||
|
|
local panel = _Map[self] or self
|
||
|
|
local noForce= ...
|
||
|
|
|
||
|
|
if not noForce then
|
||
|
|
_Queue[panel] = false
|
||
|
|
elseif _Queue[panel] == nil then
|
||
|
|
_Queue[panel] = true
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Reset the timer
|
||
|
|
Manager:SetAttribute("state-timer", "reset")
|
||
|
|
]=]
|
||
|
|
|
||
|
|
UnQueueUpdatePanel = [=[
|
||
|
|
local panel = _Map[self] or self
|
||
|
|
_Queue[panel] = nil
|
||
|
|
]=]
|
||
|
|
|
||
|
|
UpdatePanelSize = [=[
|
||
|
|
local noForce = ...
|
||
|
|
local panel = _Map[self] or self
|
||
|
|
local elements = _Panels[panel]
|
||
|
|
local count = 0
|
||
|
|
|
||
|
|
local row
|
||
|
|
local column
|
||
|
|
local columnCount = panel:GetAttribute("IFSecurePanel_ColumnCount") or 5
|
||
|
|
local rowCount = panel:GetAttribute("IFSecurePanel_RowCount") or 5
|
||
|
|
local elementWidth = panel:GetAttribute("IFSecurePanel_ElementWidth") or 16
|
||
|
|
local elementHeight = panel:GetAttribute("IFSecurePanel_ElementHeight") or 16
|
||
|
|
local hSpacing = panel:GetAttribute("IFSecurePanel_HSpacing") or 0
|
||
|
|
local vSpacing = panel:GetAttribute("IFSecurePanel_VSpacing") or 0
|
||
|
|
local marginTop = panel:GetAttribute("IFSecurePanel_MarginTop") or 0
|
||
|
|
local marginBottom = panel:GetAttribute("IFSecurePanel_MarginBottom") or 0
|
||
|
|
local marginLeft = panel:GetAttribute("IFSecurePanel_MarginLeft") or 0
|
||
|
|
local marginRight = panel:GetAttribute("IFSecurePanel_MarginRight") or 0
|
||
|
|
local orientation = panel:GetAttribute("IFSecurePanel_Orientation") or "HORIZONTAL"
|
||
|
|
local leftToRight = panel:GetAttribute("IFSecurePanel_LeftToRight")
|
||
|
|
local topToBottom = panel:GetAttribute("IFSecurePanel_TopToBottom")
|
||
|
|
local autoPos = panel:GetAttribute("IFSecurePanel_AutoPosition")
|
||
|
|
local autoSize = panel:GetAttribute("IFSecurePanel_AutoSize")
|
||
|
|
|
||
|
|
if leftToRight == nil then leftToRight = true end
|
||
|
|
if topToBottom == nil then topToBottom = true end
|
||
|
|
if autoPos == nil then autoPos = true end
|
||
|
|
if autoSize== nil then autoSize = true end
|
||
|
|
|
||
|
|
if elements then
|
||
|
|
for i = 1, #elements do
|
||
|
|
local frm = elements[i]
|
||
|
|
|
||
|
|
frm:SetWidth(elementWidth)
|
||
|
|
frm:SetHeight(elementHeight)
|
||
|
|
|
||
|
|
if not autoPos or frm:IsShown() then
|
||
|
|
local posX = (orientation == "HORIZONTAL" and count % columnCount or floor(count / rowCount)) * (elementWidth + hSpacing)
|
||
|
|
local posY = (orientation == "HORIZONTAL" and floor(count / columnCount) or count % rowCount) * (elementHeight + vSpacing)
|
||
|
|
|
||
|
|
frm:ClearAllPoints()
|
||
|
|
|
||
|
|
if topToBottom then
|
||
|
|
frm:SetPoint("TOP", panel, "TOP", 0, - posY - marginTop)
|
||
|
|
else
|
||
|
|
frm:SetPoint("BOTTOM", panel, "BOTTOM", 0, posY + marginBottom)
|
||
|
|
end
|
||
|
|
|
||
|
|
if leftToRight then
|
||
|
|
frm:SetPoint("LEFT", panel, "LEFT", posX + marginLeft, 0)
|
||
|
|
else
|
||
|
|
frm:SetPoint("RIGHT", panel, "RIGHT", - posX - marginRight, 0)
|
||
|
|
end
|
||
|
|
|
||
|
|
count = count + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if not panel:GetAttribute("IFSecurePanel_KeepMaxSize") then
|
||
|
|
if not noForce or autoSize then
|
||
|
|
if count ~= _Cache[panel] then
|
||
|
|
_Cache[panel] = count
|
||
|
|
|
||
|
|
if orientation == "HORIZONTAL" then
|
||
|
|
row = ceil(count / columnCount)
|
||
|
|
column = row == 1 and count or columnCount
|
||
|
|
else
|
||
|
|
column = ceil(count / rowCount)
|
||
|
|
row = column == 1 and count or rowCount
|
||
|
|
end
|
||
|
|
|
||
|
|
if panel:GetAttribute("IFSecurePanel_KeepColumnSize") then
|
||
|
|
column = columnCount
|
||
|
|
if row == 0 then row = 1 end
|
||
|
|
end
|
||
|
|
if panel:GetAttribute("IFSecurePanel_KeepRowSize") then
|
||
|
|
row = rowCount
|
||
|
|
if column == 0 then column = 1 end
|
||
|
|
end
|
||
|
|
|
||
|
|
if row > 0 and column > 0 then
|
||
|
|
panel:SetWidth(column * elementWidth + (column - 1) * hSpacing + marginLeft + marginRight)
|
||
|
|
panel:SetHeight(row * elementHeight + (row - 1) * vSpacing + marginTop + marginBottom)
|
||
|
|
else
|
||
|
|
panel:SetWidth(1)
|
||
|
|
panel:SetHeight(1)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
panel:SetWidth(columnCount * elementWidth + (columnCount - 1) * hSpacing + marginLeft + marginRight)
|
||
|
|
panel:SetHeight(rowCount * elementHeight + (rowCount - 1) * vSpacing + marginTop + marginBottom)
|
||
|
|
end
|
||
|
|
]=]
|
||
|
|
]]
|
||
|
|
|
||
|
|
-- The condition has no real use, just a timer ticker
|
||
|
|
_ManagerFrame:SetAttribute("_onstate-timer", [=[
|
||
|
|
if newstate ~= "reset" then
|
||
|
|
for obj, noForce in pairs(_Queue) do
|
||
|
|
Manager:RunFor(obj, UpdatePanelSize, noForce)
|
||
|
|
end
|
||
|
|
|
||
|
|
wipe(_Queue)
|
||
|
|
end
|
||
|
|
]=])
|
||
|
|
_ManagerFrame:RegisterStateDriver("timer", "[pet]pet;nopet;")
|
||
|
|
|
||
|
|
_RegisterPanel = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
|
||
|
|
if panel and not _Panels[panel] then
|
||
|
|
_Panels[panel] = newtable()
|
||
|
|
end
|
||
|
|
]=]
|
||
|
|
|
||
|
|
_UnregisterPanel = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
|
||
|
|
if panel then
|
||
|
|
_Panels[panel] = nil
|
||
|
|
_Cache[panel] = nil
|
||
|
|
end
|
||
|
|
]=]
|
||
|
|
|
||
|
|
_RegisterFrame = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
local frame = Manager:GetFrameRef("SecureElement")
|
||
|
|
|
||
|
|
if panel and frame then
|
||
|
|
_Panels[panel] = _Panels[panel] or newtable()
|
||
|
|
tinsert(_Panels[panel], frame)
|
||
|
|
|
||
|
|
_Map[frame] = panel
|
||
|
|
end
|
||
|
|
]=]
|
||
|
|
|
||
|
|
_UnregisterFrame = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
local frame = Manager:GetFrameRef("SecureElement")
|
||
|
|
|
||
|
|
_Map[frame] = nil
|
||
|
|
|
||
|
|
if panel and frame and _Panels[panel] then
|
||
|
|
for k, v in ipairs(_Panels[panel]) do
|
||
|
|
if v == frame then
|
||
|
|
return tremove(_Panels[panel], k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
]=]
|
||
|
|
|
||
|
|
_WrapShow = [[
|
||
|
|
Manager:RunFor(self, QueueUpdatePanel, true)
|
||
|
|
]]
|
||
|
|
|
||
|
|
_WrapHide = [[
|
||
|
|
Manager:RunFor(self, QueueUpdatePanel, true)
|
||
|
|
]]
|
||
|
|
|
||
|
|
_UpdatePanelSize = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
|
||
|
|
_Cache[panel] = nil
|
||
|
|
Manager:RunFor(panel, QueueUpdatePanel)
|
||
|
|
]=]
|
||
|
|
|
||
|
|
_ForceUpdatePanel = [=[
|
||
|
|
local panel = Manager:GetFrameRef("SecurePanel")
|
||
|
|
|
||
|
|
_Cache[panel] = nil
|
||
|
|
Manager:RunFor(panel, UnQueueUpdatePanel)
|
||
|
|
Manager:RunFor(panel, UpdatePanelSize)
|
||
|
|
]=]
|
||
|
|
|
||
|
|
local function registerPanel(self)
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:Execute(_RegisterPanel)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function unregisterPanel(self)
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:Execute(_UnregisterPanel)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function registerFrame(self, frame)
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:SetFrameRef("SecureElement", frame)
|
||
|
|
_ManagerFrame:Execute(_RegisterFrame)
|
||
|
|
|
||
|
|
_ManagerFrame:WrapScript(frame, "OnShow", _WrapShow)
|
||
|
|
_ManagerFrame:WrapScript(frame, "OnHide", _WrapHide)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function unregisterFrame(self, frame)
|
||
|
|
_ManagerFrame:UnwrapScript(frame, "OnShow")
|
||
|
|
_ManagerFrame:UnwrapScript(frame, "OnHide")
|
||
|
|
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:SetFrameRef("SecureElement", frame)
|
||
|
|
_ManagerFrame:Execute(_UnregisterFrame)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function secureUpdatePanelSize(self)
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:Execute(_UpdatePanelSize)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function nextItem(self, index)
|
||
|
|
index = index + 1
|
||
|
|
local ele = self[index]
|
||
|
|
if ele then return index, ele end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function reduce(self, index)
|
||
|
|
index = index or self.RowCount * self.ColumnCount
|
||
|
|
|
||
|
|
if index < self.Count then
|
||
|
|
for i = self.Count, index + 1, -1 do
|
||
|
|
local ele = self[i]
|
||
|
|
self[i] = nil
|
||
|
|
|
||
|
|
ele:Hide()
|
||
|
|
OnElementRemove(self, ele)
|
||
|
|
|
||
|
|
self.ElementPool(ele)
|
||
|
|
self:SetAttribute("IFSecurePanel_Count", i - 1)
|
||
|
|
end
|
||
|
|
|
||
|
|
return secureUpdatePanelSize(self)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function generate(self, index)
|
||
|
|
if self.ElementPool and index > self.Count then
|
||
|
|
for i = self.Count + 1, index do
|
||
|
|
local ele = self.ElementPool()
|
||
|
|
self[i] = ele
|
||
|
|
ele:SetParent(self)
|
||
|
|
ele:SetID(i)
|
||
|
|
|
||
|
|
ele:Show()
|
||
|
|
OnElementAdd(self, ele)
|
||
|
|
|
||
|
|
self:SetAttribute("IFSecurePanel_Count", i)
|
||
|
|
end
|
||
|
|
|
||
|
|
return secureUpdatePanelSize(self)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function handlePropertyChange(self, prop, value)
|
||
|
|
self:SetAttribute("IFSecurePanel_" .. prop, value)
|
||
|
|
|
||
|
|
if prop == "RowCount" or prop == "ColumnCount" then reduce(self) end
|
||
|
|
return secureUpdatePanelSize(self)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function onPropertyChanged(self, value, old, prop)
|
||
|
|
return NoCombat(handlePropertyChange, self, prop, value)
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
------------------------------------------------------
|
||
|
|
-- Event
|
||
|
|
------------------------------------------------------
|
||
|
|
-- Fired when an element is added
|
||
|
|
event "OnElementAdd"
|
||
|
|
|
||
|
|
-- Fired when an element is removed
|
||
|
|
event "OnElementRemove"
|
||
|
|
|
||
|
|
------------------------------------------------------
|
||
|
|
-- Method
|
||
|
|
------------------------------------------------------
|
||
|
|
function GetIterator(self, key)
|
||
|
|
return nextItem, self, tonumber(key) or 0
|
||
|
|
end
|
||
|
|
|
||
|
|
__NoCombat__()
|
||
|
|
RefreshLayout = secureUpdatePanelSize
|
||
|
|
|
||
|
|
function ForceRefreshLayout(self)
|
||
|
|
if not InCombatLockdown() then
|
||
|
|
_ManagerFrame:SetFrameRef("SecurePanel", self)
|
||
|
|
_ManagerFrame:Execute(_ForceUpdatePanel)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
------------------------------------------------------
|
||
|
|
-- Property
|
||
|
|
------------------------------------------------------
|
||
|
|
--- The Element Pool
|
||
|
|
property "ElementPool" { type = Recycle, default = function(self) return self.ElementType and Recycle(self.ElementType, self.ElementPrefix .. "%d", self) end }
|
||
|
|
|
||
|
|
-- The element's type
|
||
|
|
property "ElementType" { type = ClassType }
|
||
|
|
|
||
|
|
-- The prefix for the element's name
|
||
|
|
property "ElementPrefix" { type = String, default = "Element" }
|
||
|
|
|
||
|
|
-- The Element accessor, used like obj.Elements[i].
|
||
|
|
__Indexer__(NaturalNumber)
|
||
|
|
property "Elements" {
|
||
|
|
get = function(self, index)
|
||
|
|
if index >= 1 and index <= self.ColumnCount * self.RowCount then
|
||
|
|
if self[index] then return self[index] end
|
||
|
|
|
||
|
|
if self.ElementPool and not InCombatLockdown() then
|
||
|
|
generate(self, index)
|
||
|
|
|
||
|
|
return self[index]
|
||
|
|
else
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
|
||
|
|
-- The columns's count
|
||
|
|
property "ColumnCount" { type = PositiveNumber, default = 5, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The row's count
|
||
|
|
property "RowCount" { type = PositiveNumber, default = 5, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The elements's max count
|
||
|
|
property "MaxCount" { Get = function(self) return self.ColumnCount * self.RowCount end }
|
||
|
|
|
||
|
|
-- The element's width
|
||
|
|
property "ElementWidth" { type = PositiveNumber, default = 16, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The element's height
|
||
|
|
property "ElementHeight" { type = PositiveNumber, default = 16, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The element's count
|
||
|
|
property "Count" {
|
||
|
|
get = function(self)
|
||
|
|
return self:GetAttribute("IFSecurePanel_Count") or 0
|
||
|
|
end,
|
||
|
|
set = function(self, cnt)
|
||
|
|
if cnt > self.RowCount * self.ColumnCount then
|
||
|
|
error("Count can't be more than "..self.RowCount * self.ColumnCount, 2)
|
||
|
|
end
|
||
|
|
|
||
|
|
if cnt > self.Count then
|
||
|
|
if self.ElementPool then
|
||
|
|
NoCombat(generate, self, cnt)
|
||
|
|
else
|
||
|
|
error("ElementType not set.", 2)
|
||
|
|
end
|
||
|
|
elseif cnt < self.Count then
|
||
|
|
NoCombat(reduce, self, cnt)
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
type = NaturalNumber,
|
||
|
|
}
|
||
|
|
|
||
|
|
-- The orientation for elements
|
||
|
|
property "Orientation" { type = Orientation, default = Orientation.HORIZONTAL, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether the elements start from left to right
|
||
|
|
property "LeftToRight" { type = Boolean, default = true, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether the elements start from top to bottom
|
||
|
|
property "TopToBottom" { type = Boolean, default = true, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The horizontal spacing
|
||
|
|
property "HSpacing" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The vertical spacing
|
||
|
|
property "VSpacing" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether the elementPanel is autosize
|
||
|
|
property "AutoSize" { type = Boolean, default = true, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The top margin
|
||
|
|
property "MarginTop" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The bottom margin
|
||
|
|
property "MarginBottom" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The left margin
|
||
|
|
property "MarginLeft" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- The right margin
|
||
|
|
property "MarginRight" { type = Number, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether the elementPanel should keep it's max size
|
||
|
|
property "KeepMaxSize" { type = Boolean, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether adjust the elements position automatically
|
||
|
|
property "AutoPosition" { type = Boolean, default = true, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether keep the max size for columns
|
||
|
|
property "KeepColumnSize" { type = Boolean, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
-- Whether keep the max size for rows
|
||
|
|
property "KeepRowSize" { type = Boolean, handler = onPropertyChanged }
|
||
|
|
|
||
|
|
|
||
|
|
------------------------------------------------------
|
||
|
|
-- Constructor
|
||
|
|
------------------------------------------------------
|
||
|
|
function __ctor(self)
|
||
|
|
self.OnElementAdd = self.OnElementAdd + registerFrame
|
||
|
|
self.OnElementRemove = self.OnElementRemove + unregisterFrame
|
||
|
|
|
||
|
|
registerPanel(self)
|
||
|
|
end
|
||
|
|
end)
|