Nenue@54: -- Veneer Nenue@71: -- Base framework for making things draggable. Nenue@0: Nenue@84: Nenue@84: Nenue@84: Nenue@84: SLASH_VENEER1 = "/veneer" Nenue@84: SLASH_VENEER2 = "/vn" Nenue@84: Nenue@84: SlashCmdList.VENEER = function(cmd) Nenue@84: end Nenue@84: VeneerCore = { Nenue@84: Frames = {}, Nenue@84: ConfigLayers = {}, Nenue@84: FrameClusters = {}, Nenue@84: parserDepth = 0, Nenue@84: pendingCalls = {}, Nenue@84: } Nenue@84: VeneerHandlerMixin = { Nenue@84: Reanchor = nop Nenue@84: } Nenue@84: local print = DEVIAN_WORKSPACE and function(...) print('Veneer', ...) end or nop Nenue@80: local wipe = table.wipe Nenue@0: Nenue@59: local defaults = { Nenue@59: enableAll = true, Nenue@59: enableModule = { Nenue@59: BuffFrame = true, Nenue@59: }, Nenue@59: BuffFrame = { Nenue@59: width = 48, Nenue@59: height = 48, Nenue@59: } Nenue@59: } Nenue@84: Nenue@71: local configMode Nenue@79: local anonID = 0 Nenue@79: local tostring = tostring Nenue@79: local IsFrameHandle = IsFrameHandle Nenue@79: local GetAnonymousName = function(key) Nenue@79: if not key then Nenue@71: anonID = anonID + 1 Nenue@79: key = anonID Nenue@71: end Nenue@79: return 'VN' .. key Nenue@71: end Nenue@79: local GetTableName = function(table) Nenue@79: return (IsFrameHandle(table) and table:GetName()) or tostring(table) Nenue@79: end Nenue@79: Nenue@72: local anchor_coefficients = { Nenue@72: ['TOP'] = function(x, y) return x, y end, Nenue@72: ['BOTTOM'] = function(x, y) return x,y end, Nenue@72: ['LEFT'] = function(x, y) return x,y end, Nenue@72: ['RIGHT'] = function(x,y) return x,y end, Nenue@72: } Nenue@72: Nenue@84: function VeneerCore:print(...) Nenue@84: local txt = '|cFFFFFF00Veneer|r:' Nenue@84: for i = 1, select('#', ...) do Nenue@84: txt = txt .. ' '.. tostring(select(i, ...)) Nenue@84: end Nenue@84: Nenue@84: DEFAULT_CHAT_FRAME:AddMessage(txt) Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:OnLoad() Nenue@84: print('|cFFFFFF00Veneer!|r') Nenue@84: self:RegisterEvent('ADDON_LOADED') Nenue@84: self:RegisterEvent('PLAYER_LOGIN') Nenue@84: Nenue@84: self.DEVIAN_PNAME = 'Veneer' Nenue@84: self:RegisterForDrag('LeftButton') Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:OnEvent(event, ...) Nenue@84: if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then Nenue@84: if IsLoggedIn() and not self.intialized then Nenue@84: self.intialized = true Nenue@84: self:Setup() Nenue@84: end Nenue@84: end Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:OnDragStart() Nenue@84: self:StartMoving() Nenue@84: end Nenue@84: Nenue@84: Nenue@84: function VeneerCore:OnDragStop() Nenue@84: self:StopMovingOrSizing() Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:Setup () Nenue@84: if (not VeneerData) or (not VeneerData.version) then Nenue@84: VeneerData = defaults Nenue@84: end Nenue@84: self.data = VeneerData Nenue@84: Nenue@84: Nenue@84: self:ExecuteOnClusters(nil, 'Setup') Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:AddHandler(handler, ...) Nenue@84: print('*** Adding handler:', handler.moduleName or handler:GetName()) Nenue@84: local clusterTable = self.FrameClusters Nenue@84: for i = 1, select('#', ...) do Nenue@84: local anchor = select(i, ...) Nenue@84: clusterTable[anchor] = clusterTable[anchor] or {} Nenue@84: clusterTable = clusterTable[anchor] Nenue@84: print(' cluster layer', i, anchor) Nenue@84: end Nenue@84: for k,v in pairs(VeneerHandlerMixin) do Nenue@84: if not handler[k] then Nenue@84: handler[k] = v Nenue@84: end Nenue@84: end Nenue@84: tinsert(clusterTable, handler) Nenue@84: handler:Reanchor() Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:ExecuteOnClusters(layer, method) Nenue@84: self.parserDepth = self.parserDepth + 1 Nenue@84: layer = layer or self.FrameClusters Nenue@84: if not layer then Nenue@84: if self.parserDepth >= 1 then Nenue@84: tinsert(self.pendingCalls, method) Nenue@84: print('delaying walk for', method) Nenue@84: return Nenue@84: end Nenue@84: print('|cFF00FFFFVeneer|r:'..method..'('..tostring(layer)..')') Nenue@84: else Nenue@84: print(' L'..self.parserDepth) Nenue@84: end Nenue@84: for anchor, cluster in pairs(layer) do Nenue@84: for index, frame in ipairs(cluster) do Nenue@84: print(' '..anchor..'.'..index..' = '..frame:GetName()) Nenue@84: if frame[method] then Nenue@84: print(' '..frame:GetName()..':'..method..'(...)') Nenue@84: frame[method](frame) Nenue@84: end Nenue@84: end Nenue@84: if cluster.FrameClusters then Nenue@84: self:ExecuteOnClusters(cluster.FrameClusters, method) Nenue@84: end Nenue@84: end Nenue@84: self.parserDepth = self.parserDepth - 1 Nenue@84: Nenue@84: if (self.parserDepth == 0) and (#self.pendingCalls >= 1) then Nenue@84: local delayedMethod = tremove(self.pendingCalls, 1) Nenue@84: print('starting delayed walk for', delayedMethod) Nenue@84: self:ExecuteOnClusters(nil, delayedMethod) Nenue@84: end Nenue@84: end Nenue@84: Nenue@84: function VeneerCore:Update() Nenue@84: self:ExecuteOnClusters(nil, 'Update') Nenue@84: end Nenue@84: Nenue@72: local VeneerButton_OnDragStart = function(self) Nenue@72: self.startingLeft = self:GetLeft() Nenue@72: self.startingBottom = self:GetBottom() Nenue@72: self.anchors = self.anchors or {} Nenue@72: table.wipe(self.anchors) Nenue@72: Nenue@72: local frame = self:GetParent() Nenue@72: local n = frame:GetNumPoints() Nenue@72: for i = 1, n do Nenue@72: local anchor, parent, relative, x, y = frame:GetPoint(i) Nenue@72: self.anchors[i] = { Nenue@72: anchor = anchor, Nenue@72: parent = parent, Nenue@72: relative = relative, Nenue@72: x = x, Nenue@72: y = y Nenue@72: } Nenue@72: end Nenue@72: Nenue@72: print(self:GetName(), 'start moving', self.startingLeft, self.startingBottom) Nenue@72: self:StartMoving() Nenue@72: end Nenue@72: Nenue@72: local VeneerButton_OnDragStop = function(self) Nenue@72: self:StopMovingOrSizing() Nenue@72: if self.OnDragStop then Nenue@72: self.OnDragStop(self) Nenue@72: else Nenue@72: local frame = self:GetParent() Nenue@72: local dx = self:GetLeft() - self.startingLeft Nenue@72: local dy = self:GetBottom() - self.startingBottom Nenue@72: Nenue@72: frame:ClearAllPoints() Nenue@72: for i, point in ipairs(self.anchors) do Nenue@72: frame:SetPoint(point.anchor, point.parent, point.relative, point.x + dx, point.y + dy) Nenue@72: print('adjusting anchor', point.anchor, point.parent, point.relative, point.x + dx, point.y + dy) Nenue@72: end Nenue@72: end Nenue@72: end Nenue@72: Nenue@72: local Veneer_FixMovers = function() Nenue@72: for frame, veneer in pairs(veneers) do Nenue@72: if veneer:IsMoving() then Nenue@72: VeneerButton_OnDragStop(veneer) Nenue@72: end Nenue@72: end Nenue@72: end Nenue@71: Nenue@71: local VeneerButton_Update = function(self) Nenue@71: if configMode then Nenue@72: self:SetScript('OnDragStart', VeneerButton_OnDragStart) Nenue@72: self:SetScript('OnDragStop', VeneerButton_OnDragStop) Nenue@72: self:SetMovable(true) Nenue@72: self:EnableMouse(true) Nenue@71: self:RegisterForDrag('LeftButton') Nenue@71: Nenue@71: self.bg:SetColorTexture(0,1,0,0.5) Nenue@72: for i, region in ipairs(self.configLayers) do Nenue@72: region:Show() Nenue@72: end Nenue@72: self:Show() Nenue@71: else Nenue@71: Nenue@71: self:SetScript('OnDragStart', self.StartMoving) Nenue@71: self:SetScript('OnDragStop', self.StopMovingOrSizing) Nenue@71: self:SetMovable(false) Nenue@71: self:EnableMouse(false) Nenue@71: Nenue@71: self.bg:SetColorTexture(0,1,0,0) Nenue@72: for i, region in ipairs(self.configLayers) do Nenue@72: region:Hide() Nenue@72: end Nenue@72: if self.isHidden then Nenue@72: self:Hide() Nenue@72: end Nenue@72: Nenue@71: end Nenue@71: end Nenue@71: Nenue@71: local ToggleVeneerConfig = function() Nenue@71: if configMode then Nenue@71: configMode = false Nenue@84: Veneer:print('Config mode off.') Nenue@71: else Nenue@71: configMode = true Nenue@84: Veneer:print('Config mode on.') Nenue@71: end Nenue@71: Nenue@71: for frame, veneer in pairs(veneers) do Nenue@71: VeneerButton_Update(veneer) Nenue@71: end Nenue@71: end Nenue@71: Nenue@71: local VeneerButton_OnShow = function(self) Nenue@71: VeneerButton_Update(self) Nenue@71: end Nenue@71: Nenue@84: function VeneerCore:Acquire (frame, template) Nenue@71: if not frame then Nenue@71: print('|cFFFF4400Unable to acquire frame...|r') Nenue@71: return Nenue@71: end Nenue@84: local veneer = self.Frames[frame] Nenue@84: if not veneer then Nenue@84: local name = type(frame) == 'table' and GetTableName(frame) or GetAnonymousName() Nenue@84: veneer = CreateFrame('Frame', name, frame, template or 'VeneerTemplate') Nenue@84: print('+veneer', name) Nenue@71: Nenue@84: veneer:SetAllPoints(frame) Nenue@84: veneer:SetParent(frame) Nenue@84: veneer.label:SetText(name) Nenue@84: veneer.bg:SetColorTexture(0,0,0,0) Nenue@84: veneer:Hide() Nenue@84: veneer:EnableMouse(false) Nenue@84: Nenue@84: veneer:SetScript('OnShow', VeneerButton_OnShow) Nenue@84: Nenue@84: -- find current X/Y Nenue@84: veneer.currentLeft = frame:GetLeft() Nenue@84: veneer.currentTop = frame:GetTop() Nenue@84: self.Frames[frame] = veneer Nenue@71: end Nenue@71: Nenue@84: return veneer Nenue@71: end Nenue@0: Nenue@80: local mixin_probe = { Nenue@80: 'ArtifactFrame', Nenue@80: 'ArtifactFrameUnderlay', Nenue@80: } Nenue@80: Nenue@80: