# HG changeset patch
# User Flick
# Date 1302649591 25200
# Node ID 920d17851a936226ba80de7b77f3904fa6490166
# Parent b2b105747466f7dce63ee9296c59ef1d37f8802e# Parent 586447595262a1ab6733e8daba091052c1b8536c
Merge 1.1 beta 4 to stable
diff -r b2b105747466 -r 920d17851a93 .hgtags
--- a/.hgtags Thu Nov 18 13:11:08 2010 -0800
+++ b/.hgtags Tue Apr 12 16:06:31 2011 -0700
@@ -1,3 +1,4 @@
2c05008464e5cf809251d40c8f88ad87fa3ac554 1.1 Beta 1
9945a783d8b29e6e81eb8d42823d56dc84759d15 1.1 Beta 2
3e451836ce6dfa758794c27a4b3a2a1f12595e83 1.1 Beta 3
+47818b3938c912c19018419cb5738d4013107167 1.1 beta 4
diff -r b2b105747466 -r 920d17851a93 .pkgmeta
--- a/.pkgmeta Thu Nov 18 13:11:08 2010 -0800
+++ b/.pkgmeta Tue Apr 12 16:06:31 2011 -0700
@@ -4,10 +4,6 @@
- libdatabroker-1-1
- buttonfacade
-optional-dependencies:
- - ace3
- - libkeybound-1-0
-
externals:
lib/AceAddon-3.0:
url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
diff -r b2b105747466 -r 920d17851a93 ActionButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ActionButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,806 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local IsUsableAction = IsUsableAction
+local IsEquippedAction = IsEquippedAction
+local IsConsumableAction = IsConsumableAction
+local IsStackableAction = IsStackableAction
+local GetActionText = GetActionText
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local IsCurrentAction = IsCurrentAction
+local IsAutoRepeatAction = IsAutoRepeatAction
+local IsUsableAction = IsUsableAction
+local IsAttackAction = IsAttackAction
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local GetActionCooldown = GetActionCooldown
+local GetActionTexture = GetActionTexture
+local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
+local TOOLTIP_UPDATE_TIME = TOOLTIP_UPDATE_TIME
+local IsActionInRange = IsActionInRange
+local InCombatLockdown = InCombatLockdown
+local HasAction = HasAction
+
+--
+-- Secure snippets
+-- These are run within the context of the bar's sandbox, as the
+-- buttons themselves do not have their own sandbox.
+--
+local _onstate_mc = -- function(self, stateid, newstate)
+[[
+ local oldMcVehicleState = mcVehicleState
+ mcVehicleState = newstate
+ control:ChildUpdate()
+ if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then
+ control:ChildUpdate("vehicle")
+ end
+]]
+
+local _childupdate = -- function(self, snippetid, message)
+[[
+ local action = nil
+ if (doVehicle and mcVehicleState == "vehicle") or
+ (doMindControl and mcVehicleState == "mc") then
+ local idx = self:GetAttribute("bar-idx")
+ local maxN = (doVehicle and mcVehicleState == "vehicle") and 7 or 12
+ if idx and idx <= maxN then
+ action = 120 + idx
+ else
+ action = 0
+ end
+ elseif state and settings[state] and settings[state].page then
+ action = self:GetAttribute("action-"..settings[state].page)
+ end
+ if action == nil then
+ action = self:GetAttribute("default-action")
+ end
+
+ self:SetAttribute("action",action)
+
+ if not self:GetAttribute("showgrid") then
+ local tempShow = self:GetAttribute("showgrid-temp")
+ local evtShow = self:GetAttribute("showgrid-event")
+ if tempShow then tempShow = (tempShow > 0) end
+ if evtShow then evtShow = (evtShow > 0) end
+
+ if tempShow or evtShow or HasAction(action) then
+ self:Show()
+ else
+ self:Hide()
+ end
+ end
+]]
+
+local _childupdate_vehicleExit = -- function(self, snippetid, message)
+[[
+ local show = (mcVehicleState == "vehicle")
+ if show and doVehicle then
+ self:SetAttribute("type","macro")
+ self:Show()
+ else
+ self:SetAttribute("type","action")
+ end
+ control:CallMethod("ShowVehicleExit",show)
+]]
+
+local _childupdate_showgrid = -- function(self, snippetid, message)
+[[
+ showgrid_event = message
+ self:SetAttribute("showgrid-event",message)
+ if not self:GetAttribute("showgrid") then
+ local count = message + (self:GetAttribute("showgrid-temp") or 0)
+ if count <= 0 then
+ local action = self:GetAttribute("action")
+ -- note that HasAction is not updated on the target of a drag until after ACTIONBAR_HIDEGRID
+ -- so, we set a flag for this button in pre-click/receive-drag and check for it here
+ if HasAction(action) or self:GetAttribute("showgrid-clicked") then
+ if not self:IsShown() then
+ self:Show()
+ end
+ self:SetAttribute("showgrid-clicked",false)
+ else
+ if self:IsShown() then
+ self:Hide()
+ end
+ end
+ else
+ self:Show()
+ end
+ end
+]]
+
+local _onDragStart = -- function(self, button, kind, value, ...)
+[[
+ if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
+ return kind, value, ...
+ else
+ return "action", self:GetAttribute("action")
+ end
+]]
+
+local _onReceiveDrag = -- function(self, button, kind, value, ...)
+[[
+ if kind ~= "spell" and kind ~= "item" and kind ~= "macro" and kind ~= "flyout" then
+ return kind, value, ...
+ else
+ if showgrid_event and showgrid_event > 0 then
+ self:SetAttribute("showgrid-clicked",true)
+ end
+ return "action", self:GetAttribute("action")
+ end
+]]
+
+local _onClick = -- function(self, button, down)
+[[
+ if showgrid_event and showgrid_event > 0 then
+ self:SetAttribute("showgrid-clicked",true)
+ end
+ return button
+]]
+
+--
+-- private
+--
+local eventList = {
+ "PLAYER_ENTERING_WORLD",
+ "ACTIONBAR_PAGE_CHANGED",
+ "ACTIONBAR_SLOT_CHANGED",
+ "UPDATE_BINDINGS",
+ "ACTIONBAR_UPDATE_STATE",
+ "ACTIONBAR_UPDATE_USABLE",
+ "ACTIONBAR_UPDATE_COOLDOWN",
+ "UNIT_INVENTORY_CHANGED",
+ "LEARNED_SPELL_IN_TAB",
+ "UPDATE_INVENTORY_ALERTS",
+ "PLAYER_TARGET_CHANGED",
+ "TRADE_SKILL_SHOW",
+ "TRADE_SKILL_CLOSE",
+ "PLAYER_ENTER_COMBAT",
+ "PLAYER_LEAVE_COMBAT",
+ "START_AUTOREPEAT_SPELL",
+ "STOP_AUTOREPEAT_SPELL",
+ "UNIT_ENTERED_VEHICLE",
+ "UNIT_EXITED_VEHICLE",
+ "COMPANION_UPDATE",
+}
+
+--
+-- Action Button class
+--
+local buttonTypeID = "Action"
+local Super = ReAction.Button
+local Action = setmetatable(
+ {
+ defaultBarConfig = {
+ type = buttonTypeID,
+ btnWidth = 36,
+ btnHeight = 36,
+ btnRows = 1,
+ btnColumns = 12,
+ spacing = 3,
+ buttons = { },
+ },
+
+ barType = L["Action Bar"],
+ buttonTypeID = buttonTypeID
+ },
+ { __index = Super } )
+
+ReAction.Button.Action = Action
+ReAction:RegisterBarType(Action, true)
+
+function Action:New( config, bar, idx, idHint )
+ local name = format("ReAction_%s_Action_%d",bar:GetName(),idx)
+
+ self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+ self.barConfig = bar:GetConfig()
+
+ local f = self:GetFrame()
+ local barFrame = bar:GetFrame()
+
+ self.rangeTimer = TOOLTIP_UPDATE_TIME
+
+ -- set up the base action ID
+ self:SetActionIDPool("action",120)
+ config.actionID = self:AcquireActionID(config.actionID, idHint)
+ self.nPages = 1
+
+ -- attribute setup
+ f:SetAttribute("type","action")
+ f:SetAttribute("checkselfcast", true)
+ f:SetAttribute("checkfocuscast", true)
+ f:SetAttribute("action", config.actionID)
+ f:SetAttribute("default-action", config.actionID)
+ f:SetAttribute("bar-idx",idx)
+ f:SetAttribute("showgrid-temp",0)
+ f:SetAttribute("showgrid-event",0)
+ f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty)
+
+ -- non secure scripts
+ f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+ f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+ f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+ f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+ f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
+ f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end)
+ f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
+ f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForDrag("LeftButton", "RightButton")
+ f:RegisterForClicks("AnyUp")
+ for _, evt in pairs(eventList) do
+ f:RegisterEvent(evt)
+ end
+
+ f.action = config.actionID -- need this to support silly ActionButton_UpdateFlyout. Should not taint anything anymore.
+
+ -- secure handlers
+ f:SetAttribute("_childupdate", _childupdate)
+ f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid)
+ barFrame:WrapScript(f, "OnDragStart", _onDragStart)
+ barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
+ barFrame:WrapScript(f, "OnClick", _onClick)
+
+ -- attach to skinner
+ bar:SkinButton(self)
+
+ -- initial display
+ if ReAction:GetConfigMode() then
+ self:ShowGridTemp(true)
+ end
+
+ self:Refresh()
+
+ return self
+end
+
+function Action:Destroy()
+ local f = self:GetFrame()
+ local c = self:GetConfig()
+
+ f:SetAttribute("_childupdate-vehicle",nil)
+ f:SetAttribute("action",c.actionID) -- so that Super.Destroy releases the right one
+
+ if c.pageactions and #c.pageactions > 1 then
+ for i = 2, #c.pageactions do
+ self:ReleaseActionID(c.pageactions[i])
+ self:ReleaseActionID(id)
+ end
+ end
+
+ Super.Destroy(self)
+end
+
+function Action:GetBarConfig()
+ -- this is the per-bar Action module config structure,
+ -- not the config structure of the bar itself
+ return self.barConfig
+end
+
+function Action:Refresh()
+ Super.Refresh(self)
+ self:RefreshPages()
+ self:InstallVehicle()
+ self:ShowGrid(not self:GetBarConfig().hideEmpty)
+ self:UpdateAction()
+end
+
+function Action:InstallVehicle()
+ local f = self:GetFrame()
+ if self.idx == 7 and self:GetBarConfig().vehicle then
+ if not self.vehicleInstalled then
+ self.vehicleInstalled = true
+ -- install vehicle-exit button on 7th button (only)
+ f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit)
+ f:SetAttribute("macrotext","/run VehicleExit()")
+ self:GetBar():GetFrame().ShowVehicleExit = function(bar,show)
+ self:ShowVehicleExit(show)
+ end
+ end
+ -- setscale blows away tex coords
+ self:UpdateIcon()
+ elseif self.vehicleInstalled then
+ self.vehicleInstalled = false
+ f:SetAttribute("_childupdate-vehicle",nil)
+ f:SetAttribute("macrotext",nil)
+ end
+end
+
+function Action:ShowGrid( show )
+ if not InCombatLockdown() then
+ self.frame:SetAttribute("showgrid", show)
+ self:UpdateShowGrid()
+ end
+end
+
+function Action:ShowGridTemp( show )
+ -- This function only modifies the show-grid when out
+ -- of combat, and is ignored by the secure handler. Use
+ -- it for configuration modes.
+ if not InCombatLockdown() then
+ local count = self.showGridTempCount or 0
+ if show then
+ count = count + 1
+ else
+ count = count - 1
+ end
+ if count < 0 then count = 0 end
+ self.showGridTempCount = count
+ self:GetFrame():SetAttribute("showgrid-temp",count)
+ self:UpdateShowGrid()
+ end
+end
+
+function Action:UpdateAll()
+ self:UpdateActionIDLabel(ReAction:GetConfigMode())
+ self:UpdateHotkey()
+ self:UpdateShowGrid()
+ self:UpdateIcon()
+ self:UpdateBorder()
+ self:UpdateMacroText()
+ self:UpdateCount()
+ self:UpdateTooltip()
+ self:UpdateCheckedState()
+ self:UpdateUsable()
+ self:UpdateCooldown()
+ self:UpdateFlash()
+end
+
+function Action:UpdateAction()
+ local action = self:GetActionID()
+ if action ~= self.actionID then
+ self.actionID = action
+ self:UpdateAll()
+ end
+end
+
+function Action:UpdateShowGrid()
+ if not InCombatLockdown() then
+ local f = self:GetFrame()
+ local count = (f:GetAttribute("showgrid-event") or 0) +
+ (self.showGridTempCount or 0) +
+ (f:GetAttribute("showgrid") and 1 or 0)
+
+ if count <= 0 and not HasAction(self.actionID) then
+ if f:IsShown() then
+ f:Hide()
+ end
+ elseif not f:IsShown() then
+ f:Show()
+ end
+ end
+end
+
+function Action:UpdateIcon()
+ local texture, tLeft, tRight, tTop, tBottom = self:GetIconTexture()
+ local icon = self.frames.icon
+ local hotkey = self.frames.hotkey
+ local f = self:GetFrame()
+
+ if self.vehicleExitMode then
+ texture = "Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up"
+ icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
+ icon:SetVertexColor(1,1,1)
+ else
+ icon:SetTexCoord(0,1,0,1)
+ end
+
+ if texture then
+ icon:SetTexture(texture)
+ if tLeft then
+ icon:SetTexCoord(tLeft,tRight,tTop,tBottom)
+ end
+ icon:Show()
+ self.rangeTimer = -1
+ f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+ else
+ icon:Hide()
+ self.frames.cooldown:Hide()
+ self.rangeTimer = nil
+ f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+ end
+end
+
+function Action:GetIconTexture()
+ return GetActionTexture(self.actionID)
+end
+
+function Action:UpdateBorder()
+ local action = self.actionID
+ if ReAction:GetKeybindMode() then
+ self:UpdateKeybindModeDisplay(true)
+ elseif IsEquippedAction(action) then
+ self.frames.border:SetVertexColor(0, 1.0, 0, 0.35)
+ self.frames.border:Show()
+ else
+ self.frames.border:Hide()
+ end
+end
+
+function Action:UpdateMacroText()
+ local action = self.actionID
+ if not IsConsumableAction(action) and not IsStackableAction(action) then
+ self.frames.name:SetText(GetActionText(action))
+ else
+ self.frames.name:SetText("")
+ end
+end
+
+function Action:UpdateCount()
+ local action = self.actionID
+ if IsConsumableAction(action) or IsStackableAction(action) then
+ self.frames.count:SetText(GetActionCount(action))
+ else
+ self.frames.count:SetText("")
+ end
+end
+
+function Action:UpdateTooltip()
+ local f = self:GetFrame()
+ if GameTooltip:GetOwner() == f then
+ self:SetTooltip()
+ end
+end
+
+function Action:SetTooltip()
+ local f = self:GetFrame()
+ if GetCVar("UberTooltips") == "1" then
+ GameTooltip_SetDefaultAnchor(GameTooltip, f)
+ else
+ GameTooltip:SetOwner(f,"ANCHOR_RIGHT")
+ end
+ GameTooltip:SetAction(self.actionID)
+end
+
+function Action:UpdateCheckedState()
+ local action = self.actionID
+ if IsCurrentAction(action) or IsAutoRepeatAction(action) then
+ self:GetFrame():SetChecked(1)
+ else
+ self:GetFrame():SetChecked(0)
+ end
+end
+
+function Action:UpdateUsable()
+ local isUsable, notEnoughMana = self:GetUsable()
+ local noRange = self:GetInRange()
+
+ isUsable = self.vehicleExitMode or (isUsable and not noRange)
+
+ if isUsable then
+ if self.usableStatus ~= "usable" then
+ self.frames.icon:SetVertexColor(1.0, 1.0, 1.0)
+ self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+ self.usableStatus = "usable"
+ end
+ elseif noRange then
+ if self.usableStatus ~= "norange" then
+ self.frames.icon:SetVertexColor(1.0,0.1,0.1)
+ self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+ self.usableStatus = "norange"
+ end
+ elseif notEnoughMana then
+ if self.usableStatus ~= "oom" then
+ self.frames.icon:SetVertexColor(0.5, 0.5, 1.0)
+ self.frames.normalTexture:SetVertexColor(0.5, 0.5, 1.0)
+ self.usableStatus = "oom"
+ end
+ else
+ if self.usableStatus ~= "unusable" then
+ self.frames.icon:SetVertexColor(0.4, 0.4, 0.4)
+ self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+ self.usableStatus = "unusable"
+ end
+ end
+end
+
+function Action:GetUsable()
+ return IsUsableAction(self.actionID)
+end
+
+function Action:GetInRange()
+ return IsActionInRange(self.actionID) == 0
+end
+
+function Action:UpdateCooldown()
+ CooldownFrame_SetTimer(self.frames.cooldown, self:GetCooldown())
+end
+
+function Action:GetCooldown()
+ return GetActionCooldown(self.actionID)
+end
+
+function Action:UpdateFlash()
+ local action = self.actionID
+ self:SetFlash( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) )
+end
+
+function Action:SetFlash(flash)
+ if self.flashing ~= flash then
+ self.flashing = flash
+ self.flashtime = 0
+ if not flash then
+ self.frames.flash:Hide()
+ end
+ self:UpdateCheckedState()
+ end
+end
+
+function Action:RunFlash(elapsed)
+ if self.flashing then
+ local flashtime = self.flashtime - elapsed
+ self.flashtime = flashtime
+ if flashtime <= 0 then
+ local overtime = -flashtime
+ if overtime >= ATTACK_BUTTON_FLASH_TIME then
+ overtime = 0
+ end
+ flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
+ local flash = self.frames.flash
+ if flash:IsShown() then
+ flash:Hide()
+ else
+ flash:Show()
+ end
+ end
+ end
+end
+
+function Action:RunRangeFinder(elapsed)
+ local rangeTimer = self.rangeTimer
+ if rangeTimer then
+ rangeTimer = rangeTimer - elapsed
+ self.rangeTimer = rangeTimer
+ if rangeTimer <= 0 then
+ self:UpdateUsable()
+ self.rangeTimer = TOOLTIP_UPDATE_TIME
+ end
+ end
+end
+
+function Action:GetActionID(page)
+ if page == nil then
+ -- get the effective ID
+ return self:GetFrame():GetAttribute("action")
+ else
+ if page == 1 then
+ return self.config.actionID
+ else
+ return self.config.pageactions and self.config.pageactions[page] or self.config.actionID
+ end
+ end
+end
+
+function Action:SetActionID( id, page )
+ id = tonumber(id)
+ page = tonumber(page)
+ if id == nil or id < 1 or id > 120 then
+ ReAction:UserError(L["Action ID range is 1-120"])
+ return
+ end
+ if page and page ~= 1 then
+ if not self.config.pageactions then
+ self.config.pageactions = { }
+ end
+ self:ReleaseActionID(self.config.pageactions[page])
+ self.config.pageactions[page] = id
+ self:AcquireActionID(self.config.pageactions[page])
+ self.frame:SetAttribute("action-page"..page,id)
+ else
+ self:ReleaseActionID(self.config.actionID)
+ self.config.actionID = id
+ self:AcquireActionID(self.config.actionID)
+ self.frame:SetAttribute("action",id)
+ self.frame:SetAttribute("default-action",id)
+ if self.config.pageactions then
+ self.config.pageactions[1] = id
+ self.frame:SetAttribute("action-page1",id)
+ end
+ end
+end
+
+function Action:RefreshPages( force )
+ local nPages = self:GetBarConfig().nPages
+ if nPages and (nPages ~= self.nPages or force) then
+ local f = self:GetFrame()
+ local c = self.config.pageactions
+ if nPages > 1 and not c then
+ c = { }
+ self.config.pageactions = c
+ end
+ for i = 1, nPages do
+ if i > 1 then
+ c[i] = self:AcquireActionID(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons())
+ else
+ c[i] = self.config.actionID -- page 1 is the same as the base actionID
+ end
+ f:SetAttribute("action-page"..i,c[i])
+ end
+ for i = nPages+1, #c do
+ self:ReleaseActionID(c[i])
+ c[i] = nil
+ f:SetAttribute("action-page"..i,nil)
+ end
+ self.nPages = nPages
+ end
+end
+
+function Action:SetupBar( bar )
+ Super.SetupBar(self,bar)
+
+ local f = bar:GetFrame()
+ local config = bar:GetConfig()
+ f:SetAttribute("mindcontrol",config.mindcontrol)
+ f:SetAttribute("vehicle",config.vehicle)
+ f:Execute(
+ [[
+ doMindControl = self:GetAttribute("mindcontrol")
+ doVehicle = self:GetAttribute("vehicle")
+ control:ChildUpdate()
+ ]])
+
+ f:SetAttribute("_onstate-mc", _onstate_mc)
+ RegisterStateDriver(f, "mc", "[vehicleui] vehicle; [bonusbar:5] mc; none")
+
+ f:SetAttribute("lockbuttons",config.lockButtons)
+ f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat)
+ f:Execute(
+ [[
+ lockButtons = self:GetAttribute("lockbuttons")
+ lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+ ]])
+end
+
+
+function Action:SetButtonLock( bar, lock, lockCombat )
+ local f = bar:GetFrame()
+ f:SetAttribute("lockbuttons",lock)
+ f:SetAttribute("lockbuttonscombat",lockCombat)
+ f:Execute(
+ [[
+ lockButtons = self:GetAttribute("lockbuttons")
+ lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+ ]])
+end
+
+
+function Action:ShowVehicleExit(show)
+ self.vehicleExitMode = show and self:GetBarConfig().vehicle
+ self:UpdateIcon()
+end
+
+function Action:OnEnter( )
+ self:SetTooltip()
+end
+
+function Action:OnLeave( )
+ GameTooltip:Hide()
+end
+
+function Action:OnAttributeChanged( attr, value )
+ if attr ~= "statehidden" then
+ self:UpdateAction()
+ end
+ local f = self:GetFrame()
+ f.action = f:GetAttribute("action") -- support ActionButton_UpdateFlyout
+end
+
+function Action:PostClick( )
+ self:UpdateCheckedState()
+end
+
+function Action:OnUpdate( elapsed )
+ self:RunFlash(elapsed)
+ self:RunRangeFinder(elapsed)
+end
+
+function Action:OnDragStart()
+ self:UpdateCheckedState()
+ self:UpdateFlash()
+end
+
+function Action:OnReceiveDrag()
+ self:UpdateCheckedState()
+ self:UpdateFlash()
+end
+
+function Action:OnEvent(event, ...)
+ if self[event] then
+ self[event](self, event, ...)
+ end
+end
+
+function Action:ACTIONBAR_SLOT_CHANGED(event, action)
+ if action == 0 or action == self.actionID then
+ self:UpdateAll()
+ end
+end
+
+function Action:PLAYER_ENTERING_WORLD()
+ self:UpdateAction()
+end
+
+function Action:ACTIONBAR_PAGE_CHANGED()
+ self:UpdateAction()
+end
+
+function Action:UPDATE_BONUS_ACTIONBAR()
+ self:UpdateAction()
+end
+
+function Action:UPDATE_BINDINGS()
+ self:UpdateHotkey()
+end
+
+function Action:PLAYER_TARGET_CHANGED()
+ self.rangeTimer = -1
+end
+
+function Action:ACTIONBAR_UPDATE_STATE()
+ self:UpdateCheckedState()
+end
+
+function Action:TRADE_SKILL_SHOW()
+ self:UpdateCheckedState()
+end
+Action.TRADE_SKILL_CLOSE = Action.TRADE_SKILL_CLOSE
+
+function Action:UNIT_ENTERED_VEHICLE(event,unit)
+ if unit == "player" then
+ self:UpdateCheckedState()
+ end
+end
+Action.UNIT_EXITED_VEHICLE = Action.UNIT_ENTERED_VEHICLE
+
+function Action:COMPANION_UPDATE(event,unit)
+ if unit == "mount" then
+ self:UpdateCheckedState()
+ end
+end
+
+function Action:ACTIONBAR_UPDATE_USABLE()
+ self:UpdateUsable()
+end
+
+function Action:ACTIONBAR_UPDATE_COOLDOWN()
+ self:UpdateCooldown()
+end
+
+function Action:PLAYER_ENTER_COMBAT()
+ if IsAttackAction(self.actionID) then
+ self:SetFlash(true)
+ end
+end
+
+function Action:PLAYER_LEAVE_COMBAT()
+ if IsAttackAction(self.actionID) then
+ self:SetFlash(false)
+ end
+end
+
+function Action:START_AUTOREPEAT_SPELL()
+ if IsAutoRepeatAction(self.actionID) then
+ self:SetFlash(true)
+ end
+end
+
+function Action:STOP_AUTOREPEAT_SPELL()
+ if not IsAttackAction(self.actionID) then
+ self:SetFlash(false)
+ end
+end
+
+function Action:UNIT_INVENTORY_CHANGED(unit)
+ if unit == "player" then
+ self:UpdateTooltip()
+ end
+end
+
+function Action:LEARNED_SPELL_IN_TAB()
+ self:UpdateTooltip()
+end
diff -r b2b105747466 -r 920d17851a93 BagButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BagButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,499 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local ContainerIDToInventoryID = ContainerIDToInventoryID
+local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
+local IsModifiedClick = IsModifiedClick
+local CursorHasItem = CursorHasItem
+local GetInventoryItemTexture = GetInventoryItemTexture
+local GetInventorySlotInfo = GetInventorySlotInfo
+local PickupBagFromSlot = PickupBagFromSlot
+local CursorCanGoInSlot = CursorCanGoInSlot
+
+-- class declarations
+local buttonTypeID = "Bag"
+local weak = { __mode = "k" }
+local Super = ReAction.Button
+local BagBase = setmetatable(
+ {
+ defaultBarConfig = {
+ type = buttonTypeID,
+ btnWidth = 30,
+ btnHeight = 30,
+ btnRows = 1,
+ btnColumns = 6,
+ spacing = 4,
+ buttons = { }
+ },
+
+ barType = L["Bag Bar"],
+ buttonTypeID = buttonTypeID,
+
+ allButtons = setmetatable( { }, weak )
+ },
+ { __index = Super } )
+
+local Bag = setmetatable( { }, { __index = BagBase } )
+local Backpack = setmetatable( { }, { __index = BagBase } )
+local Keyring = setmetatable( { }, { __index = BagBase } )
+
+ReAction.Button.Bag = BagBase
+ReAction:RegisterBarType(BagBase)
+
+--
+-- Bag Button base class
+--
+
+function BagBase:New( btnCfg, bar, idx, idHint )
+ local name = format("ReAction_%s_Bag_%d",bar:GetName(),idx)
+
+ -- use a variable private leaf implementation class
+ -- unlike traditional OO programming, we can initialize the leaf
+ -- class before initializing its parent
+ local class = Bag
+ if idx == 1 then
+ class = Backpack
+ elseif idx == 6 then
+ class = Keyring
+ end
+ self = class:New(name, btnCfg, bar, idx)
+
+ local f = self:GetFrame()
+ local config = self:GetConfig()
+
+ -- set up the bag ID pool
+ self:SetActionIDPool("bag",6)
+ config.bagID = self:AcquireActionID(config.bagID, idHint, true)
+
+ -- non secure scripts
+ f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+ f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+ f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+ f:SetScript("OnReceiveDrag", function(frame, ...) self:OnReceiveDrag(...) end)
+ f:SetScript("OnClick", function(frame, ...) self:OnClick(...) end)
+
+ -- secure handlers
+ -- (none)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForClicks("LeftButtonUp","RightButtonUp")
+ f:RegisterEvent("UPDATE_BINDINGS")
+
+ -- frame setup
+ f:SetID(self:GetBagID())
+
+ if not f.hotkey then
+ local h = f:CreateFontString(name.."HotKey","ARTWORK","NumberFontNormalSmallGray")
+ h:SetWidth(30)
+ h:SetHeight(10)
+ h:SetJustifyH("RIGHT")
+ h:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
+ h:Show()
+ f.hotkey = h
+ end
+
+ if not _G[name.."ItemAnim"] then
+ local anim = CreateFrame("Model",name.."ItemAnim",f,"ItemAnimTemplate")
+ anim:SetPoint("BOTTOMRIGHT",f,"BOTTOMRIGHT",-10,0)
+ anim:Hide()
+ end
+
+ if not f.border then
+ local b = f:CreateTexture(name.."Border","OVERLAY")
+ b:SetAllPoints()
+ b:SetWidth(f:GetWidth()*(62/36))
+ b:SetHeight(f:GetHeight()*(62/36))
+ b:SetTexture("Interface\\Buttons\UI-ActionButton-Border")
+ b:SetBlendMode("ADD")
+ b:Hide()
+ f.border = b
+ end
+
+ self.frames.count:SetDrawLayer("ARTWORK")
+
+ self.frames.hotkey = f.hotkey
+ self.frames.border = _G[name.."Border"]
+ self.frames.icon = _G[name.."IconTexture"]
+ self.frames.anim = _G[name.."ItemAnim"]
+
+ -- initial display
+ if ReAction:GetConfigMode() then
+ self:GetFrame():Show()
+ end
+
+ self:Refresh()
+
+ BagBase.allButtons[self] = true
+
+ return self
+end
+
+function BagBase:Destroy()
+ BagBase.allButtons[self] = nil
+ Super.Destroy(self)
+end
+
+
+function BagBase:GetActionID()
+ return self.config.bagID
+end
+
+function BagBase:GetBagID()
+ return self:GetActionID() - 1
+end
+
+function BagBase:Refresh()
+ Super.Refresh(self)
+ self:UpdateHotkey()
+ self:Update()
+end
+
+function BagBase:Update()
+ self:UpdateChecked()
+end
+
+function BagBase:UpdateChecked(force)
+ if force == nil then
+ for i=1, NUM_CONTAINER_FRAMES do
+ local c = _G["ContainerFrame"..i]
+ if c:GetID() == self:GetBagID() and c:IsShown() then
+ self:GetFrame():SetChecked(1)
+ return
+ end
+ end
+ self:GetFrame():SetChecked(0)
+ end
+ self:GetFrame():SetChecked(force)
+end
+
+function BagBase:OnEvent(evt, ...)
+ if self[evt] then
+ self[evt](self, ...)
+ end
+end
+
+function BagBase:OnEnter()
+ self:SetTooltip()
+end
+
+function BagBase:OnLeave()
+ GameTooltip:Hide()
+end
+
+function BagBase:UPDATE_BINDINGS()
+ self:UpdateHotkey()
+end
+
+function BagBase:IterateAllButtons()
+ return pairs(self.allButtons)
+end
+
+
+--
+-- Bag Button class
+--
+function Bag:New(name, cfg, bar, idx)
+ self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+ local f = self:GetFrame()
+
+ f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
+
+ f:RegisterEvent("CURSOR_UPDATE")
+ f:RegisterEvent("BAG_UPDATE")
+ f:RegisterEvent("BAG_CLOSED")
+ f:SetScript("OnDragStart", function(frame, ...) self:OnDragStart(...) end)
+ f:RegisterForDrag("LeftButton")
+
+ -- attach to skinner
+ bar:SkinButton(self,
+ {
+ Icon = _G[name.."IconTexture"]
+ }
+ )
+
+ return self
+end
+
+function Bag:GetInventorySlot()
+ return ContainerIDToInventoryID(self:GetBagID())
+end
+
+function Bag:GetInventorySlotName()
+ return "Bag"..(self:GetBagID()-1).."Slot"
+end
+
+function Bag:SetTooltip()
+ GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
+ if not GameTooltip:SetInventoryItem("player", self:GetInventorySlot()) then
+ GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
+ end
+end
+
+function Bag:Update()
+ local texture = GetInventoryItemTexture("player", self:GetInventorySlot())
+ if texture then
+ self.frames.icon:SetTexture(texture)
+ self.frames.icon:Show()
+ self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+ else
+ local _, bgTex = GetInventorySlotInfo(self:GetInventorySlotName())
+ self.frames.icon:SetTexture(bgTex)
+ self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+ end
+ self:UpdateChecked()
+end
+
+function Bag:OnClick()
+ if IsModifiedClick("OPENALLBAGS") then
+ OpenAllBags()
+ else
+ if not PutItemInBag(self:GetInventorySlot()) then
+ ToggleBag(self:GetBagID())
+ end
+ end
+ self:UpdateChecked()
+end
+
+function Bag:OnReceiveDrag()
+ if CursorHasItem() then
+ PutItemInBag(self:GetInventorySlot())
+ end
+end
+
+function Bag:OnDragStart()
+ PickupBagFromSlot(self:GetInventorySlot())
+ self:Update()
+end
+
+function Bag:BAG_UPDATE(bag)
+ if bag == self:GetBagID() then
+ self:Update()
+ end
+end
+
+function Bag:CURSOR_UPDATE()
+ if CursorCanGoInSlot(self:GetInventorySlot()) then
+ self:GetFrame():LockHighlight()
+ else
+ self:GetFrame():UnlockHighlight()
+ end
+end
+
+function Bag:BAG_CLOSED(bag)
+ if bag == self:GetBagID() then
+ self:Update()
+ end
+end
+
+
+--
+-- Backpack Button class
+--
+function Backpack:New(name, cfg, bar, idx)
+ self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+ local f = self:GetFrame()
+ local icon = _G[name.."IconTexture"]
+ icon:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
+ icon:Show()
+ f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
+ f:RegisterEvent("PLAYER_ENTERING_WORLD");
+ f:RegisterEvent("CVAR_UPDATE");
+ f:SetScript("OnShow", function(frame, ...) self:OnShow(...) end)
+
+ -- attach to skinner
+ bar:SkinButton(self,
+ {
+ Icon = _G[name.."IconTexture"]
+ }
+ )
+
+ return self
+end
+
+function Backpack:Update()
+ self:UpdateFreeSlots()
+ self:UpdateChecked()
+end
+
+function Backpack:UpdateFreeSlots()
+ if GetCVar("displayFreeBagSlots") == "1" then
+ local total = 0
+ for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
+ local free, family = GetContainerNumFreeSlots(i)
+ if family == 0 then
+ total = total + free
+ end
+ end
+
+ self.freeSlots = total
+ self.frames.count:SetText(format("(%s)", self.freeSlots))
+ self.frames.count:Show()
+ elseif self.frames.count:IsShown() then
+ self.frames.count:Hide()
+ end
+end
+
+function Backpack:SetTooltip()
+ GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
+ GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)
+ GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (self.freeSlots or 0)))
+ GameTooltip:Show();
+end
+
+function Backpack:OnShow()
+ self:UpdateFreeSlots()
+end
+
+function Backpack:OnClick()
+ if IsModifiedClick("OPENALLBAGS") then
+ OpenAllBags()
+ else
+ if not PutItemInBackpack() then
+ ToggleBackpack()
+ end
+ end
+ self:UpdateChecked()
+end
+
+function Backpack:OnReceiveDrag()
+ if CursorHasItem() then
+ PutItemInBackpack()
+ end
+end
+
+function Backpack:PLAYER_ENTERING_WORLD()
+ self:CVAR_UPDATE("DISPLAY_FREE_BAG_SLOTS", GetCVar("displayFreeBagSlots"))
+end
+
+function Backpack:CVAR_UPDATE( cvar, value )
+ if cvar == "DISPLAY_FREE_BAG_SLOTS" then
+ if value == "1" then
+ self:GetFrame():RegisterEvent("BAG_UPDATE")
+ else
+ self:GetFrame():UnregisterEvent("BAG_UPDATE")
+ end
+ self:UpdateFreeSlots()
+ end
+end
+
+function Backpack:BAG_UPDATE(bag)
+ if bag >= BACKPACK_CONTAINER and bag <= NUM_BAG_SLOTS then
+ self:UpdateFreeSlots()
+ end
+end
+
+
+--
+-- Keyring Button class
+--
+function Keyring:New(name, cfg, bar, idx)
+ self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+ local f = self:GetFrame()
+
+ f:SetWidth(18)
+ f:SetHeight(39)
+
+ local tex = f:GetNormalTexture()
+ tex:ClearAllPoints()
+ tex:SetAllPoints()
+
+ f:SetNormalTexture("Interface\\Buttons\\UI-Button-KeyRing")
+ f:SetHighlightTexture("Interface\\Buttons\\UI-Button-KeyRing-Highlight")
+ f:SetPushedTexture("Interface\\Buttons\\UI-Button-KeyRing-Down")
+ f:GetNormalTexture():SetTexCoord(0,0.5625,0,0.609375)
+ f:GetHighlightTexture():SetTexCoord(0,0.5625,0,0.609375)
+ f:GetPushedTexture():SetTexCoord(0,0.5625,0,0.609375)
+
+ if not HasKey() then
+ f:Hide()
+ end
+
+ -- DO NOT attach to skinner
+
+ return self
+end
+
+function Keyring:GetBagID()
+ return KEYRING_CONTAINER
+end
+
+function Keyring:Refresh()
+ local f = self:GetFrame()
+ self.bar:PlaceButton( self, f:GetHeight(), f:GetHeight() ) -- use height x height since it's an odd size
+ self:UpdateHotkey()
+ self:Update()
+end
+
+function Keyring:SetTooltip()
+ GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT");
+ GameTooltip:SetText(KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
+ GameTooltip:AddLine();
+end
+
+function Keyring:OnReceiveDrag()
+ if CursorHasItem() then
+ PutKeyInKeyRing()
+ end
+end
+
+function Keyring:OnClick()
+ if CursorHasItem() then
+ PutKeyInKeyRing()
+ else
+ ToggleKeyRing()
+ end
+ self:UpdateChecked()
+end
+
+function Keyring:ShowGridTemp(show)
+ if not HasKey() then
+ if show then
+ self:GetFrame():Show()
+ else
+ self:GetFrame():Hide()
+ end
+ end
+end
+
+
+
+-- hook some functions to propagate to our bag buttons
+hooksecurefunc("Disable_BagButtons",
+ function()
+ for b in BagBase:IterateAllButtons() do
+ local f = b:GetFrame()
+ f:Disable()
+ SetDesaturation(b.frames.icon,1)
+ end
+ end)
+
+hooksecurefunc("Enable_BagButtons",
+ function()
+ for b in BagBase:IterateAllButtons() do
+ local f = b:GetFrame()
+ f:Enable()
+ SetDesaturation(b.frames.icon,nil)
+ end
+ end)
+
+hooksecurefunc("ContainerFrame_OnHide",
+ function()
+ for b in BagBase:IterateAllButtons() do
+ b:Update()
+ end
+ end)
+
+hooksecurefunc("ContainerFrame_OnShow",
+ function()
+ for b in BagBase:IterateAllButtons() do
+ b:Update()
+ end
+ end)
diff -r b2b105747466 -r 920d17851a93 Bar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Bar.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,854 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local LKB = ReAction.LKB
+local _G = _G
+local CreateFrame = CreateFrame
+local floor = math.floor
+local fmod = math.fmod
+local format = string.format
+local tfetch = addonTable.tfetch
+local tbuild = addonTable.tbuild
+local fieldsort = addonTable.fieldsort
+
+local LSG = LibStub("ReAction-LibShowActionGrid-1.0")
+
+---- Secure snippets ----
+local _reaction_init =
+[[
+ anchorKeys = newtable("point","relPoint","x","y")
+
+ state = nil
+ set_state = nil
+ state_override = nil
+ unit_exists = nil
+
+ showAll = false
+ hidden = false
+
+ defaultAlpha = 1.0
+ defaultScale = 1.0
+ defaultAnchor = newtable()
+
+ activeStates = newtable()
+ settings = newtable()
+ extensions = newtable()
+]]
+
+local _reaction_refresh =
+[[
+ local oldState = state
+ state = state_override or set_state or state
+
+ local hide = nil
+ if state then
+ local settings = settings[state]
+ if settings then
+ -- show/hide
+ hide = settings.hide
+ -- re-anchor
+ local old_anchor = activeStates.anchor
+ activeStates.anchor = settings.anchorEnable and state
+ if old_anchor ~= activeStates.anchor or not set_state then
+ if activeStates.anchor then
+ if settings.anchorPoint then
+ self:ClearAllPoints()
+ local f = self:GetAttribute("frameref-anchor-"..state)
+ if f then
+ self:SetPoint(settings.anchorPoint, f, settings.anchorRelPoint, settings.anchorX, settings.anchorY)
+ end
+ end
+ elseif defaultAnchor.point then
+ self:ClearAllPoints()
+ self:SetPoint(defaultAnchor.point, defaultAnchor.frame,
+ defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
+ end
+ end
+ -- re-scale
+ local old_scale = activeStates.scale
+ activeStates.scale = settings.enableScale and state
+ if old_scale ~= activeStates.scale or not set_state then
+ self:SetScale(activeStates.scale and settings.scale or defaultScale)
+ end
+ -- alpha
+ local old_alpha = activeStates.alpha
+ activeStates.alpha = settings.enableAlpha and state
+ if old_alpha ~= activeStates.alpha or not set_state then
+ self:SetAlpha(activeStates.alpha and settings.alpha or defaultAlpha)
+ end
+ end
+ end
+
+ -- hide if state or unit_exists says to
+ hide = not showAll and (hide or unithide)
+ if hide ~= hidden then
+ hidden = hide
+ if hide then
+ self:Hide()
+ else
+ self:Show()
+ end
+ end
+
+ for _, attr in pairs(extensions) do
+ control:RunAttribute(attr)
+ end
+
+ control:ChildUpdate()
+
+ if showAll then
+ control:CallMethod("UpdateHiddenLabel", state and settings[state] and settings[state].hide)
+ end
+
+ if oldState ~= state then
+ control:CallMethod("StateRefresh", state)
+ end
+]]
+
+local _onstate_reaction = -- function( self, stateid, newstate )
+[[
+ set_state = newstate
+]] .. _reaction_refresh
+
+local _onstate_showgrid = -- function( self, stateid, newstate )
+[[
+ control:ChildUpdate(stateid,newstate)
+ control:CallMethod("UpdateShowGrid")
+]]
+
+local _onstate_unitexists = -- function( self, stateid, newstate )
+[[
+ unithide = not newstate or newstate == "hide"
+]] .. _reaction_refresh
+
+local _onclick = -- function( self, button, down )
+[[
+ if state_override == button then
+ state_override = nil -- toggle
+ else
+ state_override = button
+ end
+]] .. _reaction_refresh
+
+-- For reference
+-- the option field names must match the field names of the options table, below
+local stateProperties = {
+ hide = true,
+ --keybindState = true, TODO: broken
+ anchorEnable = true,
+ anchorFrame = true,
+ anchorPoint = true,
+ anchorRelPoint = true,
+ anchorX = true,
+ anchorY = true,
+ enableScale = true,
+ scale = true,
+ enableAlpha = true,
+ alpha = true,
+}
+
+
+
+---- Bar class ----
+local Bar = { }
+local frameList = { }
+
+ReAction.Bar = Bar -- export to ReAction
+
+function Bar:New( name, config, buttonClass )
+ if type(config) ~= "table" then
+ error("ReAction.Bar: config table required")
+ end
+
+ -- create new self
+ self = setmetatable(
+ {
+ config = config,
+ name = name,
+ buttons = { },
+ buttonClass = buttonClass,
+ width = config.width or 480,
+ height = config.height or 40,
+ },
+ {__index = self} )
+
+ -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
+ -- not mouse-clickable by the user.
+ local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
+ name = name and "ReAction-"..name
+ local f = name and frameList[name]
+ if not f then
+ f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
+ if name then
+ frameList[name] = f
+ end
+ end
+ f:SetFrameStrata("MEDIUM")
+ f:SetWidth(self.width)
+ f:SetHeight(self.height)
+ f:SetAlpha(config.alpha or 1.0)
+ f:Show()
+ f:EnableMouse(false)
+ f:SetClampedToScreen(true)
+ LSG:AddFrame(f)
+
+ -- secure handlers
+ f:Execute(_reaction_init)
+ f:SetAttribute("_onstate-reaction", _onstate_reaction)
+ f:SetAttribute("_onstate-showgrid", _onstate_showgrid)
+ f:SetAttribute("_onstate-unitexists", _onstate_unitexists)
+ f:SetAttribute("_onclick", _onclick)
+
+ -- secure handler CallMethod()s
+ f.UpdateShowGrid = function() self:UpdateShowGrid() end
+ f.StateRefresh = function() self:RefreshControls() end
+ f.UpdateHiddenLabel = function(f,hidden) self:SetLabelSubtext(hidden and L["Hidden"]) end
+
+ -- Override the default frame accessor to provide strict read-only access
+ function self:GetFrame()
+ return f
+ end
+
+ self:ApplyAnchor()
+ self:SetConfigMode(ReAction:GetConfigMode())
+ self:SetKeybindMode(ReAction:GetKeybindMode())
+
+ if ReAction.LBF then
+ local g = ReAction.LBF:Group(L["ReAction"], self.name)
+ self.config.ButtonFacade = self.config.ButtonFacade or {
+ skinID = "Blizzard",
+ backdrop = true,
+ gloss = 0,
+ colors = {},
+ }
+ local c = self.config.ButtonFacade
+ g:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
+ self.LBFGroup = g
+ end
+
+ ReAction.RegisterCallback(self, "OnConfigModeChanged")
+
+ buttonClass:SetupBar(self)
+ self:ApplyStates()
+
+ return self
+end
+
+function Bar:Destroy()
+ local f = self:GetFrame()
+ self:CleanupStates()
+ for idx, b in self:IterateButtons() do
+ b:Destroy()
+ end
+ f:UnregisterAllEvents()
+ self:ShowControls(false)
+ ReAction.UnregisterAllCallbacks(self)
+ LKB.UnregisterAllCallbacks(self)
+ if self.LBFGroup then
+ self.LBFGroup:Delete(true)
+ end
+ LSG:RemoveFrame(f)
+ f:SetParent(UIParent)
+ f:ClearAllPoints()
+ f:Hide()
+end
+
+--
+-- Events
+--
+
+function Bar:OnConfigModeChanged(event, mode)
+ self:SetConfigMode(mode)
+end
+
+--
+-- Accessors
+--
+
+function Bar:GetName()
+ return self.name
+end
+
+-- only ReAction:RenameBar() should call this function. Calling from any other
+-- context will desync the bar list in the ReAction class.
+function Bar:SetName(name)
+ if self.LBFGroup then
+ -- LBF doesn't offer a method of renaming a group, so delete and remake the group.
+ local c = self.config.ButtonFacade
+ local g = ReAction.LBF:Group(L["ReAction"], name)
+ for idx, b in self:IterateButtons() do
+ self.LBFGroup:RemoveButton(b:GetFrame(), true)
+ g:AddButton(b:GetFrame())
+ end
+ self.LBFGroup:Delete(true)
+ self.LBFGroup = g
+ self.LBFGroup:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
+ end
+ self.name = name
+ if self.overlay then
+ self.overlay:SetLabel(self.name)
+ end
+end
+
+function Bar:GetFrame()
+ -- this method is included for documentation purposes. It is overridden
+ -- for each object in the :New() method.
+ error("Invalid Bar object: used without initialization")
+end
+
+function Bar:GetButton(idx)
+ return self.buttons[idx]
+end
+
+function Bar:GetButtonClass()
+ return self.buttonClass
+end
+
+function Bar:GetConfig()
+ return self.config
+end
+
+function Bar:GetAnchor()
+ local c = self.config
+ return (c.point or "CENTER"),
+ (c.anchor or self:GetFrame():GetParent():GetName()),
+ (c.relpoint or c.point or "CENTER"),
+ (c.x or 0),
+ (c.y or 0)
+end
+
+function Bar:SetAnchor(point, frame, relativePoint, x, y)
+ local c = self.config
+ c.point = point or c.point
+ c.anchor = frame or c.anchor
+ c.relpoint = relativePoint or c.relpoint
+ c.x = x or c.x
+ c.y = y or c.y
+ self:ApplyAnchor()
+end
+
+function Bar:GetSize()
+ local f = self:GetFrame()
+ return f:GetWidth(), f:GetHeight()
+end
+
+function Bar:SetSize(w,h)
+ local f = self:GetFrame()
+ self.config.width = w
+ self.config.height = h
+ f:SetWidth(w)
+ f:SetHeight(h)
+end
+
+function Bar:GetButtonSize()
+ local w = self.config.btnWidth or 32
+ local h = self.config.btnHeight or 32
+ -- TODO: get from modules?
+ return w,h
+end
+
+function Bar:SetButtonSize(w,h)
+ if w > 0 and h > 0 then
+ self.config.btnWidth = w
+ self.config.btnHeight = h
+ end
+end
+
+function Bar:GetNumButtons()
+ local r,c = self:GetButtonGrid()
+ return r*c
+end
+
+function Bar:GetButtonGrid()
+ local cfg = self.config
+ local r = cfg.btnRows or 1
+ local c = cfg.btnColumns or 1
+ local s = cfg.spacing or 4
+ return r,c,s
+end
+
+function Bar:SetButtonGrid(r,c,s)
+ if r > 0 and c > 0 and s > 0 then
+ local cfg = self.config
+ cfg.btnRows = r
+ cfg.btnColumns = c
+ cfg.spacing = s
+ end
+ self.buttonClass:SetupBar(self)
+end
+
+function Bar:GetAlpha()
+ return self.config.alpha or 1.0
+end
+
+function Bar:SetAlpha(value)
+ self.config.alpha = value
+ self:GetFrame():SetAlpha(value or 1.0)
+ self:UpdateDefaultStateAlpha()
+end
+
+function Bar:IterateButtons()
+ -- iterator returns idx, button, but does NOT iterate in index order
+ return pairs(self.buttons)
+end
+
+--
+-- Methods
+--
+
+function Bar:SetConfigMode(mode)
+ self:SetSecureData("showAll",mode)
+ self:ShowControls(mode)
+ for idx, b in self:IterateButtons() do
+ b:ShowGridTemp(mode)
+ b:UpdateActionIDLabel(mode)
+ end
+end
+
+function Bar:SetKeybindMode(mode)
+ self:SetSecureData("showAll",mode)
+ for idx, b in self:IterateButtons() do
+ b:SetKeybindMode(mode)
+ end
+end
+
+function Bar:ApplyAnchor()
+ local f = self:GetFrame()
+ local c = self.config
+ local p = c.point
+
+ f:SetWidth(c.width)
+ f:SetHeight(c.height)
+ f:ClearAllPoints()
+
+ if p then
+ local a = f:GetParent()
+ if c.anchor then
+ local bar = ReAction:GetBar(c.anchor)
+ if bar then
+ a = bar:GetFrame()
+ else
+ a = _G[c.anchor]
+ end
+ end
+ local fr = a or f:GetParent()
+ f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
+ else
+ f:SetPoint("CENTER")
+ end
+
+ self:UpdateDefaultStateAnchor()
+end
+
+function Bar:ClipNButtons( n )
+ local cfg = self.config
+ local r = cfg.btnRows or 1
+ local c = cfg.btnColumns or 1
+
+ cfg.btnRows = ceil(n/c)
+ cfg.btnColumns = min(n,c)
+end
+
+function Bar:AddButton(idx, button)
+ local f = self:GetFrame()
+
+ self.buttons[idx] = button
+
+ -- Store a properly wrapped reference to the child frame as an attribute
+ -- (accessible via "frameref-btn#")
+ f:SetFrameRef(format("btn%d",idx), button:GetFrame())
+
+ -- button constructors are responsible for calling SkinButton
+end
+
+function Bar:RemoveButton(button)
+ local idx = button:GetIndex()
+ if idx then
+ self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
+ self.buttons[idx] = nil
+ end
+ if self.LBFGroup then
+ self.LBFGroup:RemoveButton(button:GetFrame(),true)
+ end
+end
+
+function Bar:PlaceButton(button, baseW, baseH)
+ local idx = button:GetIndex()
+ if idx then
+ local r, c, s = self:GetButtonGrid()
+ local bh, bw = self:GetButtonSize()
+ local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
+ local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
+ local scale = bw/baseW
+ local b = button:GetFrame()
+
+ b:ClearAllPoints()
+ b:SetPoint("TOPLEFT",x/scale,y/scale)
+ b:SetScale(scale)
+ end
+end
+
+function Bar:SkinButton( button, data )
+ if self.LBFGroup then
+ self.LBFGroup:AddButton(button:GetFrame(), data)
+ end
+end
+
+function Bar:UpdateShowGrid()
+ for idx, button in self:IterateButtons() do
+ button:UpdateShowGrid()
+ end
+end
+
+function Bar:ShowControls(show)
+ if show then
+ if not self.overlay then
+ self.overlay = Bar.Overlay:New(self) -- see Overlay.lua
+ end
+ self.overlay:Show()
+ self:RefreshSecureState()
+ elseif self.overlay then
+ self.overlay:Hide()
+ end
+end
+
+function Bar:RefreshControls()
+ if self.overlay and self.overlay:IsShown() then
+ self.overlay:RefreshControls()
+ end
+end
+
+function Bar:SetLabelSubtext(text)
+ if self.overlay then
+ self.overlay:SetLabelSubtext(text)
+ end
+end
+
+--
+-- Secure state functions
+--
+
+function Bar:GetSecureState()
+ local env = GetManagedEnvironment(self:GetFrame())
+ return env and env.state
+end
+
+function Bar:GetStateProperty(state, propname)
+ return tfetch(self:GetConfig(), "states", state, propname)
+end
+
+function Bar:SetStateProperty(state, propname, value)
+ local s = tbuild(self:GetConfig(), "states", state)
+ s[propname] = value
+ self:SetSecureStateData(state, propname, value)
+end
+
+function Bar:ApplyStates()
+ local states = tfetch(self:GetConfig(), "states")
+ if states then
+ self:SetStateDriver(states)
+ end
+end
+
+function Bar:CleanupStates()
+ self:SetStateDriver(nil)
+end
+
+function Bar:RefreshSecureState()
+ self:GetFrame():Execute(_reaction_refresh)
+end
+
+-- usage: SetSecureData(globalname, [tblkey1, tblkey2, ...], value)
+function Bar:SetSecureData( ... )
+ local n = select('#',...)
+ if n < 2 then
+ error("ReAction.Bar:SetSecureData() requires at least 2 arguments")
+ end
+ local f = self:GetFrame()
+ f:SetAttribute("data-depth",n-1)
+ f:SetAttribute("data-value",select(n,...))
+ for i = 1, n-1 do
+ local key = select(i,...)
+ if key == nil then
+ error("ReAction.Bar:SetSecureData() - nil table key in argument list (#"..i..")")
+ end
+ f:SetAttribute("data-key-"..i, key)
+ end
+ f:Execute(
+ [[
+ local n = self:GetAttribute("data-depth")
+ if n > 0 then
+ local value = self:GetAttribute("data-value")
+ local t = _G
+ for i = 1, n do
+ local key = self:GetAttribute("data-key-"..i)
+ if not key then return end
+ if not t[key] then
+ t[key] = newtable()
+ end
+ if i == n then
+ t[key] = value
+ else
+ t = t[key]
+ end
+ end
+ end
+ ]])
+ self:RefreshSecureState()
+end
+
+function Bar:SetSecureStateData( state, key, value )
+ self:SetSecureData("settings",state,key,value)
+end
+
+-- sets a snippet to be run as an extension to _onstate-reaction
+function Bar:SetSecureStateExtension( id, snippet )
+ if id == nil then
+ error("ReAction.Bar:SetSecureStateExtension() requires an id")
+ end
+ local f = self:GetFrame()
+ f:SetAttribute("input-secure-ext-id",id)
+ f:SetAttribute("secure-ext-"..id,snippet)
+ f:Execute(
+ [[
+ local id = self:GetAttribute("input-secure-ext-id")
+ if id then
+ extensions[id] = self:GetAttribute("secure-ext-"..id) or nil
+ end
+ ]])
+ self:RefreshSecureState()
+end
+
+function Bar:SetFrameRef( name, refFrame )
+ if refFrame then
+ local _, explicit = refFrame:IsProtected()
+ if not explicit then
+ refFrame = nil
+ end
+ end
+ if refFrame then
+ self:GetFrame():SetFrameRef(name,refFrame)
+ else
+ self:GetFrame():SetAttribute("frameref-"..name,nil)
+ end
+end
+
+function Bar:SetStateDriver( states )
+ if states then
+ for state, props in pairs(states) do
+ self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
+ for propname, value in pairs(props) do
+ if propname == "anchorFrame" then
+ self:SetFrameRef("anchor-"..state, _G[value])
+ elseif propname == "rule" then
+ -- do nothing
+ else
+ self:SetSecureStateData(state, propname, value)
+ end
+ end
+ end
+ end
+ local rule = states and self:BuildStateRule(states)
+ if rule then
+ RegisterStateDriver(self:GetFrame(),"reaction",rule)
+ elseif self.statedriver then
+ UnregisterStateDriver(self:GetFrame(),"reaction")
+ end
+ self.statedriver = rule
+ self:BuildStateKeybinds(states)
+ self:RefreshSecureState()
+end
+
+-- pass unit=nil to set up the unit elsewhere, if you want something more complex
+function Bar:RegisterUnitWatch( unit, enable )
+ local f = self:GetFrame()
+ if unit then
+ f:SetAttribute("unit",unit)
+ end
+ if enable then
+ if not self.unitwatch then
+ RegisterUnitWatch(self:GetFrame(),true)
+ end
+ elseif self.unitwatch then
+ UnregisterUnitWatch(self:GetFrame())
+ end
+ self.unitwatch = enable
+ self:RefreshSecureState()
+end
+
+function Bar:SetStateKeybind( key, state )
+ local f = self:GetFrame()
+ local binds = self.statebinds
+ if not binds then
+ binds = { }
+ self.statebinds = binds
+ end
+
+ -- clear the old binding, if any
+ if binds[state] then
+ SetOverrideBinding(f, false, binds[state], nil)
+ end
+
+ if key then
+ SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
+ end
+ binds[state] = key
+end
+
+function Bar:GetStateKeybind( state )
+ if self.statebinds and state then
+ return self.statebinds[state]
+ end
+end
+
+function Bar:UpdateDefaultStateAnchor()
+ local point, frame, relPoint, x, y = self:GetAnchor()
+ local f = self:GetFrame()
+ f:SetAttribute("defaultAnchor-point",point)
+ f:SetAttribute("defaultAnchor-relPoint",relPoint)
+ f:SetAttribute("defaultAnchor-x",x)
+ f:SetAttribute("defaultAnchor-y",y)
+ self:SetFrameRef("defaultAnchor",_G[frame or "UIParent"])
+ f:Execute([[
+ for _, k in pairs(anchorKeys) do
+ defaultAnchor[k] = self:GetAttribute("defaultAnchor-"..k)
+ end
+ defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
+ ]])
+end
+
+function Bar:UpdateDefaultStateAlpha()
+ local f = self:GetFrame()
+ f:SetAttribute("defaultAlpha",self:GetAlpha())
+ f:Execute([[
+ defaultAlpha = self:GetAttribute("defaultAlpha")
+ ]])
+end
+
+---- secure state driver rules ----
+
+local playerClass = select(2, UnitClass("player"))
+local function ClassFilter(...)
+ for i = 1, select('#',...) do
+ if playerClass == select(i,...) then
+ return false
+ end
+ end
+ return true
+end
+
+local ruleformats = {
+ stealth = { format = "stealth", filter = ClassFilter("ROGUE","DRUID") },
+ nostealth = { format = "nostealth", filter = ClassFilter("ROGUE","DRUID") },
+ shadowdance = { format = "bonusbar:2", filter = ClassFilter("ROGUE") },
+ shadowform = { format = "form:1", filter = ClassFilter("PRIEST") },
+ noshadowform = { format = "noform", filter = ClassFilter("PRIEST") },
+ battle = { format = "stance:1", filter = ClassFilter("WARRIOR") },
+ defensive = { format = "stance:2", filter = ClassFilter("WARRIOR") },
+ berserker = { format = "stance:3", filter = ClassFilter("WARRIOR") },
+ caster = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
+ bear = { format = "form:1", filter = ClassFilter("DRUID") },
+ cat = { format = "form:3", filter = ClassFilter("DRUID") },
+ tree = { format = "form:5", filter = ClassFilter("DRUID") },
+ moonkin = { format = "form:5", filter = ClassFilter("DRUID") },
+ demon = { format = "form:2", filter = ClassFilter("WARLOCK") },
+ nodemon = { format = "noform", filter = ClassFilter("WARLOCK") },
+ pet = { format = "pet" },
+ nopet = { format = "nopet" },
+ harm = { format = "@target,harm" },
+ help = { format = "@target,help" },
+ notarget = { format = "@target,noexists" },
+ focusharm = { format = "@focus,harm" },
+ focushelp = { format = "@focus,help" },
+ nofocus = { format = "@focus,noexists" },
+ raid = { format = "group:raid" },
+ party = { format = "group:party" },
+ solo = { format = "nogroup" },
+ combat = { format = "combat" },
+ nocombat = { format = "nocombat" },
+ possess = { format = "@vehicle,noexists,bonusbar:5" },
+ vehicle = { format = "@vehicle,exists,bonusbar:5" },
+}
+
+function Bar.InitRuleFormats()
+ local forms = { }
+ for i = 1, GetNumShapeshiftForms() do
+ local _, name = GetShapeshiftFormInfo(i)
+ forms[name] = i;
+ end
+ -- use 9 if not found since 9 is never a valid stance/form
+ local defensive = forms[GetSpellInfo(71)] or 9
+ local berserker = forms[GetSpellInfo(2458)] or 9
+ local bear = forms[GetSpellInfo(5487)] or 9
+ local aquatic = forms[GetSpellInfo(1066)] or 9
+ local cat = forms[GetSpellInfo(768)] or 9
+ local travel = forms[GetSpellInfo(783)] or 9
+ local tree = forms[GetSpellInfo(33891)] or 9
+ local moonkin = forms[GetSpellInfo(24858)] or 9
+ local flight = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
+
+ ruleformats.defensive.format = "stance:"..defensive
+ ruleformats.berserker.format = "stance:"..berserker
+ ruleformats.caster.format = format("form:0/%d/%d/%d", aquatic, travel, flight)
+ ruleformats.bear.format = "form:"..bear
+ ruleformats.cat.format = "form:"..cat
+ ruleformats.tree.format = "form:"..tree
+ ruleformats.moonkin.format = "form:"..moonkin
+end
+
+function Bar:BuildStateRule(states)
+ -- states is a table :
+ -- states[statename].rule = {
+ -- order = #,
+ -- type = "default"/"custom"/"any"/"all",
+ -- values = { ... }, -- keys of ruleformats[]
+ -- custom = "...",
+ -- }
+ local rules = { }
+ local default
+
+ for idx, state in ipairs(fieldsort(states, "rule", "order")) do
+ local c = states[state].rule
+ local type = c.type
+ if type == "default" then
+ default = default or state
+ elseif type == "custom" then
+ if c.custom then
+ -- strip out all spaces from the custom rule
+ table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
+ end
+ elseif type == "any" or type == "all" then
+ if c.values then
+ local clauses = { }
+ for key, value in pairs(c.values) do
+ if ruleformats[key] and not ruleformats[key].filter then
+ table.insert(clauses, ruleformats[key].format)
+ end
+ end
+ if #clauses > 0 then
+ local sep = (type == "any") and "][" or ","
+ table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
+ end
+ end
+ end
+ end
+ -- make sure that the default, if any, is last
+ if default then
+ table.insert(rules, default)
+ end
+ return table.concat(rules,";")
+end
+
+function Bar:BuildStateKeybinds( states )
+ if states then
+ for name, state in pairs(states) do
+ local rule = tfetch(state, "rule")
+ if rule and rule.type == "keybind" then
+ self:SetStateKeybind(rule.keybind, name)
+ else
+ self:SetStateKeybind(nil, name) -- this clears an existing keybind
+ end
+ end
+ end
+end
+
diff -r b2b105747466 -r 920d17851a93 Button.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Button.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,359 @@
+--[[
+ ReAction Button base class
+--]]
+
+-- local imports
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local LKB = ReAction.LKB
+local _G = _G
+local CreateFrame = CreateFrame
+local GetBindingKey = GetBindingKey
+local format = string.format
+
+-- private
+local trash = CreateFrame("Frame")
+local frameList = { }
+local idPools = { }
+
+local function kb_onEnter( frame )
+ LKB:Set(frame)
+end
+
+-- Button class
+local buttonTypeID = "Button"
+local Button = {
+ defaultBarConfig = {
+ type = buttonTypeID,
+ btnWidth = 36,
+ btnHeight = 36,
+ btnRows = 1,
+ btnColumns = 12,
+ spacing = 3
+ },
+ barType = L["Button Bar"]
+}
+
+ReAction.Button = Button -- export to ReAction
+
+function Button:New( name, config, bar, idx, inherits, buttonType )
+ buttonType = buttonType or "CheckButton"
+
+ -- create new self
+ self = setmetatable(
+ {
+ bar = bar,
+ idx = idx,
+ config = config,
+ name = name,
+ },
+ { __index = self } )
+
+ -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
+ -- existing globals. Can't set to nil in the global because it's then tainted.
+ -- Caller is responsible for ensuring global uniqueness of names.
+ local f = name and frameList[name]
+ if f then
+ f:SetParent(bar:GetFrame())
+ else
+ f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
+ if name then
+ frameList[name] = f
+ end
+ end
+
+ self.frame = f
+
+ local frames = { }
+ self.frames = frames
+ frames.icon = _G[name.."Icon"]
+ frames.flash = _G[name.."Flash"]
+ frames.hotkey = _G[name.."HotKey"]
+ frames.count = _G[name.."Count"]
+ frames.name = _G[name.."Name"]
+ frames.border = _G[name.."Border"]
+ frames.cooldown = _G[name.."Cooldown"]
+ frames.normalTexture = _G[name.."NormalTexture"]
+
+ if config then
+ config.name = name
+ end
+
+ -- install LibKeyBound handlers onto frame
+ function f:GetActionName()
+ return format("%s:%s", bar:GetName(), idx)
+ end
+
+ local clickBinding = format("CLICK %s:LeftButton", name)
+ function f:GetHotkey()
+ return LKB:ToShortKey(GetBindingKey(clickBinding))
+ end
+
+ return self
+end
+
+function Button:Destroy()
+ local f = self:GetFrame()
+ f:UnregisterAllEvents()
+ self:ReleaseActionID(self:GetActionID())
+ if f then
+ f:Hide()
+ f:SetParent(trash)
+ f:ClearAllPoints()
+ end
+end
+
+function Button:GetBar()
+ return self.bar
+end
+
+function Button:GetFrame()
+ return self.frame
+end
+
+function Button:GetIndex()
+ return self.idx
+end
+
+function Button:GetName()
+ return self.name
+end
+
+function Button:GetDefaultBarConfig()
+ return self.defaultBarConfig
+end
+
+function Button:GetBarType()
+ return self.barType
+end
+
+function Button:GetButtonTypeID()
+ return self.buttonTypeID
+end
+
+function Button:GetConfig()
+ return self.config
+end
+
+function Button:GetActionID()
+ -- derived classes should override this
+ return nil
+end
+
+function Button:SetActionIDPool( poolID, maxID )
+ self.actionPoolID = poolID
+ self.actionMaxID = maxID
+end
+
+function Button:SetupBar( bar )
+ local config = bar:GetConfig()
+ if not config.buttons then
+ config.buttons = { }
+ end
+ local btnCfg = config.buttons
+
+ local r, c = bar:GetButtonGrid()
+ local n = r*c
+ local cfgN = n
+
+ local hint = nil
+ local i = 1
+ repeat
+ local b = bar:GetButton(i)
+ if b then
+ if i > n then
+ bar:RemoveButton(b)
+ b:Destroy()
+ if i > cfgN then
+ btnCfg[i] = nil
+ end
+ else
+ b:Refresh()
+ hint = b:GetActionID()
+ end
+ elseif i <= n then
+ local cfg = btnCfg[i] or { }
+ local success, r = pcall(self.New, self, cfg, bar, i, hint) -- note call semantics for derived class constructors
+ if success and r then
+ b = r
+ bar:AddButton(i,b)
+ btnCfg[i] = cfg
+ b:Refresh()
+ hint = b:GetActionID()
+ else
+ n = i - 1
+ if not success then
+ bar:ClipNButtons(n)
+ cfgN = n
+ geterrorhandler()(r)
+ end
+ end
+ end
+ i = i + 1
+ until b == nil
+end
+
+function Button:AcquireActionID( id, hint, unique )
+ local poolID = self.actionPoolID
+ local maxID = self.actionMaxID
+ if not poolID or not maxID then
+ error("AcquireActionID: must setup pool first with SetActionIDPool")
+ end
+ local pool = idPools[poolID]
+ if not pool then
+ pool = { nWraps = 0, useCount = { } }
+ for i = 1, maxID do
+ pool.useCount[i] = 0
+ end
+ idPools[poolID] = pool
+ end
+ local useCount = pool.useCount
+ if id == nil then
+ repeat
+ local nWraps = pool.nWraps or 0
+ if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then
+ id = hint
+ else
+ local start = hint or 1
+ for i = start, maxID do
+ if useCount[i] == nil or useCount[i] == nWraps then
+ id = i
+ break
+ end
+ end
+ if not id then
+ for i = 1, start do
+ if useCount[i] == nil or useCount[i] == nWraps then
+ id = i
+ break
+ end
+ end
+ end
+ end
+ if id == nil then
+ if unique then
+ return nil
+ end
+ pool.nWraps = nWraps + 1
+ end
+ until id ~= nil
+ end
+ useCount[id] = (useCount[id] or 0) + 1
+ return id
+end
+
+function Button:ReleaseActionID( id )
+ local poolID = self.actionPoolID
+ if not poolID then
+ error("ReleaseActionID: must setup pool first with SetActionIDPool")
+ end
+ local pool = idPools[poolID]
+ if pool and id and pool.useCount[id] then
+ pool.useCount[id] = pool.useCount[id] - 1
+ pool.nWraps = min(pool.useCount[id], pool.nWraps)
+ end
+end
+
+function Button:Refresh()
+ local f = self:GetFrame()
+ self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
+end
+
+function Button:SetKeybindMode( mode )
+ local f = self.frame
+ if mode then
+ self.oldOnEnter = f:GetScript("OnEnter")
+ f:SetScript("OnEnter", kb_onEnter)
+ elseif self.oldOnEnter then
+ f:SetScript("OnEnter", self.oldOnEnter)
+ self.oldOnEnter = nil
+ end
+ self:ShowGridTemp(mode)
+ self:UpdateKeybindModeDisplay( mode )
+end
+
+function Button:UpdateKeybindModeDisplay( mode )
+ local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
+ if border then
+ if mode then
+ border:SetVertexColor(LKB:GetColorKeyBoundMode())
+ border:Show()
+ else
+ border:Hide()
+ end
+ end
+end
+
+function Button:UpdateHotkey( hotkey )
+ hotkey = hotkey or self.frames.hotkey
+ if not hotkey then
+ hotkey = _G[self:GetName().."HotKey"]
+ self.frames.hotkey = hotkey
+ end
+ if hotkey then
+ local txt = self.frame:GetHotkey()
+ hotkey:SetText( txt )
+ if txt == nil or txt == "" then
+ hotkey:Hide()
+ else
+ hotkey:Show()
+ end
+ end
+end
+
+function Button:GetActionIDLabel( create )
+ local f = self:GetFrame()
+ if not f.actionIDLabel and create then
+ local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+ label:SetAllPoints()
+ label:SetJustifyH("CENTER")
+ label:SetShadowColor(0,0,0,1)
+ label:SetShadowOffset(2,-2)
+ f.actionIDLabel = label -- store the label with the frame for recycling
+ end
+ return f.actionIDLabel
+end
+
+function Button:UpdateActionIDLabel( show )
+ local label = self:GetActionIDLabel( show )
+ if label then
+ if show then
+ local id = self:GetActionID()
+ if id then
+ label:SetText(tostring(id))
+ label:Show()
+ return
+ end
+ end
+ label:Hide()
+ end
+end
+
+function Button:SetNormalVertexColor( r, g, b, a )
+ if ReAction.LBF then
+ ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
+ else
+ self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
+ end
+end
+
+function Button:GetNormalVertexColor()
+ if ReAction.LBF then
+ return ReAction.LBF:GetNormalVertexColor(self:GetFrame())
+ else
+ return self:GetFrame():GetNormalTexture():GetVertexColor()
+ end
+end
+
+function Button:UpdateShowGrid()
+ -- does nothing by default
+end
+
+function Button:ShowGridTemp(show)
+ -- does nothing by default
+end
+
+function Button:ShowGrid(show)
+ -- does nothing by default
+end
diff -r b2b105747466 -r 920d17851a93 Editor.lua
--- a/Editor.lua Thu Nov 18 13:11:08 2010 -0800
+++ b/Editor.lua Tue Apr 12 16:06:31 2011 -0700
@@ -3,12 +3,17 @@
local L = ReAction.L
local _G = _G
local wipe = wipe
+local format = string.format
+local InCombatLockdown = InCombatLockdown
+local tfetch = addonTable.tfetch
+local tbuild = addonTable.tbuild
local AceConfigReg = LibStub("AceConfigRegistry-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local pointTable = {
+ NONE = " ",
CENTER = L["Center"],
LEFT = L["Left"],
RIGHT = L["Right"],
@@ -20,7 +25,9 @@
BOTTOMRIGHT = L["Bottom Right"],
}
-local Editor = { }
+local Editor = {
+ buttonHandlers = { }
+}
function Editor:New()
-- create new self
@@ -90,12 +97,12 @@
name = L["Button Type"],
get = function() return self.tmp.barType or ReAction:GetDefaultBarType() or "" end,
set = function(info, val)
- local c = ReAction:GetBarTypeConfig(val)
+ local c = ReAction:GetDefaultBarConfig(val)
self.tmp.barType = val
- self.tmp.barSize = c.defaultButtonSize or self.tmp.barSize
- self.tmp.barRows = c.defaultBarRows or self.tmp.barRows
- self.tmp.barCols = c.defaultBarCols or self.tmp.barCols
- self.tmp.barSpacing = c.defaultBarSpacing or self.tmp.barSpacing
+ self.tmp.barSize = c.btnWidth or self.tmp.barSize
+ self.tmp.barRows = c.btnRows or self.tmp.barRows
+ self.tmp.barCols = c.btnColumns or self.tmp.barCols
+ self.tmp.barSpacing = c.spacing or self.tmp.barSpacing
end,
values = "GetBarTypes",
order = 3,
@@ -173,12 +180,9 @@
ReAction.RegisterCallback(self,"OnCreateBar")
ReAction.RegisterCallback(self,"OnDestroyBar")
- ReAction.RegisterCallback(self,"OnEraseBar")
ReAction.RegisterCallback(self,"OnRenameBar")
- for name, bar in ReAction:IterateBars() do
- self:CreateBarTree(bar)
- end
+ self:RefreshBarOptions()
return self
end
@@ -203,160 +207,170 @@
AceConfigReg:NotifyChange(self.configID)
end
-function Editor:CreateBarTree(bar)
+function Editor:UpdateBarOptions(bar)
local name = bar:GetName()
- -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
- -- unique strings. So generate a unique key (it can be whatever) for the bar
+ local key = self.barOptMap[name]
local args = self.options.args
- local key
- local i = 1
- repeat
- key = ("bar%s"):format(i)
- i = i+1
- until args[key] == nil
- self.barOptMap[name] = key
- args[key] = {
- type = "group",
- name = name,
- childGroups = "tab",
- order = i+100,
- args = {
- general = {
- type = "group",
- name = L["General"],
- order = 1,
- args = {
- name = {
- type = "input",
- name = L["Rename Bar"],
- get = function() return bar:GetName() end,
- set = function(info, value) return ReAction:RenameBar(bar, value) end,
- order = 1,
- },
- delete = {
- type = "execute",
- name = L["Delete Bar"],
- desc = function() return bar:GetName() end,
- confirm = true,
- func = function() ReAction:EraseBar(bar) end,
- order = 2
- },
- anchor = {
- type = "group",
- name = L["Anchor"],
- inline = true,
- args = {
- frame = {
- type = "input",
- name = L["Frame"],
- desc = L["The frame that the bar is anchored to"],
- get = function() local _, f = bar:GetAnchor(); return f end,
- set = function(info, val) bar:SetAnchor(nil,val) end,
- validate = function(info, name)
- if name then
- local f = ReAction:GetBar(name)
- if f then
- return true
- else
- f = _G[name]
- if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then
- local _, explicit = f:IsProtected()
- return explicit
+
+ if not key then
+ -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
+ -- unique strings. So generate a unique key (it can be whatever) for the bar
+ local i = 1
+ repeat
+ key = ("bar%s"):format(i)
+ i = i+1
+ until args[key] == nil
+ self.barOptMap[name] = key
+
+ args[key] = {
+ type = "group",
+ name = name,
+ childGroups = "tab",
+ order = i+100,
+ args = {
+ general = {
+ type = "group",
+ name = L["General"],
+ order = 1,
+ args = {
+ name = {
+ type = "input",
+ name = L["Rename Bar"],
+ get = function() return bar:GetName() end,
+ set = function(info, value) return ReAction:RenameBar(bar, value) end,
+ order = 1,
+ },
+ delete = {
+ type = "execute",
+ name = L["Delete Bar"],
+ desc = function() return bar:GetName() end,
+ confirm = true,
+ func = function() ReAction:EraseBar(bar) end,
+ order = 2
+ },
+ anchor = {
+ type = "group",
+ name = L["Anchor"],
+ inline = true,
+ args = {
+ frame = {
+ type = "input",
+ name = L["Frame"],
+ desc = L["The frame that the bar is anchored to"],
+ get = function() local _, f = bar:GetAnchor(); return f end,
+ set = function(info, val) bar:SetAnchor(nil,val) end,
+ validate = function(info, name)
+ if name then
+ local f = ReAction:GetBar(name)
+ if f then
+ return true
+ else
+ f = _G[name]
+ if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then
+ local _, explicit = f:IsProtected()
+ return explicit
+ end
end
end
- end
- return false
- end,
- width = "double",
- order = 1
+ return false
+ end,
+ width = "double",
+ order = 1
+ },
+ point = {
+ type = "select",
+ name = L["Point"],
+ desc = L["Anchor point on the bar frame"],
+ style = "dropdown",
+ get = function() return bar:GetAnchor() end,
+ set = function(info, val) bar:SetAnchor(val) end,
+ values = pointTable,
+ order = 2,
+ },
+ relativePoint = {
+ type = "select",
+ name = L["Relative Point"],
+ desc = L["Anchor point on the target frame"],
+ style = "dropdown",
+ get = function() local p,f,r = bar:GetAnchor(); return r end,
+ set = function(info, val) bar:SetAnchor(nil,nil,val) end,
+ values = pointTable,
+ order = 3,
+ },
+ x = {
+ type = "input",
+ pattern = "\-?%d+",
+ name = L["X offset"],
+ get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end,
+ set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end,
+ order = 4
+ },
+ y = {
+ type = "input",
+ pattern = "\-?%d+",
+ name = L["Y offset"],
+ get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end,
+ set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end,
+ order = 5
+ },
},
- point = {
- type = "select",
- name = L["Point"],
- desc = L["Anchor point on the bar frame"],
- style = "dropdown",
- get = function() return bar:GetAnchor() end,
- set = function(info, val) bar:SetAnchor(val) end,
- values = pointTable,
- order = 2,
- },
- relativePoint = {
- type = "select",
- name = L["Relative Point"],
- desc = L["Anchor point on the target frame"],
- style = "dropdown",
- get = function() local p,f,r = bar:GetAnchor(); return r end,
- set = function(info, val) bar:SetAnchor(nil,nil,val) end,
- values = pointTable,
- order = 3,
- },
- x = {
- type = "input",
- pattern = "\-?%d+",
- name = L["X offset"],
- get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end,
- set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end,
- order = 4
- },
- y = {
- type = "input",
- pattern = "\-?%d+",
- name = L["Y offset"],
- get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end,
- set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end,
- order = 5
- },
+ order = 3
},
- order = 3
- },
- alpha = {
- type = "range",
- name = L["Transparency"],
- get = function() return bar:GetAlpha() end,
- set = function(info, val) bar:SetAlpha(val) end,
- min = 0,
- max = 1,
- isPercent = true,
- step = 0.01,
- bigStep = 0.05,
- order = 4,
+ alpha = {
+ type = "range",
+ name = L["Transparency"],
+ get = function() return bar:GetAlpha() end,
+ set = function(info, val) bar:SetAlpha(val) end,
+ min = 0,
+ max = 1,
+ isPercent = true,
+ step = 0.01,
+ bigStep = 0.05,
+ order = 4,
+ },
},
},
- },
+ buttonOpts = self:CreateButtonOptions(bar),
+ stateOpts = self:CreateStateOptions(bar)
+ }
}
- }
- self:RefreshBarOptions()
+ end
+
+end
+
+function Editor:CreateButtonOptions(bar)
+ local buttonClass = bar:GetButtonClass()
+ local classID = buttonClass:GetButtonTypeID()
+ local handler = self.buttonHandlers[classID]
+
+ if handler then
+ local h = handler:New(bar)
+ return h:GetOptions()
+ end
end
function Editor:RefreshBarOptions()
for name, key in pairs(self.barOptMap) do
- local bar = ReAction:GetBar(name)
- if bar and key and self.options.args[key] then
- self.options.args[key].plugins = self:GenerateBarOptionsTable(bar)
+ if not ReAction:GetBar(name) then
+ self.barOptMap[name] = nil
+ self.options.args[key] = nil
end
end
- AceConfigReg:NotifyChange(self.configID)
+ for name, bar in ReAction:IterateBars() do
+ self:UpdateBarOptions(bar)
+ end
+ self:Refresh()
end
function Editor:OnCreateBar(evt, bar)
- if not self.tmp.creating then
- -- a bit of hack to work around OnCreateBar event handler ordering
- self:CreateBarTree(bar)
- end
+ self:UpdateBarOptions(bar)
+ self:Refresh()
end
function Editor:OnDestroyBar(evt, bar, name)
local key = self.barOptMap[name]
if key then
- self.options.args[key] = nil
- end
- self:Refresh()
-end
-
-function Editor:OnEraseBar(evt, name)
- local key = self.barOptMap[name]
- self.barOptMap[name] = nil
- if key then
+ self.barOptMap[name] = nil
self.options.args[key] = nil
self:Refresh()
end
@@ -364,8 +378,8 @@
function Editor:OnRenameBar(evt, bar, oldname, newname)
local key = self.barOptMap[oldname]
- self.barOptMap[oldname], self.barOptMap[newname] = nil, key
if key then
+ self.barOptMap[oldname], self.barOptMap[newname] = nil, key
self.options.args[key].name = newname
self:Refresh()
end
@@ -379,42 +393,1300 @@
function Editor:CreateBar()
if self.tmp.barName and self.tmp.barName ~= "" then
- self.tmp.creating = true
local bar = ReAction:CreateBar(self.tmp.barName, self.tmp.barType or ReAction:GetDefaultBarType(), self.tmp.barRows, self.tmp.barCols, self.tmp.barSize, self.tmp.barSpacing)
if bar then
- self:CreateBarTree(bar)
AceConfigDialog:SelectGroup(self.configID, self.barOptMap[self.tmp.barName])
self.tmp.barName = nil
end
- self.tmp.creating = false
end
end
-function Editor:GenerateBarOptionsTable( bar )
- local opts = { }
- if not ReAction.barOptionGenerators then
- return
+-------------------------------
+---- Action button handler ----
+-------------------------------
+
+do
+ local ActionHandler = {
+ buttonClass = ReAction.Button.Action,
+ options = {
+ hideEmpty = {
+ name = L["Hide Empty Buttons"],
+ order = 1,
+ type = "toggle",
+ width = "double",
+ get = "GetHideEmpty",
+ set = "SetHideEmpty",
+ },
+ lockButtons = {
+ name = L["Lock Buttons"],
+ desc = L["Prevents picking up/dragging actions (use SHIFT to override this behavior)"],
+ order = 2,
+ type = "toggle",
+ get = "GetLockButtons",
+ set = "SetLockButtons",
+ },
+ lockOnlyCombat = {
+ name = L["Only in Combat"],
+ desc = L["Only lock the buttons when in combat"],
+ order = 3,
+ type = "toggle",
+ disabled = "LockButtonsCombatDisabled",
+ get = "GetLockButtonsCombat",
+ set = "SetLockButtonsCombat",
+ },
+ pages = {
+ name = L["# Pages"],
+ desc = L["Use the Dynamic State tab to specify page transitions"],
+ order = 4,
+ type = "range",
+ min = 1,
+ max = 10,
+ step = 1,
+ get = "GetNumPages",
+ set = "SetNumPages",
+ },
+ mindcontrol = {
+ name = L["Mind Control Support"],
+ desc = L["When possessing a target (e.g. via Mind Control), map the first 12 buttons of this bar to the possessed target's actions."],
+ order = 5,
+ type = "toggle",
+ width = "double",
+ set = "SetMindControl",
+ get = "GetMindControl",
+ },
+ vehicle = {
+ name = L["Vehicle Support"],
+ desc = L["When on a vehicle, map the first 6 buttons of this bar to the vehicle actions. The vehicle-exit button is mapped to the 7th button. Pitch controls are not supported."],
+ order = 6,
+ type = "toggle",
+ width = "double",
+ get = "GetVehicle",
+ set = "SetVehicle",
+ },
+ actions = {
+ name = L["Edit Action IDs"],
+ order = 7,
+ type = "group",
+ inline = true,
+ args = {
+ method = {
+ name = L["Assign"],
+ order = 1,
+ type = "select",
+ width = "double",
+ values = { [0] = L["Choose Method..."],
+ [1] = L["Individually"],
+ [2] = L["All at Once"], },
+ get = "GetActionEditMethod",
+ set = "SetActionEditMethod",
+ },
+ rowSelect = {
+ name = L["Row"],
+ desc = L["Rows are numbered top to bottom"],
+ order = 2,
+ type = "select",
+ width = "half",
+ hidden = "IsButtonSelectHidden",
+ values = "GetRowList",
+ get = "GetSelectedRow",
+ set = "SetSelectedRow",
+ },
+ colSelect = {
+ name = L["Col"],
+ desc = L["Columns are numbered left to right"],
+ order = 3,
+ type = "select",
+ width = "half",
+ hidden = "IsButtonSelectHidden",
+ values = "GetColumnList",
+ get = "GetSelectedColumn",
+ set = "SetSelectedColumn",
+ },
+ pageSelect = {
+ name = L["Page"],
+ order = 4,
+ type = "select",
+ width = "half",
+ hidden = "IsPageSelectHidden",
+ values = "GetPageList",
+ get = "GetSelectedPage",
+ set = "SetSelectedPage",
+ },
+ single = {
+ name = L["Action ID"],
+ usage = L["Specify ID 1-120"],
+ order = 5,
+ type = "input",
+ width = "half",
+ hidden = "IsButtonSelectHidden",
+ get = "GetActionID",
+ set = "SetActionID",
+ validate = "ValidateActionID",
+ },
+ multi = {
+ name = L["ID List"],
+ usage = L["Specify a comma-separated list of IDs for each button in the bar (in order). Separate multiple pages with semicolons (;)"],
+ order = 6,
+ type = "input",
+ multiline = true,
+ width = "double",
+ hidden = "IsMultiIDHidden",
+ get = "GetMultiID",
+ set = "SetMultiID",
+ validate = "ValidateMultiID",
+ },
+ },
+ },
+ }
+ }
+
+ Editor.buttonHandlers[ActionHandler.buttonClass:GetButtonTypeID()] = ActionHandler
+
+ local meta = { __index = ActionHandler }
+
+ function ActionHandler:New( bar )
+ return setmetatable(
+ {
+ bar = bar,
+ config = bar:GetConfig(),
+ },
+ meta)
end
- for module, func in pairs(ReAction.barOptionGenerators) do
- local success, r
- if type(func) == "string" then
- success, r = pcall(module[func], module, bar)
- else
- success, r = pcall(func, bar)
- end
- if success then
- if r then
- opts[module:GetName()] = { [module:GetName()] = r }
+ function ActionHandler:Refresh()
+ self.buttonClass:SetupBar(self.bar)
+ end
+
+ function ActionHandler:UpdateButtonLock()
+ self.buttonClass:SetButtonLock(self.bar, self.config.lockButtons, self.config.lockButtonsCombat)
+ end
+
+ function ActionHandler:GetLastButton()
+ return self.bar:GetButton(self.bar:GetNumButtons())
+ end
+
+ -- options handlers
+ function ActionHandler:GetOptions()
+ return {
+ type = "group",
+ name = L["Action Buttons"],
+ handler = self,
+ order = 2,
+ args = self.options
+ }
+ end
+
+ function ActionHandler:SetHideEmpty(info, value)
+ if value ~= self.config.hideEmpty then
+ self.config.hideEmpty = value
+ for _, b in self.bar:IterateButtons() do
+ b:ShowGrid(not value)
end
- else
- geterrorhandler()(r)
end
end
- return opts
+
+ function ActionHandler:GetHideEmpty()
+ return self.config.hideEmpty
+ end
+
+ function ActionHandler:GetLockButtons()
+ return self.config.lockButtons
+ end
+
+ function ActionHandler:SetLockButtons(info, value)
+ self.config.lockButtons = value
+ self:UpdateButtonLock()
+ end
+
+ function ActionHandler:GetLockButtonsCombat()
+ return self.config.lockButtonsCombat
+ end
+
+ function ActionHandler:SetLockButtonsCombat(info, value)
+ self.config.lockButtonsCombat = value
+ self:UpdateButtonLock()
+ end
+
+ function ActionHandler:LockButtonsCombatDisabled()
+ return not self.config.lockButtons
+ end
+
+ function ActionHandler:GetNumPages()
+ return self.config.nPages
+ end
+
+ function ActionHandler:SetNumPages(info, value)
+ self.config.nPages = value
+ self:Refresh()
+ end
+
+ function ActionHandler:GetMindControl()
+ return self.config.mindcontrol
+ end
+
+ function ActionHandler:SetMindControl(info, value)
+ self.config.mindcontrol = value
+ self:Refresh()
+ end
+
+ function ActionHandler:GetVehicle()
+ return self.config.vehicle
+ end
+
+ function ActionHandler:SetVehicle(info, value)
+ self.config.vehicle = value
+ self:Refresh()
+ end
+
+ function ActionHandler:GetActionEditMethod()
+ return self.editMethod or 0
+ end
+
+ function ActionHandler:SetActionEditMethod(info, value)
+ self.editMethod = value
+ end
+
+ function ActionHandler:IsButtonSelectHidden()
+ return self.editMethod ~= 1
+ end
+
+ function ActionHandler:GetRowList()
+ local r,c = self.bar:GetButtonGrid()
+ if self.rowList == nil or #self.rowList ~= r then
+ local list = { }
+ for i = 1, r do
+ table.insert(list,i)
+ end
+ self.rowList = list
+ end
+ return self.rowList
+ end
+
+ function ActionHandler:GetSelectedRow()
+ local r, c = self.bar:GetButtonGrid()
+ local row = self.selectedRow or 1
+ if row > r then
+ row = 1
+ end
+ self.selectedRow = row
+ return row
+ end
+
+ function ActionHandler:SetSelectedRow(info, value)
+ self.selectedRow = value
+ end
+
+ function ActionHandler:GetColumnList()
+ local r,c = self.bar:GetButtonGrid()
+ if self.columnList == nil or #self.columnList ~= c then
+ local list = { }
+ for i = 1, c do
+ table.insert(list,i)
+ end
+ self.columnList = list
+ end
+ return self.columnList
+ end
+
+ function ActionHandler:GetSelectedColumn()
+ local r, c = self.bar:GetButtonGrid()
+ local col = self.selectedColumn or 1
+ if col > c then
+ col = 1
+ end
+ self.selectedColumn = col
+ return col
+ end
+
+ function ActionHandler:SetSelectedColumn(info, value)
+ self.selectedColumn = value
+ end
+
+ function ActionHandler:IsPageSelectHidden()
+ return self.editMethod ~= 1 or (self.config.nPages or 1) < 2
+ end
+
+ function ActionHandler:GetPageList()
+ local n = self.config.nPages or 1
+ if self.pageList == nil or #self.pageList ~= n then
+ local p = { }
+ for i = 1, n do
+ table.insert(p,i)
+ end
+ self.pageList = p
+ end
+ return self.pageList
+ end
+
+ function ActionHandler:GetSelectedPage()
+ local p = self.selectedPage or 1
+ if p > (self.config.nPages or 1) then
+ p = 1
+ end
+ self.selectedPage = p
+ return p
+ end
+
+ function ActionHandler:SetSelectedPage(info, value)
+ self.selectedPage = value
+ end
+
+ function ActionHandler:GetActionID()
+ local row = self.selectedRow or 1
+ local col = self.selectedColumn or 1
+ local r, c = self.bar:GetButtonGrid()
+ local n = (row-1) * c + col
+ local btn = self.bar:GetButton(n)
+ if btn then
+ return tostring(btn:GetActionID(self.selectedPage or 1))
+ end
+ end
+
+ function ActionHandler:SetActionID(info, value)
+ local row = self.selectedRow or 1
+ local col = self.selectedColumn or 1
+ local r, c = self.bar:GetButtonGrid()
+ local n = (row-1) * c + col
+ local btn = self.bar:GetButton(n)
+ if btn then
+ btn:SetActionID(tonumber(value), self.selectedPage or 1)
+ end
+ end
+
+ function ActionHandler:ValidateActionID(info, value)
+ value = tonumber(value)
+ if value == nil or value < 1 or value > 120 then
+ return L["Specify ID 1-120"]
+ end
+ return true
+ end
+
+ function ActionHandler:IsMultiIDHidden()
+ return self.editMethod ~= 2
+ end
+
+ function ActionHandler:GetMultiID()
+ local p = { }
+ for i = 1, self.config.nPages or 1 do
+ local b = { }
+ for _, btn in self.bar:IterateButtons() do
+ table.insert(b, btn:GetActionID(i))
+ end
+ table.insert(p, table.concat(b,","))
+ end
+ return table.concat(p,";\n")
+ end
+
+
+ local function ParseMultiID(nBtns, nPages, s)
+ if s:match("[^%d%s,;]") then
+ return nil
+ end
+ local p = { }
+ for list in s:gmatch("[^;]+") do
+ local pattern = ("^%s?$"):format(("%s*(%d+)%s*,"):rep(nBtns))
+ local ids = { list:match(pattern) }
+ if #ids ~= nBtns then
+ return nil
+ end
+ table.insert(p,ids)
+ end
+ if #p ~= nPages then
+ return nil
+ end
+ return p
+ end
+
+ function ActionHandler:SetMultiID(info, value)
+ local p = ParseMultiID(self.bar:GetNumButtons(), self.config.nPages or 1, value)
+ for page, b in ipairs(p) do
+ for button, id in ipairs(b) do
+ self.bar:GetButton(button):SetActionID(id, page)
+ end
+ end
+ end
+
+ function ActionHandler:ValidateMultiID(info, value)
+ local bad = L["Invalid action ID list string"]
+ if value == nil or ParseMultiID(self.bar:GetNumButtons(), self.config.nPages or 1, value) == nil then
+ return bad
+ end
+ return true
+ end
end
+----------------------------------
+---- PetAction button handler ----
+----------------------------------
+
+do
+ local PetHandler = {
+ buttonClass = ReAction.Button.PetAction,
+ }
+
+ Editor.buttonHandlers[PetHandler.buttonClass:GetButtonTypeID()] = PetHandler
+
+ local meta = { __index = PetHandler }
+
+ function PetHandler:New(bar)
+ return setmetatable(
+ {
+ bar = bar,
+ config = bar.config
+ }, meta)
+ end
+
+ function PetHandler:GetLockButtons()
+ return self.config.lockButtons
+ end
+
+ function PetHandler:SetLockButtons(info, value)
+ self.config.lockButtons = value
+ self.buttonClass:UpdateButtonLock(self.bar)
+ end
+
+ function PetHandler:GetLockButtonsCombat()
+ return self.config.lockButtonsCombat
+ end
+
+ function PetHandler:SetLockButtonsCombat(info, value)
+ self.config.lockButtonsCombat = value
+ self.buttonClass:UpdateButtonLock(self.bar)
+ end
+
+ function PetHandler:LockButtonsCombatDisabled()
+ return not self.config.lockButtons
+ end
+
+ function PetHandler:GetOptions()
+ return {
+ type = "group",
+ name = L["Pet Buttons"],
+ handler = self,
+ order = 2,
+ args = {
+ lockButtons = {
+ name = L["Lock Buttons"],
+ desc = L["Prevents picking up/dragging actions (use SHIFT to override this behavior)"],
+ order = 2,
+ type = "toggle",
+ get = "GetLockButtons",
+ set = "SetLockButtons",
+ },
+ lockOnlyCombat = {
+ name = L["Only in Combat"],
+ desc = L["Only lock the buttons when in combat"],
+ order = 3,
+ type = "toggle",
+ disabled = "LockButtonsCombatDisabled",
+ get = "GetLockButtonsCombat",
+ set = "SetLockButtonsCombat",
+ },
+ }
+ }
+ end
+end
+
+
+-------------------------------------
+---- Vehicle Exit button handler ----
+-------------------------------------
+
+do
+ local VExitHandler = {
+ buttonClass = ReAction.Button.VehicleExit,
+ }
+
+ Editor.buttonHandlers[VExitHandler.buttonClass:GetButtonTypeID()] = VExitHandler
+
+ local meta = { __index = VExitHandler }
+
+ function VExitHandler:New(bar)
+ return setmetatable(
+ {
+ bar = bar,
+ }, meta)
+ end
+
+ function VExitHandler:GetConfig()
+ return self.bar:GetConfig()
+ end
+
+ function VExitHandler:GetPassengerOnly()
+ return not self:GetConfig().withControls
+ end
+
+ function VExitHandler:SetPassengerOnly(info, value)
+ self:GetConfig().withControls = not value
+ self.buttonClass:UpdateRegistration(self.bar)
+ end
+
+
+ function VExitHandler:GetOptions()
+ return {
+ type = "group",
+ name = L["Exit Vehicle"],
+ handler = self,
+ args = {
+ passengerOnly = {
+ name = L["Show only when passenger"],
+ desc = L["Only show the button when riding as a passenger in a vehicle (no vehicle controls)"],
+ order = 2,
+ width = "double",
+ type = "toggle",
+ get = "GetPassengerOnly",
+ set = "SetPassengerOnly",
+ },
+ }
+ }
+ end
+end
+
+
+------------------------------
+--- Dynamic State options ----
+------------------------------
+do
+ local ApplyStates = ReAction.Bar.ApplyStates
+ local CleanupStates = ReAction.Bar.CleanupStates
+ local SetProperty = ReAction.Bar.SetStateProperty
+ local GetProperty = ReAction.Bar.GetStateProperty
+
+ -- pre-sorted by the order they should appear in
+ local rules = {
+ -- rule fields
+ { "stance", { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
+ { "form", { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
+ { "stealth", { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]}, {shadowdance = L["Shadow Dance"]} } },
+ { "shadow", { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
+ { "demon", { {demon = L["Demon Form"]}, {nodemon = L["No Demon Form"]} } },
+ { "pet", { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
+ { "target", { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
+ { "focus", { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
+ { "possess", { {possess = L["Mind Control"]} } },
+ { "vehicle", { {vehicle = L["In a Vehicle"]} } },
+ { "group", { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
+ { "combat", { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
+ }
+
+ local ruleSelect = { }
+ local ruleMap = { }
+ local optionMap = setmetatable({},{__mode="k"})
+
+
+ -- unpack rules table into ruleSelect and ruleMap
+ for _, c in ipairs(rules) do
+ local rule, fields = unpack(c)
+ for _, field in ipairs(fields) do
+ local key, label = next(field)
+ table.insert(ruleSelect, label)
+ table.insert(ruleMap, key)
+ end
+ end
+
+ local stateOptions = {
+ ordering = {
+ name = L["Info"],
+ order = 1,
+ type = "group",
+ args = {
+ delete = {
+ name = L["Delete this State"],
+ order = -1,
+ type = "execute",
+ func = "DeleteState",
+ },
+ rename = {
+ name = L["Name"],
+ order = 1,
+ type = "input",
+ get = "GetName",
+ set = "SetStateName",
+ pattern = "^%w*$",
+ usage = L["State names must be alphanumeric without spaces"],
+ },
+ ordering = {
+ name = L["Evaluation Order"],
+ desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
+ order = 2,
+ type = "group",
+ inline = true,
+ args = {
+ up = {
+ name = L["Up"],
+ order = 1,
+ type = "execute",
+ width = "half",
+ func = "MoveStateUp",
+ },
+ down = {
+ name = L["Down"],
+ order = 2,
+ type = "execute",
+ width = "half",
+ func = "MoveStateDown",
+ }
+ }
+ }
+ }
+ },
+ properties = {
+ name = L["Properties"],
+ order = 2,
+ type = "group",
+ args = {
+ desc = {
+ name = L["Set the properties for the bar when in this state"],
+ order = 1,
+ type = "description"
+ },
+ page = {
+ name = L["Show Page #"],
+ order = 11,
+ type = "select",
+ width = "half",
+ disabled = "IsPageDisabled",
+ hidden = "IsPageHidden",
+ values = "GetPageValues",
+ set = "SetProp",
+ get = "GetPage",
+ },
+ hide = {
+ name = L["Hide Bar"],
+ order = 90,
+ type = "toggle",
+ set = "SetProp",
+ get = "GetProp",
+ },
+ --[[ BROKEN
+ keybindState = {
+ name = L["Override Keybinds"],
+ desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
+ order = 91,
+ type = "toggle",
+ set = "SetProp",
+ get = "GetProp",
+ }, ]]
+ position = {
+ name = L["Position"],
+ order = 92,
+ type = "group",
+ inline = true,
+ args = {
+ anchorEnable = {
+ name = L["Reposition"],
+ order = 1,
+ type = "toggle",
+ set = "SetProp",
+ get = "GetProp",
+ },
+ anchorFrame = {
+ name = L["Anchor Frame"],
+ order = 2,
+ type = "select",
+ values = "GetAnchorFrames",
+ set = "SetAnchorFrame",
+ get = "GetAnchorFrame",
+ disabled = "GetAnchorDisabled",
+ hidden = "GetAnchorDisabled",
+ },
+ anchorPoint = {
+ name = L["Point"],
+ order = 3,
+ type = "select",
+ values = pointTable,
+ set = "SetAnchorPointProp",
+ get = "GetAnchorPointProp",
+ disabled = "GetAnchorDisabled",
+ hidden = "GetAnchorDisabled",
+ },
+ anchorRelPoint = {
+ name = L["Relative Point"],
+ order = 4,
+ type = "select",
+ values = pointTable,
+ set = "SetAnchorPointProp",
+ get = "GetAnchorPointProp",
+ disabled = "GetAnchorDisabled",
+ hidden = "GetAnchorDisabled",
+ },
+ anchorX = {
+ name = L["X Offset"],
+ order = 5,
+ type = "range",
+ min = -100,
+ max = 100,
+ step = 1,
+ set = "SetProp",
+ get = "GetProp",
+ disabled = "GetAnchorDisabled",
+ hidden = "GetAnchorDisabled",
+ },
+ anchorY = {
+ name = L["Y Offset"],
+ order = 6,
+ type = "range",
+ min = -100,
+ max = 100,
+ step = 1,
+ set = "SetProp",
+ get = "GetProp",
+ disabled = "GetAnchorDisabled",
+ hidden = "GetAnchorDisabled",
+ },
+ },
+ },
+ scale = {
+ name = L["Scale"],
+ order = 93,
+ type = "group",
+ inline = true,
+ args = {
+ enableScale = {
+ name = L["Set New Scale"],
+ order = 1,
+ type = "toggle",
+ set = "SetProp",
+ get = "GetProp",
+ },
+ scale = {
+ name = L["Scale"],
+ order = 2,
+ type = "range",
+ min = 0.25,
+ max = 2.5,
+ step = 0.05,
+ isPercent = true,
+ set = "SetProp",
+ get = "GetScale",
+ disabled = "GetScaleDisabled",
+ hidden = "GetScaleDisabled",
+ },
+ },
+ },
+ alpha = {
+ name = L["Transparency"],
+ order = 94,
+ type = "group",
+ inline = true,
+ args = {
+ enableAlpha = {
+ name = L["Set Transparency"],
+ order = 1,
+ type = "toggle",
+ set = "SetProp",
+ get = "GetProp",
+ },
+ alpha = {
+ name = L["Transparency"],
+ order = 2,
+ type = "range",
+ min = 0,
+ max = 1,
+ step = 0.01,
+ bigStep = 0.05,
+ isPercent = true,
+ set = "SetProp",
+ get = "GetAlpha",
+ disabled = "GetAlphaDisabled",
+ hidden = "GetAlphaDisabled",
+ },
+ },
+ },
+ },
+ plugins = { }
+ },
+ rules = {
+ name = L["Rule"],
+ order = 3,
+ type = "group",
+ args = {
+ mode = {
+ name = L["Select this state"],
+ order = 2,
+ type = "select",
+ style = "radio",
+ values = {
+ default = L["by default"],
+ any = L["when ANY of these"],
+ all = L["when ALL of these"],
+ custom = L["via custom rule"],
+ keybind = L["via keybinding"],
+ },
+ set = "SetType",
+ get = "GetType",
+ },
+ clear = {
+ name = L["Clear All"],
+ order = 3,
+ type = "execute",
+ hidden = "GetClearAllDisabled",
+ disabled = "GetClearAllDisabled",
+ func = "ClearAllConditions",
+ },
+ inputs = {
+ name = L["Conditions"],
+ order = 4,
+ type = "multiselect",
+ hidden = "GetConditionsDisabled",
+ disabled = "GetConditionsDisabled",
+ values = ruleSelect,
+ set = "SetCondition",
+ get = "GetCondition",
+ },
+ custom = {
+ name = L["Custom Rule"],
+ order = 5,
+ type = "input",
+ multiline = true,
+ hidden = "GetCustomDisabled",
+ disabled = "GetCustomDisabled",
+ desc = L["Syntax like macro rules: see preset rules for examples"],
+ set = "SetCustomRule",
+ get = "GetCustomRule",
+ validate = "ValidateCustomRule",
+ },
+ keybind = {
+ name = L["Keybinding"],
+ order = 6,
+ inline = true,
+ hidden = "GetKeybindDisabled",
+ disabled = "GetKeybindDisabled",
+ type = "group",
+ args = {
+ desc = {
+ name = L["Invoking a state keybind toggles an override of all other transition rules."],
+ order = 1,
+ type = "description",
+ },
+ keybind = {
+ name = L["State Hotkey"],
+ desc = L["Define an override toggle keybind"],
+ order = 2,
+ type = "keybinding",
+ set = "SetKeybind",
+ get = "GetKeybind",
+ },
+ },
+ },
+ },
+ },
+ }
+
+ local StateHandler = { }
+ local meta = { __index = StateHandler }
+
+ function StateHandler:New( bar, opts )
+ local self = setmetatable(
+ {
+ bar = bar
+ },
+ meta )
+
+ function self:GetName()
+ return opts.name
+ end
+
+ function self:SetName(name)
+ opts.name = name
+ end
+
+ function self:GetOrder()
+ return opts.order
+ end
+
+ -- get reference to states table: even if the bar
+ -- name changes the states table ref won't
+ self.states = tbuild(bar:GetConfig(), "states")
+ self.state = tbuild(self.states, opts.name)
+
+ opts.order = self:GetRuleField("order")
+ if opts.order == nil then
+ -- add after the highest
+ opts.order = 100
+ for _, state in pairs(self.states) do
+ local x = tonumber(tfetch(state, "rule", "order"))
+ if x and x >= opts.order then
+ opts.order = x + 1
+ end
+ end
+ self:SetRuleField("order",opts.order)
+ end
+
+ return self
+ end
+
+ -- helper methods
+
+ function StateHandler:SetRuleField( key, value, ... )
+ tbuild(self.state, "rule", ...)[key] = value
+ end
+
+ function StateHandler:GetRuleField( ... )
+ return tfetch(self.state, "rule", ...)
+ end
+
+ function StateHandler:FixAll( setkey )
+ -- if multiple selections in the same group are chosen when 'all' is selected,
+ -- keep only one of them. If changing the mode, the first in the fields list will
+ -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
+ -- it will be retained.
+ local notified = false
+ if self:GetRuleField("type") == "all" then
+ for _, c in ipairs(rules) do
+ local rule, fields = unpack(c)
+ local once = false
+ if setkey then
+ for idx, field in ipairs(fields) do
+ if next(field) == setkey then
+ once = true
+ end
+ end
+ end
+ for idx, field in ipairs(fields) do
+ local key = next(field)
+ if self:GetRuleField("values",key) then
+ if once and key ~= setkey then
+ self:SetRuleField(key,false,"values")
+ if not setkey and not notified then
+ ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
+ notified = true
+ end
+ end
+ once = true
+ end
+ end
+ end
+ end
+ end
+
+ function StateHandler:GetNeighbors()
+ local before, after
+ for k, v in pairs(self.states) do
+ local o = tonumber(tfetch(v, "rule", "order"))
+ if o and k ~= self:GetName() then
+ local obefore = tfetch(self.states,before,"rule","order")
+ local oafter = tfetch(self.states,after,"rule","order")
+ if o < self:GetOrder() and (not obefore or obefore < o) then
+ before = k
+ end
+ if o > self:GetOrder() and (not oafter or oafter > o) then
+ after = k
+ end
+ end
+ end
+ return before, after
+ end
+
+ function StateHandler:SwapOrder( a, b )
+ -- do options table
+ local args = optionMap[self.bar].args
+ args[a].order, args[b].order = args[b].order, args[a].order
+ -- do profile
+ a = tbuild(self.states, a, "rule")
+ b = tbuild(self.states, b, "rule")
+ a.order, b.order = b.order, a.order
+ end
+
+ -- handler methods
+
+ function StateHandler:GetProp( info )
+ -- gets property of the same name as the options arg
+ return GetProperty(self.bar, self:GetName(), info[#info])
+ end
+
+ function StateHandler:SetProp( info, value )
+ -- sets property of the same name as the options arg
+ SetProperty(self.bar, self:GetName(), info[#info], value)
+ end
+
+ function StateHandler:DeleteState()
+ if self.states[self:GetName()] then
+ self.states[self:GetName()] = nil
+ ApplyStates(self.bar)
+ end
+ optionMap[self.bar].args[self:GetName()] = nil
+ end
+
+ function StateHandler:SetStateName(info, value)
+ -- check for existing state name
+ if self.states[value] then
+ ReAction:UserError(format(L["State named '%s' already exists"],value))
+ return
+ end
+ local args = optionMap[self.bar].args
+ local name = self:GetName()
+ self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil
+ self:SetName(value)
+ ApplyStates(self.bar)
+ ReAction:ShowEditor(self.bar, moduleID, value)
+ end
+
+ function StateHandler:MoveStateUp()
+ local before, after = self:GetNeighbors()
+ if before then
+ self:SwapOrder(before, self:GetName())
+ ApplyStates(self.bar)
+ end
+ end
+
+ function StateHandler:MoveStateDown()
+ local before, after = self:GetNeighbors()
+ if after then
+ self:SwapOrder(self:GetName(), after)
+ ApplyStates(self.bar)
+ end
+ end
+
+ function StateHandler:GetAnchorDisabled()
+ return not GetProperty(self.bar, self:GetName(), "anchorEnable")
+ end
+
+ function StateHandler:IsPageDisabled()
+ local n = self.bar:GetConfig().nPages or 1
+ return not (n > 1)
+ end
+
+ function StateHandler:IsPageHidden()
+ return not self.bar:GetConfig().nPages
+ end
+
+ function StateHandler:GetPageValues()
+ if not self._pagevalues then
+ self._pagevalues = { }
+ end
+ local n = self.bar:GetConfig().nPages
+ -- cache the results
+ if self._npages ~= n then
+ self._npages = n
+ wipe(self._pagevalues)
+ for i = 1, n do
+ self._pagevalues["page"..i] = i
+ end
+ end
+ return self._pagevalues
+ end
+
+ function StateHandler:GetPage(info)
+ return self:GetProp(info) or 1
+ end
+
+ function StateHandler:GetAnchorFrames(info)
+ self._anchorframes = self._anchorframes or { }
+ table.wipe(self._anchorframes)
+
+ table.insert(self._anchorframes, "UIParent")
+ for name, bar in ReAction:IterateBars() do
+ table.insert(self._anchorframes, bar:GetFrame():GetName())
+ end
+ return self._anchorframes
+ end
+
+ function StateHandler:GetAnchorFrame(info)
+ local value = self:GetProp(info)
+ for k,v in pairs(self._anchorframes) do
+ if v == value then
+ return k
+ end
+ end
+ end
+
+ function StateHandler:SetAnchorFrame(info, value)
+ local f = _G[self._anchorframes[value]]
+ if f then
+ self.bar:SetFrameRef("anchor-"..self:GetName(), f)
+ self:SetProp(info, f:GetName())
+ end
+ end
+
+ function StateHandler:SetAnchorPointProp(info, value)
+ self:SetProp(info, value ~= "NONE" and value or nil)
+ end
+
+ function StateHandler:GetAnchorPointProp(info)
+ return self:GetProp(info) or "NONE"
+ end
+
+ function StateHandler:GetScale(info)
+ return self:GetProp(info) or 1.0
+ end
+
+ function StateHandler:GetScaleDisabled()
+ return not GetProperty(self.bar, self:GetName(), "enableScale")
+ end
+
+ function StateHandler:GetAlpha(info)
+ return self:GetProp(info) or 1.0
+ end
+
+ function StateHandler:GetAlphaDisabled()
+ return not GetProperty(self.bar, self:GetName(), "enableAlpha")
+ end
+
+ function StateHandler:SetType(info, value)
+ self:SetRuleField("type", value)
+ self:FixAll()
+ ApplyStates(self.bar)
+ end
+
+ function StateHandler:GetType()
+ return self:GetRuleField("type")
+ end
+
+ function StateHandler:GetClearAllDisabled()
+ local t = self:GetRuleField("type")
+ return not( t == "any" or t == "all" or t == "custom")
+ end
+
+ function StateHandler:ClearAllConditions()
+ local t = self:GetRuleField("type")
+ if t == "custom" then
+ self:SetRuleField("custom","")
+ elseif t == "any" or t == "all" then
+ self:SetRuleField("values", {})
+ end
+ ApplyStates(self.bar)
+ end
+
+ function StateHandler:GetConditionsDisabled()
+ local t = self:GetRuleField("type")
+ return not( t == "any" or t == "all")
+ end
+
+ function StateHandler:SetCondition(info, key, value)
+ self:SetRuleField(ruleMap[key], value or nil, "values")
+ if value then
+ self:FixAll(ruleMap[key])
+ end
+ ApplyStates(self.bar)
+ end
+
+ function StateHandler:GetCondition(info, key)
+ return self:GetRuleField("values", ruleMap[key]) or false
+ end
+
+ function StateHandler:GetCustomDisabled()
+ return self:GetRuleField("type") ~= "custom"
+ end
+
+ function StateHandler:SetCustomRule(info, value)
+ self:SetRuleField("custom",value)
+ ApplyStates(self.bar)
+ end
+
+ function StateHandler:GetCustomRule()
+ return self:GetRuleField("custom") or ""
+ end
+
+ function StateHandler:ValidateCustomRule(info, value)
+ local s = value:gsub("%s","") -- remove all spaces
+ -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
+ repeat
+ if s == "" then
+ return true
+ end
+ local c, r = s:match("(%b[])(.*)")
+ if c == nil and s and #s > 0 then
+ return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "")
+ end
+ s = r
+ until c == nil
+ return true
+ end
+
+ function StateHandler:GetKeybindDisabled()
+ return self:GetRuleField("type") ~= "keybind"
+ end
+
+ function StateHandler:GetKeybind()
+ return self:GetRuleField("keybind")
+ end
+
+ function StateHandler:SetKeybind(info, value)
+ if value and #value == 0 then
+ value = nil
+ end
+ self:SetRuleField("keybind",value)
+ ApplyStates(self.bar)
+ end
+
+ local function CreateStateOptions(bar, name)
+ local opts = {
+ type = "group",
+ name = name,
+ childGroups = "tab",
+ args = stateOptions
+ }
+
+ opts.handler = StateHandler:New(bar,opts)
+
+ return opts
+ end
+
+ function Editor:CreateStateOptions(bar)
+ local private = { }
+ local states = tbuild(bar:GetConfig(), "states")
+ local options = {
+ name = L["Dynamic State"],
+ type = "group",
+ order = -1,
+ childGroups = "tree",
+ disabled = InCombatLockdown,
+ args = {
+ __desc__ = {
+ name = L["States are evaluated in the order they are listed"],
+ order = 1,
+ type = "description",
+ },
+ __new__ = {
+ name = L["New State..."],
+ order = 2,
+ type = "group",
+ args = {
+ name = {
+ name = L["State Name"],
+ desc = L["Set a name for the new state"],
+ order = 1,
+ type = "input",
+ get = function() return private.newstatename or "" end,
+ set = function(info,value) private.newstatename = value end,
+ pattern = "^%w*$",
+ usage = L["State names must be alphanumeric without spaces"],
+ },
+ create = {
+ name = L["Create State"],
+ order = 2,
+ type = "execute",
+ func = function ()
+ local name = private.newstatename
+ if states[name] then
+ ReAction:UserError(format(L["State named '%s' already exists"],name))
+ else
+ -- TODO: select default state options and pass as final argument
+ states[name] = { }
+ optionMap[bar].args[name] = CreateStateOptions(bar,name)
+ ReAction:ShowEditor(bar, moduleID, name)
+ private.newstatename = ""
+ end
+ end,
+ disabled = function()
+ local name = private.newstatename or ""
+ return #name == 0 or name:find("%W")
+ end,
+ }
+ }
+ }
+ }
+ }
+ for name, config in pairs(states) do
+ options.args[name] = CreateStateOptions(bar,name)
+ end
+ optionMap[bar] = options
+ return options
+ end
+end
+
---- Export to ReAction ----
function ReAction:ShowEditor(bar, ...)
@@ -439,22 +1711,3 @@
end
end
-function ReAction:RegisterBarOptionGenerator( module, func )
- if not module or type(module) ~= "table" then -- doesn't need to be a proper module, strictly
- error("ReAction:RegisterBarOptionGenerator() : Invalid module")
- end
- if type(func) == "string" then
- if not module[func] then
- error(("ReAction:RegisterBarOptionGenerator() : Invalid method '%s'"):format(func))
- end
- elseif func and type(func) ~= "function" then
- error("ReAction:RegisterBarOptionGenerator() : Invalid function")
- end
- self.barOptionGenerators = self.barOptionGenerators or { }
- self.barOptionGenerators[module] = func
-
- if self.editor then
- self.editor:RefreshBarOptions()
- end
-end
-
diff -r b2b105747466 -r 920d17851a93 MultiCastButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MultiCastButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,779 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local unpack = unpack
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local InCombatLockdown = InCombatLockdown
+local IsUsableSpell = IsUsableSpell
+local IsUsableAction = IsUsableAction
+local IsSpellKnown = IsSpellKnown
+local IsSpellInRange = IsSpellInRange
+local IsActionInRange = IsActionInRange
+local GetSpellInfo = GetSpellInfo
+local GetSpellCooldown = GetSpellCooldown
+local GetActionCooldown = GetActionCooldown
+local GetSpellTexture = GetSpellTexture
+local GetActionTexture = GetActionTexture
+local GetMultiCastTotemSpells = GetMultiCastTotemSpells
+
+--[[
+ Blizzard Constants:
+ - NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4
+ - NUM_MULTI_CAST_PAGES = 3
+ - SHAMAN_TOTEM_PRIORITIES = { } -- sets the order of the totems
+ - TOTEM_MULTI_CAST_SUMMON_SPELLS = { } -- list of summon spellIDs
+ - TOTEM_MULTI_CAST_RECALL_SPELLS = { } -- list of recall spellIDs
+
+ Blizzard Events:
+ - UPDATE_MULTI_CAST_ACTIONBAR
+
+ Blizzard APIs:
+ - GetMultiCastBarOffset() : returns 6
+
+ - SetMultiCastSpell(actionID, spellID) (protected) OR
+ SetAttribute("type","multispell")
+ SetAttribute("action",actionID)
+ SetAttribute("spell",spellID)
+
+ note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
+ so that's action ID 132-144.
+
+ - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
+ returns spellIDs for all known totems that fit that slot. This function is available in
+ the secure environment.
+
+ Blizzard textures:
+ All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
+ texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
+ this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
+
+ Each totem button and arrow has a colored border indicating its elemental type.
+
+ TODO:
+ - make whether to show the colored border configurable (looks really bad with ButtonFacade:Zoomed)
+ - apply ButtonFacade to the flyout buttons? Or at least zoom the textures slightly?
+ - use a multiplier with SetTexCoord on totem bar texture?
+
+ Design Notes:
+ - Only the header has a secure context. All other frames execute in its context.
+
+ - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are
+ GetBonusBarOffset()=6, 132-144) with 3 pages of 4 buttons. The paging is controlled by
+ the summon flyout, which is also paged with the summon spells (the recall button is not paged)
+
+ - A spell list is updated in the secure context at setup time (TODO: redo setup when learning new
+ spells) with the list of spells known for each slot.
+
+ - Each button (except recall) has an arrow button which appears on mouseover and when clicked
+ opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
+ appear.
+
+ - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
+ of the bar. Each time the flyout panel is opened, the individual buttons grab their corresponding
+ spell/type from the list, according to the slot which opened the flyout. Each button either sets
+ the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
+ actually cast any spells (though, I suppose we could modify this so that e.g. configurable
+ right-click casts the spell). The flyout also has a close button which closes the flyout: the
+ flyout-open code positions the close button anchored to the last button in the flyout (which
+ changes dynamically because each slot has a different number of items in the list).
+
+ - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of
+ the summon spells is cast from elsewhere.
+
+ - The default UI has Call of the Elements always selected on UI load. This module remembers the last
+ selected one and restores it.
+
+
+]]--
+
+
+--
+-- Secure snippets
+--
+
+-- bar
+local _bar_init = -- function(self)
+[[
+ -- set up some globals in the secure environment
+ flyout = self:GetFrameRef("flyout")
+ flyoutSlot = nil
+ summonSlot = self:GetAttribute("summonSlot")
+ recallSlot = self:GetAttribute("recallSlot")
+ baseActionID = self:GetAttribute("baseActionID")
+ slotsPerPage = self:GetAttribute("slotsPerPage")
+ currentPage = currentPage or self:GetAttribute("lastSummon") or 1
+
+ totemIDsBySlot = newtable()
+ for i = 1, slotsPerPage do
+ totemIDsBySlot[i] = self:GetAttribute("TOTEM_PRIORITY_"..i)
+ end
+
+ -- these are set up in bar:SetupBar()
+ flyoutChildren = flyoutChildren or newtable()
+ summonSpells = summonSpells or newtable()
+]]
+
+local _onstate_multispellpage = -- function(self, stateid, newstate)
+[[
+ currentPage = tonumber(newstate)
+ control:CallMethod("UpdateLastSummon",currentPage)
+ control:ChildUpdate()
+]]
+
+
+-- buttons
+local _childupdate = -- function(self, snippetid, message)
+[[
+ local t = self:GetAttribute("type")
+ self:SetAttribute(t, self:GetAttribute(t.."-page"..currentPage))
+]]
+
+local _onEnter = -- function(self)
+ -- for whatever reason, RegisterAutoHide is unreliable
+ -- unless you re-anchor the frame prior to calling it.
+ -- Even then, it's still not terribly reliable.
+[[
+ local slot = self:GetAttribute("bar-idx")
+ local arrow = owner:GetFrameRef("arrow-"..slot)
+ if arrow and not arrow:IsShown() and not (flyout:IsVisible() and flyoutSlot == slot) then
+ arrow:ClearAllPoints()
+ arrow:SetPoint("BOTTOM",self,"TOP",0,0)
+ arrow:Show()
+ arrow:RegisterAutoHide(0)
+ arrow:AddToAutoHide(self)
+ end
+]]
+
+
+-- flyout arrow
+local _arrow_openFlyout = -- function(self)
+[[
+ local slot = self:GetAttribute("bar-idx")
+ local totemID = totemIDsBySlot[slot - (summonSlot or 0)]
+ if totemID == 0 then
+ totemID = "summon"
+ end
+
+ local lastButton, lastPage
+ for page, b in ipairs(flyoutChildren) do
+ b:Hide()
+ b:SetAttribute("totemSlot",totemID)
+ if slot == summonSlot then
+ local spellID = self:GetParent():GetAttribute("spell-page"..page)
+ if spellID then
+ b:SetAttribute("type","changePage")
+ b:SetAttribute("spell",spellID)
+ b:Show()
+ lastButton = b
+ lastPage = page
+ end
+ else
+ local spell = select(page, 0, GetMultiCastTotemSpells(totemID) )
+ if spell then
+ b:SetAttribute("type","multispell")
+ b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
+ b:SetAttribute("spell", spell)
+ b:Show()
+ lastButton = b
+ lastPage = page
+ end
+ end
+ end
+
+ local close = owner:GetFrameRef("close")
+ if lastButton and close then
+ close:ClearAllPoints()
+ close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
+ close:Show()
+ control:CallMethod("UpdateFlyoutTextures",totemID)
+ end
+
+ flyout:ClearAllPoints()
+ flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring
+ if lastPage then
+ flyout:SetHeight(lastPage * 27 + (close and close:GetHeight() or 0))
+ end
+ flyout:Show()
+ flyout:RegisterAutoHide(1) -- TODO: configurable
+ flyout:AddToAutoHide(owner)
+ flyoutSlot = slot
+ self:Hide()
+]]
+
+local _closeFlyout = -- function(self)
+[[
+ flyout:Hide()
+]]
+
+
+-- flyout child buttons
+local _flyout_child_preClick = -- function(self, button, down)
+[[
+ local button = button
+ if self:GetAttribute("type") == "changePage" then
+ owner:SetAttribute("state-multispellpage",self:GetAttribute("index"))
+ self:GetParent():Hide()
+ return false
+ else
+ return nil, "close"
+ end
+]]
+
+local _flyout_child_postClick = -- function(self, message, button, down)
+[[
+ if message == "close" then
+ self:GetParent():Hide() -- hide flyout after selecting
+ end
+]]
+
+
+--
+-- The Blizzard totem bar textures are all actually one big texture,
+-- with texcoord offsets. Shamelessly stolen from FrameXML/MultiCastActionBarFrame.lua
+--
+local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
+local FLYOUT_UP_BUTTON_HL_TCOORDS = { 72/128, 92/128, 88/256, 98/256 }
+local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128, 92/128, 69/256, 79/256 }
+
+local SLOT_EMPTY_TCOORDS = {
+ [EARTH_TOTEM_SLOT] = { 66/128, 96/128, 3/256, 33/256 },
+ [FIRE_TOTEM_SLOT] = { 67/128, 97/128, 100/256, 130/256 },
+ [WATER_TOTEM_SLOT] = { 39/128, 69/128, 209/256, 239/256 },
+ [AIR_TOTEM_SLOT] = { 66/128, 96/128, 36/256, 66/256 },
+}
+
+local SLOT_OVERLAY_TCOORDS = {
+ [EARTH_TOTEM_SLOT] = { 1/128, 35/128, 172/256, 206/256 },
+ [FIRE_TOTEM_SLOT] = { 36/128, 70/128, 172/256, 206/256 },
+ [WATER_TOTEM_SLOT] = { 1/128, 35/128, 207/256, 240/256 },
+ [AIR_TOTEM_SLOT] = { 36/128, 70/128, 137/256, 171/256 },
+}
+
+local FLYOUT_UP_BUTTON_TCOORDS = {
+ ["summon"] = { 99/128, 127/128, 84/256, 102/256 },
+ [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 160/256, 178/256 },
+ [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 122/256, 140/256 },
+ [WATER_TOTEM_SLOT] = { 99/128, 127/128, 199/256, 217/256 },
+ [AIR_TOTEM_SLOT] = { 99/128, 127/128, 237/256, 255/256 },
+}
+
+local FLYOUT_DOWN_BUTTON_TCOORDS = {
+ ["summon"] = { 99/128, 127/128, 65/256, 83/256 },
+ [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 141/256, 159/256 },
+ [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 103/256, 121/256 },
+ [WATER_TOTEM_SLOT] = { 99/128, 127/128, 180/256, 198/256 },
+ [AIR_TOTEM_SLOT] = { 99/128, 127/128, 218/256, 236/256 },
+}
+
+local FLYOUT_TOP_TCOORDS = {
+ ["summon"] = { 33/128, 65/128, 1/256, 23/256 },
+ [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 46/256, 68/256 },
+ [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 46/256, 68/256 },
+ [WATER_TOTEM_SLOT] = { 0/128, 32/128, 1/256, 23/256 },
+ [AIR_TOTEM_SLOT] = { 0/128, 32/128, 91/256, 113/256 },
+}
+
+local FLYOUT_MIDDLE_TCOORDS = {
+ ["summon"] = { 33/128, 65/128, 23/256, 43/256 },
+ [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 68/256, 88/256 },
+ [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 68/256, 88/256 },
+ [WATER_TOTEM_SLOT] = { 0/128, 32/128, 23/256, 43/256 },
+ [AIR_TOTEM_SLOT] = { 0/128, 32/128, 113/256, 133/256 },
+}
+
+local eventList = {
+ "ACTIONBAR_SLOT_CHANGED",
+ "ACTIONBAR_UPDATE_STATE",
+ "ACTIONBAR_UPDATE_USABLE",
+ "ACTIONBAR_UPDATE_COOLDOWN",
+ "UPDATE_BINDINGS",
+ "UPDATE_MULTI_CAST_ACTIONBAR",
+}
+
+--
+-- MultiCast Button class
+-- Inherits implementation methods from Action button class, but circumvents the constructor
+-- and redefines/removes some methods.
+--
+local buttonTypeID = "Totem"
+local Super = ReAction.Button
+local Action = ReAction.Button.Action
+local MultiCast = setmetatable(
+ {
+ defaultBarConfig = {
+ type = buttonTypeID,
+ btnWidth = 36,
+ btnHeight = 36,
+ btnRows = 1,
+ btnColumns = 6,
+ spacing = 3,
+ buttons = { }
+ },
+
+ barType = L["Totem Bar"],
+ buttonTypeID = buttonTypeID
+ },
+ { __index = Action } )
+
+ReAction.Button.MultiCast = MultiCast
+ReAction:RegisterBarType(MultiCast)
+
+function MultiCast:New( btnConfig, bar, idx )
+ local maxIndex = bar.nTotemSlots or 0
+ if bar.summonSlot then
+ maxIndex = maxIndex + 1
+ end
+ if bar.recallSlot then
+ maxIndex = maxIndex + 1
+ end
+
+ if not bar.hasMulticast or idx > maxIndex then
+ return false
+ end
+
+ if idx < 1 then
+ error("invalid index")
+ end
+
+ local name = format("ReAction_%s_Totem_%d",bar:GetName(),idx)
+
+ self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+ local barFrame = bar:GetFrame()
+ local f = self:GetFrame()
+
+ -- attributes
+ local page = (idx == bar.recallSlot) and 1 or bar:GetConfig().lastSummon or 1
+ if idx == bar.recallSlot or idx == bar.summonSlot then
+ f:SetAttribute("type","spell")
+ local spells = (idx == bar.summonSlot) and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
+ f:SetAttribute("spell",spells[page])
+ for i, spell in ipairs(spells) do
+ if spell and IsSpellKnown(spell) then
+ f:SetAttribute("spell-page"..i, spell)
+ end
+ end
+ else
+ local offset = bar.summonSlot and 1 or 0
+ local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
+ local baseAction = barFrame:GetAttribute("baseActionID") + slot
+ self.totemSlot = slot
+ f:SetAttribute("type","action")
+ f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+ for i = 1, NUM_MULTI_CAST_PAGES do
+ f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+ end
+ if not f.overlayTex then
+ local tx = f:CreateTexture("OVERLAY")
+ tx:SetTexture(TOTEM_TEXTURE)
+ tx:SetTexCoord(unpack(SLOT_OVERLAY_TCOORDS[self.totemSlot]))
+ tx:SetWidth(34)
+ tx:SetHeight(34)
+ tx:SetPoint("CENTER")
+ tx:Show()
+ f.overlayTex = tx
+ end
+ end
+ f:SetAttribute("bar-idx",idx)
+
+ -- non secure scripts
+ f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+ f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+ f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+ f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+ f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
+
+ -- secure handlers
+ if idx ~= bar.recallSlot then
+ f:SetAttribute("_childupdate",_childupdate)
+ end
+ barFrame:WrapScript(f, "OnEnter", _onEnter)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForClicks("AnyUp")
+ for _, evt in pairs(eventList) do
+ f:RegisterEvent(evt)
+ end
+
+ -- Set up a proxy for the icon texture for use with ButtonFacade
+ local SetTexCoordRaw = self.frames.icon.SetTexCoord
+ self.frames.icon.SetTexCoord = function( tx, ... )
+ if self:GetIconTexture() == TOTEM_TEXTURE then
+ SetTexCoordRaw(tx,select(2,self:GetIconTexture()))
+ else
+ SetTexCoordRaw(tx,...)
+ end
+ end
+
+ -- attach to skinner
+ bar:SkinButton(self)
+
+ f:Show()
+
+ -- open arrow and flyout background textures
+ if idx ~= bar.recallSlot then
+ local arrow = f._arrowFrame or CreateFrame("Button", nil, f, "SecureFrameTemplate")
+ f._arrowFrame = arrow
+ arrow:SetWidth(28)
+ arrow:SetHeight(18)
+ arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
+ arrow:SetNormalTexture(TOTEM_TEXTURE)
+ local slot = self.totemSlot or "summon"
+ arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS[slot]) )
+ arrow:SetHighlightTexture(TOTEM_TEXTURE)
+ arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
+ arrow:SetAttribute("bar-idx",idx)
+ arrow:Hide()
+ barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
+ barFrame:SetFrameRef("arrow-"..idx,arrow)
+ end
+
+ self:Refresh()
+
+ return self
+end
+
+function MultiCast:Destroy()
+ local barFrame = self.bar:GetFrame()
+ local f = self:GetFrame()
+ pcall( barFrame.UnwrapScript, barFrame, f, "OnEnter" ) -- ignore errors
+ if f._arrowFrame then
+ pcall( barFrame.UnwrapScript, barFrame, f._arrowFrame,"OnClick" ) -- ignore errors
+ end
+ Super.Destroy(self)
+end
+
+function MultiCast:Refresh()
+ Super.Refresh(self)
+ self:UpdateAction()
+end
+
+function MultiCast:ShowGrid( show )
+end
+
+function MultiCast:ShowGridTemp( show )
+end
+
+function MultiCast:AcquireActionID()
+end
+
+function MultiCast:ReleaseActionID()
+end
+
+function MultiCast:UpdateShowGrid()
+end
+
+function MultiCast:UpdateBorder()
+end
+
+function MultiCast:UpdateMacroText()
+end
+
+function MultiCast:UpdateCount()
+end
+
+function MultiCast:UpdateCheckedState()
+ local action = self:GetActionID()
+ if action and IsCurrentAction(action) then
+ self:GetFrame():SetChecked(1)
+ else
+ self:GetFrame():SetChecked(0)
+ end
+end
+
+function MultiCast:RefreshHasActionAttributes()
+end
+
+function MultiCast:UpdateFlash()
+end
+
+function MultiCast:GetIconTexture()
+ local tx
+ if self.spellID then
+ tx = GetSpellTexture(GetSpellInfo(self.spellID))
+ elseif self.actionID then
+ tx = GetActionTexture(self.actionID)
+ end
+ if tx then
+ return tx
+ else
+ return TOTEM_TEXTURE, unpack(SLOT_EMPTY_TCOORDS[self.totemSlot or 1])
+ end
+end
+
+function MultiCast:UpdateAction()
+ local action = self:GetActionID()
+ if action then
+ if action ~= self.actionID then
+ self.actionID = action
+ self:UpdateAll()
+ end
+ else
+ local spellID = self:GetSpellID()
+ if spellID ~= self.spellID then
+ self.spellID = spellID
+ self:UpdateAll()
+ end
+ end
+end
+
+function MultiCast:GetActionID(page)
+ return self:GetFrame():GetAttribute("action")
+end
+
+function MultiCast:GetSpellID(page)
+ return self:GetFrame():GetAttribute("spell")
+end
+
+function MultiCast:SetActionID( id )
+ error("Can not set action ID of multicast buttons")
+end
+
+function MultiCast:SetTooltip()
+ local barFrame = self:GetFrame()
+ if GetCVar("UberTooltips") == "1" then
+ GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
+ else
+ GameTooltip:SetOwner(barFrame)
+ end
+ if self.spellID then
+ GameTooltip:SetSpellByID(self.spellID,false,true)
+ elseif self.actionID then
+ GameTooltip:SetAction(self.actionID)
+ end
+end
+
+function MultiCast:GetUsable()
+ if self.spellID then
+ return IsUsableSpell((GetSpellInfo(self.spellID)))
+ elseif self.actionID then
+ return IsUsableAction(self.actionID)
+ end
+end
+
+function MultiCast:GetInRange()
+ if self.spellID then
+ return IsSpellInRange((GetSpellInfo(self.spellID))) == 0
+ elseif self.actionID then
+ return IsActionInRange(self.actionID) == 0
+ end
+end
+
+function MultiCast:GetCooldown()
+ if self.spellID then
+ return GetSpellCooldown((GetSpellInfo(self.spellID)))
+ elseif self.actionID then
+ return GetActionCooldown(self.actionID)
+ else
+ return 0, 0, 0
+ end
+end
+
+function MultiCast:UPDATE_MULTI_CAST_ACTIONBAR()
+ self:UpdateAll()
+end
+
+
+--
+-- flyout setup
+--
+local function ShowFlyoutTooltip(frame)
+ if GetCVar("UberTooltips") == "1" then
+ GameTooltip_SetDefaultAnchor(GameTooltip, frame)
+ else
+ GameTooltip:SetOwner(frame)
+ end
+ local spell = frame:GetAttribute("spell")
+ if spell == nil or spell == 0 then
+ GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
+ else
+ GameTooltip:SetSpellByID(spell,false,true)
+ end
+end
+
+local function HideFlyoutTooltip()
+ GameTooltip:Hide()
+end
+
+local function UpdateFlyoutIcon(frame)
+ local spellID = frame:GetAttribute("spell")
+ if spellID == 0 or spellID == nil then
+ frame.icon:SetTexture(TOTEM_TEXTURE)
+ local slot = tonumber(frame:GetAttribute("totemSlot")) or 1
+ frame.icon:SetTexCoord( unpack(SLOT_EMPTY_TCOORDS[slot]) )
+ else
+ frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
+ frame.icon:SetTexCoord(0,1,0,1)
+ end
+end
+
+function MultiCast:SetupBar( bar )
+ Super.SetupBar(self,bar)
+
+ local slot = 0
+ local nTotemSlots = 0
+ local summonSlot = nil
+ local recallSlot = nil
+
+ -- figure out the capabilities of the character
+ for i, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do
+ if spell and IsSpellKnown(spell) then
+ slot = 1
+ summonSlot = 1
+ end
+ end
+
+ for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
+ local totem = SHAMAN_TOTEM_PRIORITIES[i];
+ if GetTotemInfo(totem) and GetMultiCastTotemSpells(totem) then
+ nTotemSlots = nTotemSlots + 1
+ slot = slot + 1
+ end
+ end
+
+ slot = slot + 1
+ for i, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do
+ if spell and IsSpellKnown(spell) then
+ recallSlot = slot
+ end
+ end
+
+ if nTotemSlots == 0 then
+ bar.hasMulticast = false -- no multicast capability
+ return
+ end
+
+ bar.hasMulticast = true
+ bar.summonSlot = summonSlot
+ bar.recallSlot = recallSlot
+ bar.nTotemSlots = nTotemSlots
+
+
+ local f = bar:GetFrame()
+
+ -- init bar secure environment
+ f:SetAttribute("lastSummon", bar:GetConfig().lastSummon)
+ f:SetAttribute("summonSlot", summonSlot)
+ f:SetAttribute("recallSlot", recallSlot)
+ f:SetAttribute("slotsPerPage", NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+ f:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
+ for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
+ f:SetAttribute("TOTEM_PRIORITY_"..i,p)
+ end
+ f:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
+
+ function f:UpdateLastSummon(value)
+ bar:GetConfig().lastSummon = value
+ end
+
+ -- create flyout container frame and close arrow
+ local flyout = bar._flyoutFrame
+ if not flyout then
+ flyout = CreateFrame("Frame", nil, f, "SecureFrameTemplate")
+ bar._flyoutFrame = flyout
+ f:SetFrameRef("flyout",flyout)
+ flyout.buttons = { }
+ flyout:Hide()
+ flyout:SetWidth(24)
+ flyout:SetHeight(1)
+ flyout:SetPoint("BOTTOM",f,"TOP",0,0)
+
+ local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
+ close:SetWidth(28)
+ close:SetHeight(18)
+ close:SetPoint("BOTTOM",flyout,"TOP")
+ close:SetNormalTexture(TOTEM_TEXTURE)
+ close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS["summon"]))
+ close:SetHighlightTexture(TOTEM_TEXTURE)
+ close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
+ f:SetFrameRef("close",close)
+ f:WrapScript(close, "OnClick", _closeFlyout)
+ close:Show()
+
+ local midTx = flyout:CreateTexture("BACKGROUND")
+ midTx:SetWidth(32)
+ midTx:SetHeight(20)
+ midTx:SetPoint("BOTTOM")
+ midTx:SetTexture(TOTEM_TEXTURE)
+ midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS["summon"]))
+ midTx:Show()
+
+ local topTx = flyout:CreateTexture("BACKGROUND")
+ topTx:SetWidth(32)
+ topTx:SetHeight(20)
+ topTx:SetTexture(TOTEM_TEXTURE)
+ midTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS["summon"]))
+ topTx:SetPoint("BOTTOM",midTx,"TOP",0,-10)
+ topTx:Show()
+
+ function flyout:UpdateTextures(slot)
+ slot = slot or "summon"
+ close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS[slot]))
+ midTx:ClearAllPoints()
+ midTx:SetPoint("BOTTOM")
+ midTx:SetPoint("TOP",close,"BOTTOM",0,0)
+ midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS[slot]))
+ topTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS[slot]))
+ end
+
+ -- create flyout buttons
+ for i = 1, 10 do -- maximum 9 spells + 1 empty slot
+ local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
+ b:SetWidth(24)
+ b:SetHeight(24)
+ local prev = flyout.buttons[i-1]
+ b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
+ b.icon = b:CreateTexture("BACKGROUND")
+ b.icon:SetAllPoints()
+ b.icon:Show()
+ b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
+ b:GetHighlightTexture():SetBlendMode("ADD")
+ b:RegisterForClicks("AnyUp")
+ b:SetScript("OnShow",UpdateFlyoutIcon)
+ b:SetScript("OnEnter",ShowFlyoutTooltip)
+ b:SetScript("OnLeave",HideFlyoutTooltip)
+ b:SetAttribute("index",i)
+ f:SetAttribute("flyout-child-idx",i)
+ f:SetFrameRef("flyout-child",b)
+ f:Execute([[
+ flyoutChildren = flyoutChildren or newtable()
+ flyoutChildren[self:GetAttribute("flyout-child-idx")] = self:GetFrameRef("flyout-child")
+ ]])
+ f:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
+ b:Show()
+ flyout.buttons[i] = b
+ end
+ end
+
+ -- scale flyout frame
+ local scale = bar:GetButtonSize() / 36
+ flyout:SetScale(scale)
+
+ function f:UpdateFlyoutTextures(slot)
+ flyout:UpdateTextures(slot)
+ end
+
+ -- re-execute setup when new spells are loaded
+ if not f.events_registered then
+ f:RegisterEvent("UPDATE_MULTI_CAST_ACTIONBAR")
+ f:RegisterEvent("PLAYER_ENTERING_WORLD")
+ -- Bar.frame does not use OnEvent
+ f:SetScript("OnEvent",
+ function()
+ if not InCombatLockdown() then
+ self:SetupBar(bar)
+ end
+ end)
+ f.events_registered = true
+ end
+
+
+ f:Execute(_bar_init)
+end
+
diff -r b2b105747466 -r 920d17851a93 Options.lua
--- a/Options.lua Thu Nov 18 13:11:08 2010 -0800
+++ b/Options.lua Tue Apr 12 16:06:31 2011 -0700
@@ -40,10 +40,9 @@
type = "toggle",
name = L["Hide Blizzard Action Bars"],
desc = L["Hide the default main bar and extra action bars"],
- handler = self:GetModule("HideBlizzard"),
- get = "IsHidden",
- set = "SetHidden",
- disabled = "OptionDisabled",
+ get = "OptionGetHideBlizzardBars",
+ set = "OptionSetHideBlizzardBars",
+ disabled = InCombatLockdown,
width = "full",
order = 3,
},
@@ -51,10 +50,9 @@
type = "toggle",
name = L["Hide Blizzard Vehicle Bar"],
desc = L["Hide the default vechicle action bar"],
- handler = self:GetModule("HideBlizzard"),
- get = "IsHidden",
- set = "SetHidden",
- disabled = "OptionDisabled",
+ get = "OptionGetHideBlizzardVehicleBar",
+ set = "OptionSetHideBlizzardVehicleBar",
+ disabled = function() return InCombatLockdown() or ReAction:OptionGetHideBlizzardBars() == false end,
width = "full",
order = 4,
},
@@ -101,10 +99,6 @@
AceConfigDialog:AddToBlizOptions(configID, options.args.profiles.name, configID, "profiles")
- self.db.RegisterCallback(self,"OnProfileChanged")
- self.db.RegisterCallback(self,"OnProfileReset", "OnProfileChanged")
- self.db.RegisterCallback(self,"OnProfileCopied","OnProfileChanged")
-
SlashCmdList["REACTION"] = function(option)
option = string.match(option or "", "^%s*(%S+)")
if option == "config" or option == "options" then
@@ -139,6 +133,14 @@
showAlert = true,
whileDead = true,
}
+
+ -- reroute blizzard action bar config to ReAction config window
+ InterfaceOptionsActionBarsPanel:HookScript("OnShow",
+ function()
+ if ReAction:OptionGetHideBlizzardBars() then
+ ReAction:ShowOptions()
+ end
+ end )
end
@@ -147,14 +149,6 @@
end
-function ReAction:OnProfileChanged()
- self:RebuildAll()
- if not self.db.global.skipKeybindWarning then
- StaticPopup_Show("REACTION_KB_WARN")
- end
-end
-
-
function ReAction:OptionSetConfigMode(info, value)
self:SetConfigMode(value)
end
@@ -181,6 +175,25 @@
end
+function ReAction:OptionSetHideBlizzardBars( info, hide )
+ self.db.profile.options.hideBlizzardBars = hide
+ self:ManageBlizzardBars()
+end
+
+function ReAction:OptionGetHideBlizzardBars()
+ return self.db.profile.options.hideBlizzardBars
+end
+
+function ReAction:OptionSetHideBlizzardVehicleBar( info, hide )
+ self.db.profile.options.hideBlizzardVehicleBar = hide
+ self:ManageBlizzardBars()
+end
+
+function ReAction:OptionGetHideBlizzardVehicleBar()
+ return self.db.profile.options.hideBlizzardVehicleBar
+end
+
+
-- export to LDB
local LDB = LibStub:GetLibrary("LibDataBroker-1.1")
if LDB then
diff -r b2b105747466 -r 920d17851a93 Overlay.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Overlay.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,754 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local LKB = ReAction.LKB
+local CreateFrame = CreateFrame
+local InCombatLockdown = InCombatLockdown
+local floor = math.floor
+local min = math.min
+local format = string.format
+local GameTooltip = GameTooltip
+local Bar = ReAction.Bar
+local GetSize = Bar.GetSize
+local SetSize = Bar.SetSize
+local GetButtonSize = Bar.GetButtonSize
+local GetButtonGrid = Bar.GetButtonGrid
+local SetButtonSize = Bar.SetButtonSize
+local SetButtonGrid = Bar.SetButtonGrid
+local ApplyAnchor = Bar.ApplyAnchor
+local GameTooltipTextRight1 = GameTooltipTextRight1
+local GameTooltipTextRight2 = GameTooltipTextRight2
+local GameTooltipTextRight3 = GameTooltipTextRight3
+
+--
+-- Wrap some of the bar manipulators to make them state-aware
+--
+local function SetAnchor( bar, point, frame, relPoint, x, y )
+ local state = bar:GetSecureState()
+ if state then
+ local anchorstate = bar:GetStateProperty(state, "anchorEnable")
+ if anchorstate then
+ bar:SetStateProperty(state, "anchorFrame", frame)
+ bar:SetStateProperty(state, "anchorPoint", point)
+ bar:SetStateProperty(state, "anchorRelPoint", relPoint)
+ bar:SetStateProperty(state, "anchorX", x or 0)
+ bar:SetStateProperty(state, "anchorY", y or 0)
+ bar:SetAnchor(bar:GetAnchor())
+ return
+ end
+ end
+ bar:SetAnchor(point, frame, relPoint, x, y)
+end
+
+local function GetStateScale( bar )
+ local state = bar:GetSecureState()
+ if state and bar:GetStateProperty(state, "enableScale") then
+ return bar:GetStateProperty(state, "scale")
+ end
+end
+
+local function SetStateScale( bar, scale )
+ local state = bar:GetSecureState()
+ if state and bar:GetStateProperty(state, "enableScale") then
+ bar:SetStateProperty(state, "scale", scale)
+ end
+end
+
+
+--
+-- Bar config overlay
+--
+
+local function GetNormalTextColor()
+ return 1.0, 1.0, 1.0, 1.0
+end
+
+local function GetAnchoredTextColor()
+ return 1.0, 1.0, 1.0, 1.0
+end
+
+local function GetNormalBgColor()
+ return 0.7, 0.7, 1.0, 0.3
+end
+
+local function GetAnchoredBgColor()
+ return 0.9, 0.2, 0.7, 0.3
+end
+
+local function StoreSize(bar)
+ local f = bar:GetFrame()
+ SetSize( bar, f:GetWidth(), f:GetHeight() )
+end
+
+local function StoreExtents(bar)
+ local f = bar:GetFrame()
+ local p, fr, rp, x, y = f:GetPoint(1)
+ fr = fr and fr:GetName() or "UIParent"
+ SetAnchor( bar, p, fr, rp, x, y )
+ SetSize( bar, f:GetWidth(), f:GetHeight() )
+end
+
+local function RecomputeButtonSize(bar)
+ local w, h = GetSize(bar)
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+
+ local scaleW = (floor(w/c) - s) / bw
+ local scaleH = (floor(h/r) - s) / bh
+ local scale = min(scaleW, scaleH)
+
+ SetButtonSize(bar, scale * bw, scale * bh, s)
+end
+
+local function ComputeBarScale(bar, overlay)
+ local w, h = overlay:GetWidth() - 8, overlay:GetHeight() - 8
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+
+ local scaleW = w / (c*(bw+s))
+ local scaleH = h / (r*(bh+s))
+ local scale = min(scaleW, scaleH)
+
+ if scale > 2.5 then
+ scale = 2.5
+ elseif scale < 0.25 then
+ scale = 0.25
+ end
+
+ return scale
+end
+
+local function RecomputeButtonSpacing(bar)
+ local w, h = GetSize(bar)
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+
+ SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
+end
+
+local function RecomputeGrid(bar)
+ local w, h = GetSize(bar)
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+
+ SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
+end
+
+local function ClampToButtons(bar)
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+ SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1)
+end
+
+local function HideGameTooltip()
+ GameTooltip:Hide()
+end
+
+local anchorInside = { inside = true }
+local anchorOutside = { outside = true }
+local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" }
+local oppositeEdges = {
+ TOP = "BOTTOM",
+ BOTTOM = "TOP",
+ LEFT = "RIGHT",
+ RIGHT = "LEFT"
+}
+local pointsOnEdge = {
+ BOTTOM = { "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", },
+ TOP = { "TOP", "TOPLEFT", "TOPRIGHT", },
+ RIGHT = { "RIGHT", "BOTTOMRIGHT", "TOPRIGHT", },
+ LEFT = { "LEFT", "BOTTOMLEFT", "TOPLEFT", },
+}
+local edgeSelector = {
+ BOTTOM = 1, -- select x of x,y
+ TOP = 1, -- select x of x,y
+ LEFT = 2, -- select y of x,y
+ RIGHT = 2, -- select y of x,y
+}
+local snapPoints = {
+ [anchorOutside] = {
+ BOTTOMLEFT = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"},
+ BOTTOM = {"TOP"},
+ BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"},
+ RIGHT = {"LEFT"},
+ TOPRIGHT = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"},
+ TOP = {"BOTTOM"},
+ TOPLEFT = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"},
+ LEFT = {"RIGHT"},
+ CENTER = {"CENTER"}
+ },
+ [anchorInside] = {
+ BOTTOMLEFT = {"BOTTOMLEFT"},
+ BOTTOM = {"BOTTOM"},
+ BOTTOMRIGHT = {"BOTTOMRIGHT"},
+ RIGHT = {"RIGHT"},
+ TOPRIGHT = {"TOPRIGHT"},
+ TOP = {"TOP"},
+ TOPLEFT = {"TOPLEFT"},
+ LEFT = {"LEFT"},
+ CENTER = {"CENTER"}
+ }
+}
+local insidePointOffsetFuncs = {
+ BOTTOMLEFT = function(x, y) return x, y end,
+ BOTTOM = function(x, y) return 0, y end,
+ BOTTOMRIGHT = function(x, y) return -x, y end,
+ RIGHT = function(x, y) return -x, 0 end,
+ TOPRIGHT = function(x, y) return -x, -y end,
+ TOP = function(x, y) return 0, -y end,
+ TOPLEFT = function(x, y) return x, -y end,
+ LEFT = function(x, y) return x, 0 end,
+ CENTER = function(x, y) return x, y end,
+}
+local pointCoordFuncs = {
+ BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end,
+ BOTTOM = function(f) return nil, f:GetBottom() end,
+ BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
+ RIGHT = function(f) return f:GetRight(), nil end,
+ TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end,
+ TOP = function(f) return nil, f:GetTop() end,
+ TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end,
+ LEFT = function(f) return f:GetLeft(), nil end,
+ CENTER = function(f) return f:GetCenter() end,
+}
+local edgeBoundsFuncs = {
+ BOTTOM = function(f) return f:GetLeft(), f:GetRight() end,
+ LEFT = function(f) return f:GetBottom(), f:GetTop() end
+}
+edgeBoundsFuncs.TOP = edgeBoundsFuncs.BOTTOM
+edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT
+local cornerTexCoords = {
+ -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
+ TOPLEFT = { 1, 1, 1, 0, 0, 1, 0, 0 },
+ TOPRIGHT = { 1, 0, 0, 0, 1, 1, 0, 1 },
+ BOTTOMLEFT = { 0, 1, 1, 1, 0, 0, 1, 0 },
+ BOTTOMRIGHT = { 0, 0, 0, 1, 1, 0, 1, 1 },
+}
+
+-- Returns absolute coordinates x,y of the named point 'p' of frame 'f'
+local function GetPointCoords( f, p )
+ local x, y = pointCoordFuncs[p](f)
+ if not(x and y) then
+ local cx, cy = f:GetCenter()
+ x = x or cx
+ y = y or cy
+ end
+ return x, y
+end
+
+
+-- Returns true if frame 'f1' can be anchored to frame 'f2'
+local function CheckAnchorable( f1, f2 )
+ -- can't anchor a frame to itself or to nil
+ if f1 == f2 or f2 == nil then
+ return false
+ end
+
+ -- can always anchor to UIParent
+ if f2 == UIParent then
+ return true
+ end
+
+ -- also can't do circular anchoring of frames
+ -- walk the anchor chain, which generally shouldn't be that expensive
+ -- (who nests draggables that deep anyway?)
+ for i = 1, f2:GetNumPoints() do
+ local _, f = f2:GetPoint(i)
+ if not f then f = f2:GetParent() end
+ return CheckAnchorable(f1,f)
+ end
+
+ return true
+end
+
+-- Returns true if frames f1 and f2 specified edges overlap
+local function CheckEdgeOverlap( f1, f2, e )
+ local l1, u1 = edgeBoundsFuncs[e](f1)
+ local l2, u2 = edgeBoundsFuncs[e](f2)
+ return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2
+end
+
+-- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2
+local function CheckPointEdgeOverlap( f1, p1, f2, e2 )
+ local l, u = edgeBoundsFuncs[e2](f2)
+ local x, y = GetPointCoords(f1,p1)
+ x = select(edgeSelector[e2], x, y)
+ return l <= x and x <= u
+end
+
+-- Returns the distance between corresponding edges. It is
+-- assumed that the passed in edges e1 and e2 are the same or opposites
+local function GetEdgeDistance( f1, f2, e1, e2 )
+ local x1, y1 = pointCoordFuncs[e1](f1)
+ local x2, y2 = pointCoordFuncs[e2](f2)
+ return math.abs((x1 or y1) - (x2 or y2))
+end
+
+local globalSnapTargets = { [UIParent] = anchorInside }
+
+local function GetClosestFrameEdge(f1,f2,a)
+ local dist, edge, opp
+ if f2:IsVisible() and CheckAnchorable(f1,f2) then
+ for _, e in pairs(edges) do
+ local o = a.inside and e or oppositeEdges[e]
+ if CheckEdgeOverlap(f1,f2,e) then
+ local d = GetEdgeDistance(f1, f2, e, o)
+ if not dist or (d < dist) then
+ dist, edge, opp = d, e, o
+ end
+ end
+ end
+ end
+ return dist, edge, opp
+end
+
+local function GetClosestVisibleEdge( f )
+ local r, o, e1, e2
+ local a = anchorOutside
+ for _, b in ReAction:IterateBars() do
+ local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a)
+ if d and (not r or d < r) then
+ r, o, e1, e2 = d, b:GetFrame(), e, opp
+ end
+ end
+ for f2, a2 in pairs(globalSnapTargets) do
+ local d, e, opp = GetClosestFrameEdge(f,f2,a2)
+ if d and (not r or d < r) then
+ r, o, e1, e2, a = d, f2, e, opp, a2
+ end
+ end
+ return o, e1, e2, a
+end
+
+local function GetClosestVisiblePoint(f1)
+ local f2, e1, e2, a = GetClosestVisibleEdge(f1)
+ if f2 then
+ local rsq, p, rp, x, y
+ -- iterate pointsOnEdge in order and use < to prefer edge centers to corners
+ for _, p1 in ipairs(pointsOnEdge[e1]) do
+ if CheckPointEdgeOverlap(f1,p1,f2,e2) then
+ for _, p2 in pairs(snapPoints[a][p1]) do
+ local x1, y1 = GetPointCoords(f1,p1)
+ local x2, y2 = GetPointCoords(f2,p2)
+ local dx = x1 - x2
+ local dy = y1 - y2
+ local rsq2 = dx*dx + dy*dy
+ if not rsq or rsq2 < rsq then
+ rsq, p, rp, x, y = rsq2, p1, p2, dx, dy
+ end
+ end
+ end
+ end
+ return f2, p, rp, x, y
+ end
+end
+
+local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff)
+ local o, p, rp, x, y = GetClosestVisiblePoint(f1)
+ local s = false
+
+ local insideOffsetFunc = p and insidePointOffsetFuncs[p]
+ local coordFunc = p and pointCoordFuncs[p]
+ if not insideOffsetFunc or not coordFunc then
+ return
+ end
+
+ local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0)
+ local xx, yy = coordFunc(f1)
+ if xx and yy then
+ if math.abs(x) <= rx then
+ if math.abs(y) <= ry then
+ x = sx
+ y = sy
+ s = true
+ elseif CheckEdgeOverlap(f1,o,"LEFT") then
+ x = sx
+ s = true
+ end
+ elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then
+ y = sy
+ s = true
+ end
+ elseif xx then
+ if math.abs(x) <= rx then
+ x = sx
+ s = true
+ if math.abs(y) <= ry then
+ y = sy
+ end
+ end
+ elseif yy then
+ if math.abs(y) <= ry then
+ y = sy
+ s = true
+ if math.abs(x) <= rx then
+ x = sx
+ end
+ end
+ end
+
+ -- correct for some Lua oddities with doubles
+ if x == -0 then x = 0 end
+ if y == -0 then y = 0 end
+
+ if s then
+ return o, p, rp, math.floor(x), math.floor(y)
+ end
+end
+
+local function CreateSnapIndicator()
+ local si = CreateFrame("Frame",nil,UIParent)
+ si:SetFrameStrata("HIGH")
+ si:SetHeight(16)
+ si:SetWidth(16)
+ local tex = si:CreateTexture()
+ tex:SetAllPoints()
+ tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
+ tex:SetBlendMode("ADD")
+ tex:SetDrawLayer("OVERLAY")
+ return si
+end
+
+local si1 = CreateSnapIndicator()
+local si2 = CreateSnapIndicator()
+
+local function DisplaySnapIndicator( f, rx, ry, xOff, yOff )
+ local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff)
+ if o then
+ si1:ClearAllPoints()
+ si2:ClearAllPoints()
+ si1:SetPoint("CENTER", f, p, 0, 0)
+ local xx, yy = pointCoordFuncs[rp](o)
+ x = math.abs(x) <=rx and xx and 0 or x
+ y = math.abs(y) <=ry and yy and 0 or y
+ si2:SetPoint("CENTER", o, rp, x, y)
+ si1:Show()
+ si2:Show()
+ else
+ if si1:IsVisible() then
+ si1:Hide()
+ si2:Hide()
+ end
+ end
+ return o, p
+end
+
+local function HideSnapIndicator()
+ if si1:IsVisible() then
+ si1:Hide()
+ si2:Hide()
+ end
+end
+
+local function UpdateLabelString(overlay)
+ local label = overlay.labelString
+ if label then
+ local name = overlay.labelName
+ if name and overlay.labelSubtext then
+ name = format("%s (%s)", name, overlay.labelSubtext)
+ end
+ label:SetText(name or "")
+ end
+end
+
+local function CreateControls(bar)
+ local f = bar:GetFrame()
+
+ f:SetMovable(true)
+ f:SetResizable(true)
+
+ -- child of UIParent so that alpha and scale doesn't propagate to it
+ local overlay = CreateFrame("Button", nil, UIParent)
+ overlay:EnableMouse(true)
+ overlay:SetFrameLevel(10) -- set it above the buttons
+ overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4)
+ overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4)
+ overlay:SetBackdrop({
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ tile = true,
+ tileSize = 16,
+ edgeSize = 16,
+ insets = { left = 0, right = 0, top = 0, bottom = 0 },
+ })
+
+ -- textures
+ local bgTex = overlay:CreateTexture(nil,"BACKGROUND")
+ bgTex:SetTexture(0.7,0.7,1.0,0.2)
+ bgTex:SetPoint("TOPLEFT",4,-4)
+ bgTex:SetPoint("BOTTOMRIGHT",-4,4)
+ local hTex = overlay:CreateTexture(nil,"HIGHLIGHT")
+ hTex:SetTexture(0.7,0.7,1.0,0.2)
+ hTex:SetPoint("TOPLEFT",4,-4)
+ hTex:SetPoint("BOTTOMRIGHT",-4,4)
+ hTex:SetBlendMode("ADD")
+ local aTex = overlay:CreateTexture(nil,"ARTWORK")
+ aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
+ aTex:SetWidth(16)
+ aTex:SetHeight(16)
+ aTex:Hide()
+
+ -- label
+ local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+ label:SetAllPoints()
+ label:SetJustifyH("CENTER")
+ label:SetShadowColor(0,0,0,1)
+ label:SetShadowOffset(3,-3)
+ label:SetTextColor(GetNormalTextColor())
+ label:SetText(bar:GetName())
+ label:Show()
+ overlay.labelString = label
+ overlay.labelName = bar:GetName()
+
+ local function UpdateAnchorDecoration()
+ local point, anchor, relPoint, x, y = f:GetPoint(1)
+ if point then
+ local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
+ if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then
+ bgTex:SetTexture( GetAnchoredBgColor() )
+ hTex:SetTexture( GetAnchoredBgColor() )
+ label:SetTextColor( GetAnchoredTextColor() )
+ aTex:ClearAllPoints()
+ aTex:SetPoint(point)
+ aTex:Show()
+ return
+ end
+ end
+ bgTex:SetTexture( GetNormalBgColor() )
+ hTex:SetTexture( GetNormalBgColor() )
+ label:SetTextColor( GetNormalTextColor() )
+ aTex:Hide()
+ end
+
+ local function StopResize()
+ f:StopMovingOrSizing()
+ f.isMoving = false
+ f:SetScript("OnUpdate",nil)
+ StoreSize(bar)
+ ClampToButtons(bar)
+ ReAction:RefreshEditor()
+ end
+
+ local function CornerUpdate()
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = GetButtonGrid(bar)
+ local ss = GetStateScale(bar)
+ if IsShiftKeyDown() then
+ if ss then
+ f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss )
+ f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss )
+ scale = ComputeBarScale(bar, overlay)
+ else
+ f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
+ f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 )
+ RecomputeButtonSize(bar)
+ end
+ elseif not ss and IsAltKeyDown() then
+ f:SetMinResize( bw*c, bh*r )
+ f:SetMaxResize( 2*bw*c, 2*bh*r )
+ RecomputeButtonSpacing(bar)
+ else
+ f:SetMinResize( bw+s+1, bh+s+1 )
+ f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 )
+ RecomputeGrid(bar)
+ end
+ GameTooltipTextRight2:SetText(format("%d x %d",r,c))
+
+ local ss = GetStateScale(bar)
+ if ss then
+ GameTooltipTextRight4:SetText(format("%d%%", scale*100))
+ else
+ local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
+ GameTooltipTextRight3:SetText(size)
+ GameTooltipTextRight4:SetText(tostring(s))
+ end
+ end
+
+ -- corner drag handles
+ for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
+ local corner = CreateFrame("Frame",nil,overlay)
+ corner:EnableMouse(true)
+ corner:SetWidth(16)
+ corner:SetHeight(16)
+ corner:SetPoint(point)
+
+ local tex = corner:CreateTexture(nil,"HIGHLIGHT")
+ tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner")
+ tex:SetTexCoord(unpack(cornerTexCoords[point]))
+ tex:SetBlendMode("ADD")
+ tex:SetAlpha(0.6)
+ tex:SetAllPoints()
+
+ corner:SetScript("OnMouseDown",
+ function(_,btn)
+ f:SetScript("OnUpdate", CornerUpdate)
+ f:StartSizing(point)
+ end
+ )
+ corner:SetScript("OnMouseUp",
+ function()
+ local ss = GetStateScale(bar)
+ if ss then
+ SetStateScale(bar, ComputeBarScale(bar, overlay))
+ end
+ StopResize()
+ end)
+ corner:SetScript("OnEnter",
+ function()
+ local bw, bh = GetButtonSize(bar)
+ local r, c, s = bar:GetButtonGrid()
+ local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
+ local ss = GetStateScale(bar)
+ local state = bar:GetSecureState()
+ GameTooltip:SetOwner(f, "ANCHOR_"..point)
+ if ss then
+ GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
+ else
+ GameTooltip:AddLine(bar:GetName())
+ end
+ GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c))
+ if ss then
+ GameTooltip:AddLine(L["State Scale Override"])
+ GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100))
+ else
+ GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size)))
+ GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"], L["to change spacing:"]), tostring(floor(s)))
+ end
+ GameTooltip:Show()
+ end
+ )
+ corner:SetScript("OnLeave",
+ function()
+ GameTooltip:Hide()
+ f:SetScript("OnUpdate",nil)
+ end
+ )
+ end
+
+ overlay:RegisterForDrag("LeftButton")
+ overlay:RegisterForClicks("RightButtonUp")
+
+ overlay:SetScript("OnDragStart",
+ function()
+ f:StartMoving()
+ f.isMoving = true
+ local w,h = bar:GetButtonSize()
+ f:ClearAllPoints()
+ UpdateAnchorDecoration()
+ f:SetScript("OnUpdate", function()
+ if IsShiftKeyDown() then
+ local f, p = DisplaySnapIndicator(f,w,h)
+ else
+ HideSnapIndicator()
+ end
+ end)
+ end
+ )
+
+ local function UpdateDragTooltip()
+ GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
+ local ss = GetStateScale(bar)
+ local state = bar:GetSecureState()
+ if ss then
+ GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
+ else
+ GameTooltip:AddLine(bar:GetName())
+ end
+ GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"]))
+ GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"]))
+ GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."]))
+ local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1)
+ if point then
+ local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
+ if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then
+ frame = frame or UIParent
+ GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName()))
+ end
+ end
+ GameTooltip:Show()
+ end
+
+ overlay:SetScript("OnDragStop",
+ function()
+ f:StopMovingOrSizing()
+ f.isMoving = false
+ f:SetScript("OnUpdate",nil)
+
+ if IsShiftKeyDown() then
+ local w, h = bar:GetButtonSize()
+ local a, p, rp, x, y = GetClosestPointSnapped(f,w,h)
+ if a then
+ f:ClearAllPoints()
+ f:SetPoint(p,a,rp,x,y)
+ end
+ HideSnapIndicator()
+ end
+
+ StoreExtents(bar)
+ ReAction:RefreshEditor()
+ UpdateDragTooltip()
+ UpdateAnchorDecoration()
+ end
+ )
+
+ overlay:SetScript("OnEnter",
+ function()
+ UpdateDragTooltip()
+ end
+ )
+
+ overlay:SetScript("OnLeave", HideGameTooltip)
+
+ overlay:SetScript("OnClick",
+ function()
+ ReAction:ShowEditor(bar)
+ end
+ )
+
+ function overlay:RefreshControls()
+ UpdateAnchorDecoration()
+ end
+
+ overlay:SetScript("OnShow", overlay.RefreshControls)
+
+ if ReAction:GetKeybindMode() then
+ overlay:SetFrameLevel(1)
+ end
+
+ UpdateLabelString(overlay)
+ UpdateAnchorDecoration()
+
+ return overlay
+end
+
+
+-- export methods to the Bar prototype
+Bar.Overlay = { }
+function Bar.Overlay:New( bar )
+ return setmetatable( {frame = CreateControls(bar)}, {__index=self} )
+end
+
+function Bar.Overlay:SetLabel(name)
+ self.frame.labelName = name
+ UpdateLabelString(self.frame)
+end
+
+function Bar.Overlay:SetLabelSubtext(text)
+ self.frame.labelSubtext = text
+ UpdateLabelString(self.frame)
+end
+
+function Bar.Overlay:Show()
+ self.frame:Show()
+end
+
+function Bar.Overlay:Hide()
+ self.frame:Hide()
+end
+
+function Bar.Overlay:IsShown()
+ return self.frame:IsShown()
+end
+
+function Bar.Overlay:RefreshControls()
+ self.frame:RefreshControls()
+end
\ No newline at end of file
diff -r b2b105747466 -r 920d17851a93 PetActionButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/PetActionButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,324 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local InCombatLockdown = InCombatLockdown
+local GetPetActionInfo = GetPetActionInfo
+local GetPetActionSlotUsable = GetPetActionSlotUsable
+local GetPetActionCooldown = GetPetActionCooldown
+local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
+local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
+local SetDesaturation = SetDesaturation
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+
+--
+-- Secure snippets
+-- These are run within the context of the bar's sandbox, as the
+-- buttons themselves do not have their own sandbox.
+--
+local _onDragStart = -- function(self, button, kind, value, ...)
+[[
+ if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
+ return kind, value, ...
+ else
+ return "petaction", self:GetAttribute("action")
+ end
+]]
+
+local _onReceiveDrag = -- function(self, button, kind, value, ...)
+[[
+ if kind then -- pet spells on the cursor return nil from GetCursorInfo(), which is very strange
+ return kind, value, ...
+ end
+ return "petaction", self:GetAttribute("action")
+]]
+
+--
+-- private
+--
+local eventList = {
+"PLAYER_CONTROL_LOST",
+"PLAYER_CONTROL_GAINED",
+"PLAYER_FARSIGHT_FOCUS_CHANGED",
+"UNIT_PET",
+"UNIT_FLAGS",
+"UNIT_AURA",
+"PET_BAR_UPDATE",
+"PET_BAR_UPDATE_COOLDOWN",
+"PET_BAR_UPDATE_USABLE",
+"UPDATE_BINDINGS",
+}
+
+--
+-- Pet Action Button class
+--
+local buttonTypeID = "PetAction"
+local Super = ReAction.Button
+local Pet = setmetatable(
+ {
+ defaultBarConfig = {
+ type = buttonTypeID,
+ btnWidth = 30,
+ btnHeight = 30,
+ btnRows = 1,
+ btnColumns = 10,
+ spacing = 8,
+ buttons = { }
+ },
+
+ barType = L["Pet Action Bar"],
+ buttonTypeID = buttonTypeID
+ },
+ { __index = Super } )
+
+ReAction.Button.PetAction = Pet
+ReAction:RegisterBarType(Pet)
+
+function Pet:New( config, bar, idx, idHint )
+ local name = format("ReAction_%s_PetAction_%d",bar:GetName(),idx)
+
+ self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+ local f = self:GetFrame()
+ if not f.autoCastTexture then
+ -- store autocast stuff with the frame for recycling
+ local tex = f:CreateTexture(nil,"OVERLAY")
+ tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]])
+ tex:SetHeight(58)
+ tex:SetWidth(58)
+ tex:SetPoint("CENTER")
+ f.autoCastTexture = tex
+ f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") -- create after autocast texture so it's on top
+ -- move the cooldown around
+ local cd = self.frames.cooldown
+ cd:ClearAllPoints()
+ cd:SetWidth(33)
+ cd:SetHeight(33)
+ cd:SetPoint("CENTER", f, "CENTER", -2, -1)
+ -- resize to 30x30
+ f:SetHeight(30)
+ f:SetWidth(30)
+ local nt = _G[name.."NormalTexture"]
+ nt:SetHeight(54)
+ nt:SetWidth(54)
+ end
+ local barFrame = bar:GetFrame()
+
+ -- set up the base action ID
+ self:SetActionIDPool("pet",10)
+ config.actionID = self:AcquireActionID(config.actionID, idHint, true)
+
+ -- attribute setup
+ -- There's no secure way to do PetAutoCastToggle by actionID, so use
+ -- a click-through proxy to the Blizzard pet buttons for right-click
+ -- Note that technically this doesn't do PetStopAttack() when
+ -- IsPetAttackActive() is true: however that's only true when using
+ -- Eyes of the Beast and appears not to really do anything (at least
+ -- I can't find any difference)
+ f:SetAttribute("type","pet")
+ f:SetAttribute("type2","click")
+ f:SetAttribute("clickbutton2",_G["PetActionButton"..config.actionID])
+ f:SetAttribute("action",config.actionID)
+ f:SetAttribute("checkselfcast", true)
+ f:SetAttribute("checkfocuscast", true)
+
+ -- non secure scripts
+ f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+ f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+ f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+ f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+ f:SetScript("PreClick", function(frame) self:PreClick() end)
+ f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
+ f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
+
+ -- secure handlers
+ barFrame:WrapScript(f, "OnDragStart", _onDragStart)
+ barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForDrag("LeftButton", "RightButton")
+ f:RegisterForClicks("AnyUp")
+ for _, evt in pairs(eventList) do
+ f:RegisterEvent(evt)
+ end
+
+ -- attach to skinner
+ bar:SkinButton(self,
+ {
+ AutoCast = f.autoCastShine,
+ AutoCastable = f.autoCastTexture
+ })
+
+ self:Refresh()
+ f:Show()
+
+ return self
+end
+
+function Pet:SetupBar(bar)
+ Super.SetupBar(self,bar)
+
+ -- auto show/hide when pet exists
+ bar:RegisterUnitWatch("pet",true)
+
+ self:UpdateButtonLock(bar)
+end
+
+function Pet:UpdateButtonLock(bar)
+ local f = bar:GetFrame()
+ f:SetAttribute("lockbuttons",bar.config.lockButtons)
+ f:SetAttribute("lockbuttonscombat",bar.config.lockButtonsCombat)
+ f:Execute(
+ [[
+ lockButtons = self:GetAttribute("lockbuttons")
+ lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+ ]])
+end
+
+function Pet:Refresh()
+ Super.Refresh(self)
+ self:Update()
+ self:UpdateHotkey()
+end
+
+function Pet:GetActionID()
+ return self.config.actionID
+end
+
+function Pet:SetActionID(id)
+ if not InCombatLockdown() then
+ if id < 0 or id > 10 then
+ ReAction:UserError(L["Pet action ID range is 1-10"])
+ return
+ end
+ self.config.actionID = id
+ f:SetAttribute("clickbutton2",_G["PetActionButton"..id])
+ f:SetAttribute("action",id)
+ self:Update()
+ self:UpdateHotkey()
+ end
+end
+
+function Pet:Update()
+ local action = self.config.actionID
+ local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(action)
+ local f = self:GetFrame()
+ local icon = self.frames.icon
+
+ if isToken then
+ icon:SetTexture(_G[texture])
+ self.tooltipName = _G[name]
+ else
+ icon:SetTexture(texture)
+ self.tooltipName = name
+ end
+
+ self.isToken = isToken
+ self.tooltipSubtext = subtext
+ f:SetChecked( isActive and 1 or 0 )
+
+ if autoCastAllowed then
+ f.autoCastTexture:Show()
+ else
+ f.autoCastTexture:Hide()
+ end
+
+ if autoCastEnabled then
+ AutoCastShine_AutoCastStart(f.autoCastShine)
+ else
+ AutoCastShine_AutoCastStop(f.autoCastShine)
+ end
+
+ if texture then
+ if GetPetActionSlotUsable(action) then
+ SetDesaturation(icon,nil)
+ else
+ SetDesaturation(icon,1)
+ end
+ icon:Show()
+ f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+ else
+ icon:Hide()
+ f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+ end
+
+ self:UpdateCooldown()
+end
+
+function Pet:UpdateCooldown()
+ CooldownFrame_SetTimer(self.frames.cooldown, GetPetActionCooldown(self.config.actionID))
+end
+
+function Pet:SetTooltip()
+ if self.tooltipName then
+ local f = self:GetFrame()
+ local uber = GetCVar("UberTooltips")
+ if self.isToken or (uber == "0") then
+ if uber == "0" then
+ GameTooltip:SetOwner(f, "ANCHOR_RIGHT")
+ else
+ GameTooltip_SetDefaultAnchor(GameTooltip, f)
+ end
+ GameTooltip:SetText(self.tooltipName)
+ if self.tooltipSubtext then
+ GameTooltip:AddLine(self.tooltipSubtext, "", 0.5, 0.5, 0.5)
+ end
+ GameTooltip:Show()
+ else
+ GameTooltip_SetDefaultAnchor(GameTooltip, f)
+ GameTooltip:SetPetAction(self.config.actionID)
+ end
+ else
+ GameTooltip:Hide()
+ end
+end
+
+function Pet:OnEvent(event, unit)
+ if event =="PET_BAR_UPDATE_COOLDOWN" then
+ self:UpdateCooldown()
+ elseif event == "UPDATE_BINDINGS" then
+ self:UpdateHotkey()
+ elseif event == "UNIT_PET" then
+ if unit == "player" then
+ self:Update()
+ end
+ elseif event == "UNIT_FLAGS" or event == "UNIT_AURA" then
+ if unit == "pet" then
+ self:Update()
+ end
+ else
+ self:Update()
+ end
+end
+
+function Pet:OnEnter()
+ self:SetTooltip()
+end
+
+function Pet:OnLeave()
+ GameTooltip:Hide()
+end
+
+function Pet:OnAttributeChanged(attr,value)
+ self:Update()
+end
+
+function Pet:PreClick()
+ self:GetFrame():SetChecked(0)
+end
+
+function Pet:OnDragStart()
+ self:SetChecked(0)
+ self:Update()
+end
+
+function Pet:OnReceiveDrag()
+ self:SetChecked(0)
+ self:Update()
+end
+
diff -r b2b105747466 -r 920d17851a93 Profile.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Profile.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,157 @@
+local _, addonTable = ...
+local ReAction = addonTable.ReAction
+
+ReAction.PROFILEVERSION_LATEST = 2
+
+ReAction.defaultProfile = {
+ profile = {
+ dbversion = nil,
+ bars = { },
+ options = {
+ hideBlizzardBars = false,
+ hideBlizzardVehicleBar = false,
+ },
+ },
+ global = {
+ skipKeybindWarning = false,
+ }
+}
+
+function ReAction:UpgradeProfile()
+ local db = self.db
+
+ if not db.profile.dbversion then
+ -- upgrade from legacy db to v1
+
+ -- (1) remove unused defaultBars table (cleanup)
+ db.profile.defaultBars = nil
+
+ -- (2) HideBlizzard is no longer a module
+ local hb = db:GetNamespace("HideBlizzard",true) or db:RegisterNamespace("HideBlizzard")
+ if hb then
+ db.profile.options.hideBlizzardBars = hb.profile.hide
+ db.profile.options.hideBlizzardVehicleBar = hb.profile.hideVehicle
+ hb:ResetProfile()
+ end
+
+ -- (3) LBF is no longer a module
+ local bf = db:GetNamespace("ButtonFacade",true) or db:RegisterNamespace("ButtonFacade")
+ if bf then
+ for name, bar in pairs(db.profile.bars) do
+ bar.ButtonFacade = bf.profile[name] or bar.ButtonFacade
+ end
+ bf:ResetProfile()
+ end
+
+ -- (4) Action module uses the bar config directly
+ local action = db:GetNamespace("Action",true) or db:RegisterNamespace("Action")
+ if action then
+ for name, bar in pairs(db.profile.bars) do
+ local ac = action.profile.bars and action.profile.bars[name]
+ if ac then
+ for key, value in pairs(ac) do
+ bar[key] = value
+ end
+ end
+ end
+ action:ResetProfile()
+ end
+
+ -- (5) Bags module uses the bar config directly
+ local bag = db:GetNamespace("Bag",true) or db:RegisterNamespace("Bag")
+ if bag then
+ for name, bar in pairs(db.profile.bars) do
+ local bc = bag.profile.buttons and bag.profile.buttons[name]
+ if bc then
+ bar.buttons = bc
+ end
+ end
+ bag:ResetProfile()
+ end
+
+ -- (6) Pet module uses the bar config directly
+ local pet = db:GetNamespace("PetAction",true) or db:RegisterNamespace("PetAction")
+ if pet then
+ for name, bar in pairs(db.profile.bars) do
+ local pc = pet.profile.buttons and pet.profile.buttons[name]
+ if pc then
+ bar.buttons = pc
+ end
+ end
+ pet:ResetProfile()
+ end
+
+ -- (7) Stance module uses the bar config directly
+ local stance = db:GetNamespace("Stance",true) or db:RegisterNamespace("Stance")
+ if stance then
+ for name, bar in pairs(db.profile.bars) do
+ local sc = stance.profile.buttons and stance.profile.buttons[name]
+ if sc then
+ bar.buttons = sc
+ end
+ end
+ stance:ResetProfile()
+ end
+
+ -- (8) Totem module uses the bar config directly
+ local totem = db:GetNamespace("Totem",true) or db:RegisterNamespace("Totem")
+ if totem then
+ for name, bar in pairs(db.profile.bars) do
+ local tc = totem.profile.buttons and totem.profile.buttons[name]
+ if tc then
+ bar.buttons = tc
+ end
+ end
+ totem:ResetProfile()
+ end
+
+ -- (9) Vehicle exit button uses the bar config directly
+ local vehicle = db:GetNamespace("VehicleExit",true) or db:RegisterNamespace("VehicleExit")
+ if vehicle then
+ for name, bar in pairs(db.profile.bars) do
+ local vc = vehicle.profile.buttons and vehicle.profile.buttons[name]
+ if vc then
+ bar.buttons = vc
+ end
+ end
+ vehicle:ResetProfile()
+ end
+
+ db.profile.dbversion = 1
+ end
+
+
+ if db.profile.dbversion < 2 then
+ -- upgrade from v1 to v2
+
+ -- (10) State module uses the bar config directly
+ local state = db:GetNamespace("State",true) or db:RegisterNamespace("State")
+ if state then
+ for name, bar in pairs(db.profile.bars) do
+ local sc = state.profile.bars and state.profile.bars[name] and state.profile.bars[name].states
+ if sc then
+ bar.states = sc
+ end
+ end
+ state:ResetProfile()
+ end
+
+ db.profile.dbversion = 2
+ end
+
+ db.profile.dbversion = self.PROFILEVERSION_LATEST
+end
+
+function ReAction:OnProfileChanged()
+ self:UpgradeProfile()
+ self:RebuildAll()
+ if not self.db.global.skipKeybindWarning then
+ StaticPopup_Show("REACTION_KB_WARN") -- see Options.lua
+ end
+end
+
+function ReAction:OnNewProfile()
+ self.db.profile.dbversion = ReAction.PROFILEVERSION_LATEST
+ self:OnProfileChanged()
+end
+
diff -r b2b105747466 -r 920d17851a93 ReAction.lua
--- a/ReAction.lua Thu Nov 18 13:11:08 2010 -0800
+++ b/ReAction.lua Tue Apr 12 16:06:31 2011 -0700
@@ -3,59 +3,120 @@
local pairs = pairs
local type = type
local geterrorhandler = geterrorhandler
-local LKB = LibStub("LibKeyBound-1.0")
local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
+local LKB = LibStub("LibKeyBound-1.0",true)
+if not LKB then
+ LoadAddOn("LibKeyBound-1.0")
+ LKB = LibStub("LibKeyBound-1.0")
+end
------ Utility ------
-local tcopy
-do
- function tcopy(x)
- if type(x) ~= "table" then
- return x
- end
- local r = {}
- for k,v in pairs(x) do
- r[k] = tcopy(v)
- end
- return r
+-- make a deep copy of a table
+local function tcopy(x)
+ if type(x) ~= "table" then
+ return x
end
+ local r = {}
+ for k,v in pairs(x) do
+ r[k] = tcopy(v)
+ end
+ return r
end
+-- traverse a table tree by key list and fetch the result or first nil
+local function tfetch(t, ...)
+ for i = 1, select('#', ...) do
+ t = t and t[select(i, ...)]
+ end
+ return t
+end
+
+-- traverse a table tree by key list and build tree as necessary
+local function tbuild(t, ...)
+ for i = 1, select('#', ...) do
+ local key = select(i, ...)
+ if not t[key] then t[key] = { } end
+ t = t[key]
+ end
+ return t
+end
+
+-- return a new array of keys of table 't', sorted by comparing
+-- sub-fields (obtained via tfetch) of the table values
+local function fieldsort( t, ... )
+ local r = { }
+ for k in pairs(t) do
+ table.insert(r,k)
+ end
+ local path = { ... }
+ table.sort(r, function(lhs, rhs)
+ local olhs = tfetch(t[lhs], unpack(path)) or 0
+ local orhs = tfetch(t[rhs], unpack(path)) or 0
+ return olhs < orhs
+ end)
+ return r
+end
+
+-- store in the addon table
+addonTable.tcopy = tcopy
+addonTable.tfetch = tfetch
+addonTable.tbuild = tbuild
+addonTable.fieldsort = fieldsort
+
------ Core ------
local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction",
"AceEvent-3.0"
)
addonTable.ReAction = ReAction
-ReAction.version = "1.1"
+ReAction.version = GetAddOnMetadata("ReAction","Version")
ReAction.L = L
ReAction.LKB = LKB
+ReAction.barTypes = { }
+
------ Handlers ------
function ReAction:OnInitialize()
self.db = LibStub("AceDB-3.0"):New("ReAction_DB",
- {
- profile = {
- bars = { },
- defaultBar = { },
- }
- },
+ self.defaultProfile,
true -- use global 'Default' (locale-specific)
)
+ self:UpgradeProfile()
+
self.bars = { }
- self.defaultBarConfig = { }
+
+ self.LBF = LibStub("LibButtonFacade",true)
+ if self.LBF then
+ self.LBF:RegisterSkinCallback("ReAction", self.OnSkinChanged, self)
+ end
+
+ -- It's fairly normal to use the Blizzard vehicle bar, and to have
+ -- your regular buttons in the same location. If you do this, and don't
+ -- bother to hide your buttons, they'll obscure some parts of the vehicle bar.
+ VehicleMenuBar:SetFrameLevel(VehicleMenuBar:GetFrameLevel()+3)
self.callbacks = LibStub("CallbackHandler-1.0"):New(self)
+
LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED")
LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED")
LKB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED")
+
+ -- see Profile.lua for these callback implementations
+ self.db.RegisterCallback(self,"OnProfileChanged")
+ self.db.RegisterCallback(self,"OnProfileCopied","OnProfileChanged")
+ self.db.RegisterCallback(self,"OnNewProfile")
+ self.db.RegisterCallback(self,"OnProfileReset", "OnNewProfile")
+
self:RegisterEvent("PLAYER_REGEN_DISABLED")
+ self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
+
self:InitializeOptions()
end
function ReAction:OnEnable()
self:InitializeBars()
+ self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui
end
function ReAction:OnDisable()
@@ -71,6 +132,16 @@
end
end
+function ReAction:UPDATE_SHAPESHIFT_FORMS()
+ -- Re-parse the rules table according to the new form list.
+ -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
+ -- as well as when gaining new abilities.
+ self.Bar:InitRuleFormats()
+ for _, bar in self:IterateBars() do
+ bar:ApplyStates()
+ end
+end
+
function ReAction:LIBKEYBOUND_ENABLED( evt )
self:SetKeybindMode(true)
end
@@ -79,6 +150,24 @@
return self:SetKeybindMode(false)
end
+function ReAction:OnSkinChanged( skinID, gloss, backdrop, group, button, colors )
+ if group == nil then
+ -- don't store global
+ else
+ -- 'group' is the bar-name
+ local bar = self:GetBar(group)
+ if bar then
+ local c = bar:GetConfig().ButtonFacade
+ if c then
+ c.skinID = skinID
+ c.gloss = gloss
+ c.backdrop = backdrop
+ c.colors = colors
+ end
+ end
+ end
+end
+
------ Methods ------
@@ -110,31 +199,26 @@
function ReAction:CreateBar(name, config, ...)
local profile = self.db.profile
- if name then
- if self.bars[name] then
- self:UserError(format(L["ReAction: name '%s' already in use"],name))
- return nil
- end
- else
- local prefix = L["Bar "]
- local i = 1
- repeat
- name = prefix..i
- i = i + 1
- until self.bars[name] == nil
+ name = tostring(name)
+ if not name or name == "" then
+ error("ReAction:CreateBar() - bar name string required")
+ elseif self.bars[name] then
+ self:UserError(format(L["ReAction: name '%s' already in use"],name))
+ return nil
end
+ local class
if type(config) == "string" then
- config = self.defaultBarConfig[config]
- if not config then
- error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...))))
+ class = self.barTypes[config]
+ if not class then
+ error(("ReAction:CreateBar() - unknown bar type '%s'"):format(config))
end
- config = tcopy(config)
- config.btnRows = select(1,...) or config.btnRows or 1
- config.btnColumns = select(2,...) or config.btnColumns or 12
- config.btnWidth = select(3,...) or config.btnWidth or 36
- config.btnHeight = select(3,...) or config.btnHeight or 36
- config.spacing = select(4,...) or config.spacing or 3
+ config = tcopy(class:GetDefaultBarConfig())
+ config.btnRows = select(1,...) or config.btnRows
+ config.btnColumns = select(2,...) or config.btnColumns
+ config.btnWidth = select(3,...) or config.btnWidth
+ config.btnHeight = select(3,...) or config.btnHeight
+ config.spacing = select(4,...) or config.spacing
config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1
config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1
config.anchor = config.anchor or "UIParent"
@@ -142,11 +226,16 @@
config.relpoint = config.relpoint or "BOTTOM"
config.y = config.y or 200
config.x = config.x or 0
+ else
+ config = config or profile.bars[name] or { }
+ if not config or not config.type or not self.barTypes[config.type] then
+ error(("ReAction: Unable to construct/fetch config table for bar '%s'"):format(name))
+ end
+ class = self.barTypes[config.type]
end
- config = config or profile.bars[name] or tcopy(profile.defaultBar)
profile.bars[name] = config
- local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua
+ local bar = self.Bar:New( name, config, class ) -- ReAction.Bar defined in Bar.lua
self.bars[name] = bar
self.callbacks:Fire("OnCreateBar", bar, name)
if self.configMode then
@@ -165,24 +254,18 @@
end
end
-function ReAction:RefreshBar(x)
- local bar, name = self:GetBar(x)
- if bar and name then
- self.callbacks:Fire("OnRefreshBar", bar, name)
- end
-end
-
function ReAction:InitializeBars()
if not self.barsInitialized then
+ self:ManageBlizzardBars()
+
for name, config in pairs(self.db.profile.bars) do
if config then
self:CreateBar(name, config)
end
end
- -- re-anchor and refresh in case anchor order does not match init order
+ -- re-anchor in case anchor order does not match init order
for name, bar in pairs(self.bars) do
bar:ApplyAnchor()
- self.callbacks:Fire("OnRefreshBar", bar, name)
end
self.barsInitialized = true
end
@@ -226,35 +309,57 @@
function ReAction:EraseBar(x)
local bar, name = self:GetBar(x)
if bar and name then
- self.callbacks:Fire("OnEraseBar", bar, name)
self:DestroyBar(bar)
self.db.profile.bars[name] = nil
end
end
-function ReAction:RegisterBarType( name, config, isDefaultChoice )
- self.defaultBarConfig[name] = config
- if isDefaultChoice then
- self.defaultBarConfigChoice = name
+local blizzFrames = {
+ MainMenuBar,
+ MultiBarLeft,
+ MultiBarRight,
+ MultiBarBottomLeft,
+ MultiBarBottomRight,
+}
+
+local hideFrame = CreateFrame("Frame")
+hideFrame:Hide()
+local hiddenParents = { }
+local function ManageBlizzFrame(f, hide)
+ if hide and not hiddenParents[f] then
+ hiddenParents[f] = f:GetParent()
+ f:SetParent(hideFrame)
+ elseif not hide and hiddenParents[f] then
+ f:SetParent(hiddenParents[f])
+ hiddenParents[f] = nil
+ if f:IsShown() then
+ f:Show() -- refresh
+ end
end
- self:RefreshEditor()
end
-function ReAction:UnregisterBarType( name )
- self.defaultBarConfig[name] = nil
- if self.defaultBarConfigChoice == name then
- self.defaultBarConfigChoice = nil
+function ReAction:ManageBlizzardBars()
+ for _, f in pairs(blizzFrames) do
+ ManageBlizzFrame(f, self.db.profile.options.hideBlizzardBars)
end
- self:RefreshEditor()
+ ManageBlizzFrame(VehicleMenuBar, self.db.profile.options.hideBlizzardVehicleBar)
+end
+
+function ReAction:RegisterBarType( class, isDefault )
+ local name = class:GetButtonTypeID()
+ self.barTypes[name] = class
+ if isDefault then
+ self.defaultBarType = name
+ end
end
function ReAction:IterateBarTypes()
- return pairs(self.defaultBarConfig)
+ return pairs(self.barTypes)
end
-function ReAction:GetBarTypeConfig(name)
- if name then
- return self.defaultBarConfig[name]
+function ReAction:GetDefaultBarConfig(barType)
+ if barType and self.barTypes[barType] then
+ return self.barTypes[barType]:GetDefaultBarConfig()
end
end
@@ -267,7 +372,7 @@
end
function ReAction:GetDefaultBarType()
- return self.defaultBarConfigChoice
+ return self.defaultBarType
end
function ReAction:SetConfigMode( mode )
@@ -302,3 +407,18 @@
function ReAction:GetKeybindMode( mode )
return self.kbMode
end
+
+
+-- ConfigMode support
+CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {}
+
+function CONFIGMODE_CALLBACKS.ReAction( action, mode )
+ if action == "ON" then
+ ReAction:SetConfigMode(true)
+ elseif action == "OFF" then
+ ReAction:SetConfigMode(false)
+ elseif action == "LISTMODES" then
+ -- no modes
+ end
+end
+
diff -r b2b105747466 -r 920d17851a93 ReAction.toc
--- a/ReAction.toc Thu Nov 18 13:11:08 2010 -0800
+++ b/ReAction.toc Tue Apr 12 16:06:31 2011 -0700
@@ -4,9 +4,8 @@
## DefaultState: enabled
## LoadOnDemand: 0
## Author: Flick
-## Version: 1.1
+## Version: 1.1 beta 4
## SavedVariables: ReAction_DB
-## OptionalDeps: Ace3, LibKeyBound-1.0
## X-Embeds: Ace3, LibKeyBound-1.0
## X-Category: Action Bars
## X-License: MIT
diff -r b2b105747466 -r 920d17851a93 ReAction.xml
--- a/ReAction.xml Thu Nov 18 13:11:08 2010 -0800
+++ b/ReAction.xml Tue Apr 12 16:06:31 2011 -0700
@@ -6,10 +6,16 @@
+
+
+
+
+
+
+
+
+
+
-
-
-
-
diff -r b2b105747466 -r 920d17851a93 StanceButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/StanceButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,198 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local InCombatLockdown = InCombatLockdown
+local GetNumShapeshiftForms = GetNumShapeshiftForms
+local GetShapeshiftFormInfo = GetShapeshiftFormInfo
+local IsUsableSpell = IsUsableSpell
+local GetSpellInfo = GetSpellInfo
+
+--
+-- private
+--
+local playerClass = select(2,UnitClass("player"))
+
+local eventList = {
+ "PLAYER_REGEN_ENABLED",
+ "PLAYER_ENTERING_WORLD",
+ "UPDATE_SHAPESHIFT_FORM",
+ "UPDATE_SHAPESHIFT_FORMS",
+ "UPDATE_SHAPESHIFT_USABLE",
+ "UPDATE_SHAPESHIFT_COOLDOWN",
+ "UPDATE_BINDINGS",
+}
+
+--
+-- Stance Button class
+--
+local buttonTypeID = "Stance"
+local Super = ReAction.Button
+local Stance = setmetatable(
+ {
+ defaultConfig = {
+ type = buttonTypeID,
+ btnHeight = 36,
+ btnWidth = 36,
+ btnRows = 1,
+ btnColumns = 6,
+ spacing = 3
+ },
+
+ barType = L["Stance Bar"],
+ buttonTypeID = buttonTypeID
+ },
+ { __index = Super } )
+
+ReAction.Button.Stance = Stance
+ReAction:RegisterBarType(Stance)
+
+function Stance:New( config, bar, idx, idHint )
+ local name = format("ReAction_%s_Stance_%d",bar:GetName(),idx)
+
+ self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+ local f = self:GetFrame()
+ local barFrame = bar:GetFrame()
+ local config = self:GetConfig()
+
+ -- set up the base stance ID
+ self:SetActionIDPool("stance",8)
+ config.stanceID = self:AcquireActionID(config.stanceID, idHint, true)
+
+ -- attribute setup
+ f:SetAttribute("type","spell")
+
+ -- non secure scripts
+ f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+ f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+ f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+ f:SetScript("PreClick", function(frame, ...) self:PreClick(...) end)
+
+ -- secure handlers
+ -- (none)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForClicks("AnyUp")
+ for _, evt in pairs(eventList) do
+ f:RegisterEvent(evt)
+ end
+
+ -- attach to skinner
+ bar:SkinButton(self)
+
+ -- initial display
+ if ReAction:GetConfigMode() then
+ self:GetFrame():Show()
+ end
+
+ self:Refresh()
+
+ return self
+end
+
+function Stance:GetActionID()
+ return self.config.stanceID
+end
+
+function Stance:UpdateAction()
+ if InCombatLockdown() then
+ self.updatePending = true
+ else
+ self.updatePending = false
+ local idx = self:GetActionID()
+ local f = self:GetFrame()
+ if idx > GetNumShapeshiftForms() then
+ f:Hide()
+ else
+ f:SetAttribute("spell", select(2,GetShapeshiftFormInfo(idx)))
+ f:Show()
+ self:Update()
+ end
+ end
+end
+
+function Stance:Refresh()
+ Super.Refresh(self)
+ self:UpdateHotkey()
+ self:UpdateAction()
+end
+
+function Stance:Update()
+ local texture, _, isActive, isCastable = GetShapeshiftFormInfo(self:GetActionID())
+
+ local icon = self.frames.icon
+ icon:SetTexture(texture)
+ self:GetFrame():SetChecked( isActive and 1 or 0 )
+ if isCastable then
+ self.frames.hotkey:Show()
+ icon:SetVertexColor(1.0, 1.0, 1.0)
+ else
+ icon:SetVertexColor(0.4, 0.4, 0.4)
+ end
+
+ self:UpdateCooldown()
+end
+
+function Stance:UpdateCooldown()
+ local start, duration, enabled = GetShapeshiftFormCooldown(self:GetActionID())
+ if start then
+ CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enabled)
+ end
+end
+
+function Stance:SetTooltip()
+ if GetCVar("UberTooltips") == "1" then
+ GameTooltip_SetDefaultAnchor(GameTooltip, self:GetFrame())
+ else
+ GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT")
+ end
+ GameTooltip:SetShapeshift(self:GetActionID())
+end
+
+function Stance:OnEnter()
+ self:SetTooltip()
+end
+
+function Stance:OnLeave()
+ GameTooltip:Hide()
+end
+
+function Stance:PreClick()
+ local f = self:GetFrame()
+ f:SetChecked( not f:GetChecked() )
+end
+
+function Stance:OnEvent(event, arg)
+ if event == "PLAYER_REGEN_ENABLED" then
+ if self.updatePending then
+ self:UpdateAction()
+ end
+ elseif event == "UPDATE_SHAPESHIFT_COOLDOWN" then
+ self:UpdateCooldown()
+ elseif event == "UPDATE_SHAPESHIFT_FORMS" then
+ self:UpdateAction()
+ elseif event == "UNIT_AURA" then
+ if arg == "player" then
+ self:Update()
+ end
+ elseif event == "UPDATE_BINDINGS" then
+ self:UpdateHotkey()
+ else
+ self:Update()
+ end
+end
+
+function Stance:ShowGridTemp(show)
+ if show then
+ self:GetFrame():Show()
+ else
+ self:UpdateAction()
+ end
+end
diff -r b2b105747466 -r 920d17851a93 VehicleExitButton.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VehicleExitButton.lua Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,108 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local format = string.format
+
+--
+-- VExitButton Button class
+--
+local buttonTypeID = "VehicleExit"
+local Super = ReAction.Button
+local VExitButton = setmetatable(
+ {
+ defaultBarConfig = {
+ type = buttonTypeID ,
+ btnWidth = 36,
+ btnHeight = 36,
+ btnRows = 1,
+ btnColumns = 1,
+ spacing = 3,
+ buttons = { }
+ },
+
+ barType = L["Exit Vehicle Floater"],
+ buttonTypeID = buttonTypeID
+ },
+ { __index = Super } )
+
+ReAction.Button.VehicleExit = VExitButton
+ReAction:RegisterBarType(VExitButton)
+
+function VExitButton:New( config, bar, idx )
+ local name = format("ReAction_%s_VehicleExit_%d",bar:GetName(),idx)
+
+ self = Super.New(self, name, config, bar, idx, "SecureFrameTemplate, ActionButtonTemplate", "Button")
+
+ -- frame setup
+ local f = self:GetFrame()
+ self.frames.icon:SetTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up")
+ self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
+
+ -- attribute setup
+ -- (none)
+
+ -- non secure scripts
+ f:SetScript("OnClick", VehicleExit)
+ f:SetScript("OnEnter", function(frame) GameTooltip_AddNewbieTip(frame, LEAVE_VEHICLE, 1.0, 1.0, 1.0, nil) end)
+ f:SetScript("OnLeave", GameTooltip_Hide)
+ f:SetScript("OnEvent", function(frame, evt, ...) self:OnEvent(evt,...) end)
+
+ -- event registration
+ f:EnableMouse(true)
+ f:RegisterForClicks("AnyUp")
+ f:RegisterEvent("UPDATE_BINDINGS")
+
+ -- attach to skinner
+ bar:SkinButton(self)
+
+ self:Refresh()
+ self:UpdateHotkey()
+
+ return self
+end
+
+function VExitButton:SetupBar(bar)
+ Super.SetupBar(self,bar)
+ self:UpdateRegistration(bar)
+end
+
+function VExitButton:GetActionID()
+ return 1
+end
+
+function VExitButton:Refresh()
+ Super.Refresh(self)
+ -- it seems that setscale kills the texcoord, have to refresh it
+ self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
+end
+
+function VExitButton:OnEvent(event, ...)
+ if self[event] then
+ self[event](self, event, ...)
+ end
+end
+
+function VExitButton:UPDATE_BINDINGS()
+ self:UpdateHotkey()
+end
+
+function VExitButton:UpdateRegistration(bar)
+ -- auto show/hide when on a vehicle
+ local config = bar:GetConfig()
+ local f = bar:GetFrame()
+ if config.withControls then
+ if bar.vehicleExitStateRegistered then
+ UnregisterStateDriver(f, "unitexists")
+ bar.vehicleExitStateRegistered = false
+ end
+ bar:RegisterUnitWatch("vehicle",true)
+ else
+ bar:RegisterUnitWatch("vehicle",false)
+ if not bar.vehicleExitStateRegistered then
+ f:SetAttribute("unit","vehicle")
+ RegisterStateDriver(f, "unitexists", "[target=vehicle,exists,novehicleui] show; hide") -- spoof onstate-unitexists
+ bar.vehicleExitStateRegistered = true
+ end
+ end
+end
+
diff -r b2b105747466 -r 920d17851a93 classes/ActionButton.lua
--- a/classes/ActionButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,782 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local IsUsableAction = IsUsableAction
-local IsEquippedAction = IsEquippedAction
-local IsConsumableAction = IsConsumableAction
-local IsStackableAction = IsStackableAction
-local GetActionText = GetActionText
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local IsCurrentAction = IsCurrentAction
-local IsAutoRepeatAction = IsAutoRepeatAction
-local IsUsableAction = IsUsableAction
-local IsAttackAction = IsAttackAction
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local GetActionCooldown = GetActionCooldown
-local GetActionTexture = GetActionTexture
-local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
-local TOOLTIP_UPDATE_TIME = TOOLTIP_UPDATE_TIME
-local IsActionInRange = IsActionInRange
-local InCombatLockdown = InCombatLockdown
-local HasAction = HasAction
-
---
--- Secure snippets
--- These are run within the context of the bar's sandbox, as the
--- buttons themselves do not have their own sandbox.
---
-local _onstate_mc = -- function(self, stateid, newstate)
-[[
- local oldMcVehicleState = mcVehicleState
- mcVehicleState = newstate
- control:ChildUpdate()
- if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then
- control:ChildUpdate("vehicle")
- end
-]]
-
-local _childupdate = -- function(self, snippetid, message)
-[[
- local action = nil
- if (doVehicle and mcVehicleState == "vehicle") or
- (doMindControl and mcVehicleState == "mc") then
- local idx = self:GetAttribute("bar-idx")
- local maxN = (doVehicle and mcVehicleState == "vehicle") and 7 or 12
- if idx and idx <= maxN then
- action = 120 + idx
- else
- action = 0
- end
- elseif state and settings[state] and settings[state].page then
- action = self:GetAttribute("action-"..settings[state].page)
- end
- if action == nil then
- action = self:GetAttribute("default-action")
- end
-
- self:SetAttribute("action",action)
-
- if not self:GetAttribute("showgrid") then
- local tempShow = self:GetAttribute("showgrid-temp")
- local evtShow = self:GetAttribute("showgrid-event")
- if tempShow then tempShow = (tempShow > 0) end
- if evtShow then evtShow = (evtShow > 0) end
-
- if tempShow or evtShow or HasAction(action) then
- self:Show()
- else
- self:Hide()
- end
- end
-]]
-
-local _childupdate_vehicleExit = -- function(self, snippetid, message)
-[[
- local show = (mcVehicleState == "vehicle")
- if show and doVehicle then
- self:SetAttribute("type","macro")
- self:Show()
- else
- self:SetAttribute("type","action")
- end
- control:CallMethod("ShowVehicleExit",show)
-]]
-
-local _childupdate_showgrid = -- function(self, snippetid, message)
-[[
- showgrid_event = message
- self:SetAttribute("showgrid-event",message)
- if not self:GetAttribute("showgrid") then
- local count = message + (self:GetAttribute("showgrid-temp") or 0)
- if count <= 0 then
- local action = self:GetAttribute("action")
- -- note that HasAction is not updated on the target of a drag until after ACTIONBAR_HIDEGRID
- -- so, we set a flag for this button in pre-click/receive-drag and check for it here
- if HasAction(action) or self:GetAttribute("showgrid-clicked") then
- if not self:IsShown() then
- self:Show()
- end
- self:SetAttribute("showgrid-clicked",false)
- else
- if self:IsShown() then
- self:Hide()
- end
- end
- else
- self:Show()
- end
- end
-]]
-
-local _onDragStart = -- function(self, button, kind, value, ...)
-[[
- if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
- return kind, value, ...
- else
- return "action", self:GetAttribute("action")
- end
-]]
-
-local _onReceiveDrag = -- function(self, button, kind, value, ...)
-[[
- if kind ~= "spell" and kind ~= "item" and kind ~= "macro" then
- return kind, value, ...
- else
- if showgrid_event and showgrid_event > 0 then
- self:SetAttribute("showgrid-clicked",true)
- end
- return "action", self:GetAttribute("action")
- end
-]]
-
-local _onClick = -- function(self, button, down)
-[[
- if showgrid_event and showgrid_event > 0 then
- self:SetAttribute("showgrid-clicked",true)
- end
- return button
-]]
-
---
--- private
---
-local eventList = {
- "PLAYER_ENTERING_WORLD",
- "ACTIONBAR_PAGE_CHANGED",
- "ACTIONBAR_SLOT_CHANGED",
- "UPDATE_BINDINGS",
- "ACTIONBAR_UPDATE_STATE",
- "ACTIONBAR_UPDATE_USABLE",
- "ACTIONBAR_UPDATE_COOLDOWN",
- "UNIT_INVENTORY_CHANGED",
- "LEARNED_SPELL_IN_TAB",
- "UPDATE_INVENTORY_ALERTS",
- "PLAYER_TARGET_CHANGED",
- "TRADE_SKILL_SHOW",
- "TRADE_SKILL_CLOSE",
- "PLAYER_ENTER_COMBAT",
- "PLAYER_LEAVE_COMBAT",
- "START_AUTOREPEAT_SPELL",
- "STOP_AUTOREPEAT_SPELL",
- "UNIT_ENTERED_VEHICLE",
- "UNIT_EXITED_VEHICLE",
- "COMPANION_UPDATE",
-}
-
---
--- Action Button class
---
-local Super = ReAction.Button
-local Action = setmetatable( { }, { __index = Super } )
-ReAction.Button.Action = Action
-
-function Action:New( idx, barConfig, bar, idHint )
- local name = format("ReAction_%s_Action_%d",bar:GetName(),idx)
-
- self = Super.New(self, name, barConfig.buttons[idx], bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
- self.barConfig = barConfig
-
- local f = self:GetFrame()
- local barFrame = bar:GetFrame()
- local config = self:GetConfig()
-
- self.rangeTimer = TOOLTIP_UPDATE_TIME
-
- -- set up the base action ID
- self:SetActionIDPool("action",120)
- config.actionID = self:AcquireActionID(config.actionID, idHint)
- self.nPages = 1
-
- -- attribute setup
- f:SetAttribute("type","action")
- f:SetAttribute("checkselfcast", true)
- f:SetAttribute("checkfocuscast", true)
- f:SetAttribute("action", config.actionID)
- f:SetAttribute("default-action", config.actionID)
- f:SetAttribute("bar-idx",idx)
- f:SetAttribute("showgrid-temp",0)
- f:SetAttribute("showgrid-event",0)
- f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty)
-
- -- non secure scripts
- f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
- f:SetScript("OnEnter", function(frame) self:OnEnter() end)
- f:SetScript("OnLeave", function(frame) self:OnLeave() end)
- f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
- f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
- f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end)
- f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
- f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForDrag("LeftButton", "RightButton")
- f:RegisterForClicks("AnyUp")
- for _, evt in pairs(eventList) do
- f:RegisterEvent(evt)
- end
-
- -- secure handlers
- f:SetAttribute("_childupdate", _childupdate)
- f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid)
- barFrame:WrapScript(f, "OnDragStart", _onDragStart)
- barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
- barFrame:WrapScript(f, "OnClick", _onClick)
-
- -- attach to skinner
- bar:SkinButton(self)
-
- -- initial display
- if ReAction:GetConfigMode() then
- self:ShowGridTemp(true)
- end
-
- self:Refresh()
-
- return self
-end
-
-function Action:Destroy()
- local f = self:GetFrame()
- local c = self:GetConfig()
-
- f:SetAttribute("_childupdate-vehicle",nil)
- f:SetAttribute("action",c.actionID) -- so that Super.Destroy releases the right one
-
- if c.pageactions and #c.pageactions > 1 then
- for i = 2, #c.pageactions do
- self:ReleaseActionID(c.pageactions[i])
- self:ReleaseActionID(id)
- end
- end
-
- Super.Destroy(self)
-end
-
-function Action:GetBarConfig()
- -- this is the per-bar Action module config structure,
- -- not the config structure of the bar itself
- return self.barConfig
-end
-
-function Action:Refresh()
- Super.Refresh(self)
- self:RefreshPages()
- self:InstallVehicle()
- self:ShowGrid(not self:GetBarConfig().hideEmpty)
- self:UpdateAction()
-end
-
-function Action:InstallVehicle()
- local f = self:GetFrame()
- if self.idx == 7 and self:GetBarConfig().vehicle then
- if not self.vehicleInstalled then
- self.vehicleInstalled = true
- -- install vehicle-exit button on 7th button (only)
- f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit)
- f:SetAttribute("macrotext","/run VehicleExit()")
- self:GetBar():GetFrame().ShowVehicleExit = function(bar,show)
- self:ShowVehicleExit(show)
- end
- end
- -- setscale blows away tex coords
- self:UpdateIcon()
- elseif self.vehicleInstalled then
- self.vehicleInstalled = false
- f:SetAttribute("_childupdate-vehicle",nil)
- f:SetAttribute("macrotext",nil)
- end
-end
-
-function Action:ShowGrid( show )
- if not InCombatLockdown() then
- self.frame:SetAttribute("showgrid", show)
- self:UpdateShowGrid()
- end
-end
-
-function Action:ShowGridTemp( show )
- -- This function only modifies the show-grid when out
- -- of combat, and is ignored by the secure handler. Use
- -- it for configuration modes.
- if not InCombatLockdown() then
- local count = self.showGridTempCount or 0
- if show then
- count = count + 1
- else
- count = count - 1
- end
- if count < 0 then count = 0 end
- self.showGridTempCount = count
- self:GetFrame():SetAttribute("showgrid-temp",count)
- self:UpdateShowGrid()
- end
-end
-
-function Action:UpdateAll()
- self:UpdateActionIDLabel(ReAction:GetConfigMode())
- self:UpdateHotkey()
- self:UpdateShowGrid()
- self:UpdateIcon()
- self:UpdateBorder()
- self:UpdateMacroText()
- self:UpdateCount()
- self:UpdateTooltip()
- self:UpdateCheckedState()
- self:UpdateUsable()
- self:UpdateCooldown()
- self:UpdateFlash()
-end
-
-function Action:UpdateAction()
- local action = self:GetActionID()
- if action ~= self.actionID then
- self.actionID = action
- self:UpdateAll()
- end
-end
-
-function Action:UpdateShowGrid()
- if not InCombatLockdown() then
- local f = self:GetFrame()
- local count = (f:GetAttribute("showgrid-event") or 0) +
- (self.showGridTempCount or 0) +
- (f:GetAttribute("showgrid") and 1 or 0)
-
- if count <= 0 and not HasAction(self.actionID) then
- if f:IsShown() then
- f:Hide()
- end
- elseif not f:IsShown() then
- f:Show()
- end
- end
-end
-
-function Action:UpdateIcon()
- local texture, tLeft, tRight, tTop, tBottom = self:GetIconTexture()
- local icon = self.frames.icon
- local hotkey = self.frames.hotkey
- local f = self:GetFrame()
-
- if self.vehicleExitMode then
- texture = "Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up"
- icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
- icon:SetVertexColor(1,1,1)
- else
- icon:SetTexCoord(0,1,0,1)
- end
-
- if texture then
- icon:SetTexture(texture)
- if tLeft then
- icon:SetTexCoord(tLeft,tRight,tTop,tBottom)
- end
- icon:Show()
- self.rangeTimer = -1
- f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
- else
- icon:Hide()
- self.frames.cooldown:Hide()
- self.rangeTimer = nil
- f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
- end
-end
-
-function Action:GetIconTexture()
- return GetActionTexture(self.actionID)
-end
-
-function Action:UpdateBorder()
- local action = self.actionID
- if ReAction:GetKeybindMode() then
- self:UpdateKeybindModeDisplay(true)
- elseif IsEquippedAction(action) then
- self.frames.border:SetVertexColor(0, 1.0, 0, 0.35)
- self.frames.border:Show()
- else
- self.frames.border:Hide()
- end
-end
-
-function Action:UpdateMacroText()
- local action = self.actionID
- if not IsConsumableAction(action) and not IsStackableAction(action) then
- self.frames.name:SetText(GetActionText(action))
- else
- self.frames.name:SetText("")
- end
-end
-
-function Action:UpdateCount()
- local action = self.actionID
- if IsConsumableAction(action) or IsStackableAction(action) then
- self.frames.count:SetText(GetActionCount(action))
- else
- self.frames.count:SetText("")
- end
-end
-
-function Action:UpdateTooltip()
- local f = self:GetFrame()
- if GameTooltip:GetOwner() == f then
- self:SetTooltip()
- end
-end
-
-function Action:SetTooltip()
- local f = self:GetFrame()
- if GetCVar("UberTooltips") == "1" then
- GameTooltip_SetDefaultAnchor(GameTooltip, f)
- else
- GameTooltip:SetOwner(f,"ANCHOR_RIGHT")
- end
- GameTooltip:SetAction(self.actionID)
-end
-
-function Action:UpdateCheckedState()
- local action = self.actionID
- if IsCurrentAction(action) or IsAutoRepeatAction(action) then
- self:GetFrame():SetChecked(1)
- else
- self:GetFrame():SetChecked(0)
- end
-end
-
-function Action:UpdateUsable()
- local isUsable, notEnoughMana = self:GetUsable()
- local noRange = self:GetInRange()
-
- isUsable = self.vehicleExitMode or (isUsable and not noRange)
-
- if isUsable then
- if self.usableStatus ~= "usable" then
- self.frames.icon:SetVertexColor(1.0, 1.0, 1.0)
- self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
- self.usableStatus = "usable"
- end
- elseif noRange then
- if self.usableStatus ~= "norange" then
- self.frames.icon:SetVertexColor(1.0,0.1,0.1)
- self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
- self.usableStatus = "norange"
- end
- elseif notEnoughMana then
- if self.usableStatus ~= "oom" then
- self.frames.icon:SetVertexColor(0.5, 0.5, 1.0)
- self.frames.normalTexture:SetVertexColor(0.5, 0.5, 1.0)
- self.usableStatus = "oom"
- end
- else
- if self.usableStatus ~= "unusable" then
- self.frames.icon:SetVertexColor(0.4, 0.4, 0.4)
- self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
- self.usableStatus = "unusable"
- end
- end
-end
-
-function Action:GetUsable()
- return IsUsableAction(self.actionID)
-end
-
-function Action:GetInRange()
- return IsActionInRange(self.actionID) == 0
-end
-
-function Action:UpdateCooldown()
- CooldownFrame_SetTimer(self.frames.cooldown, self:GetCooldown())
-end
-
-function Action:GetCooldown()
- return GetActionCooldown(self.actionID)
-end
-
-function Action:UpdateFlash()
- local action = self.actionID
- self:SetFlash( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) )
-end
-
-function Action:SetFlash(flash)
- if self.flashing ~= flash then
- self.flashing = flash
- self.flashtime = 0
- if not flash then
- self.frames.flash:Hide()
- end
- self:UpdateCheckedState()
- end
-end
-
-function Action:RunFlash(elapsed)
- if self.flashing then
- local flashtime = self.flashtime - elapsed
- self.flashtime = flashtime
- if flashtime <= 0 then
- local overtime = -flashtime
- if overtime >= ATTACK_BUTTON_FLASH_TIME then
- overtime = 0
- end
- flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
- local flash = self.frames.flash
- if flash:IsShown() then
- flash:Hide()
- else
- flash:Show()
- end
- end
- end
-end
-
-function Action:RunRangeFinder(elapsed)
- local rangeTimer = self.rangeTimer
- if rangeTimer then
- rangeTimer = rangeTimer - elapsed
- self.rangeTimer = rangeTimer
- if rangeTimer <= 0 then
- self:UpdateUsable()
- self.rangeTimer = TOOLTIP_UPDATE_TIME
- end
- end
-end
-
-function Action:GetActionID(page)
- if page == nil then
- -- get the effective ID
- return self:GetFrame():GetAttribute("action")
- else
- if page == 1 then
- return self.config.actionID
- else
- return self.config.pageactions and self.config.pageactions[page] or self.config.actionID
- end
- end
-end
-
-function Action:SetActionID( id, page )
- id = tonumber(id)
- page = tonumber(page)
- if id == nil or id < 1 or id > 120 then
- ReAction:UserError(L["Action ID range is 1-120"])
- return
- end
- if page and page ~= 1 then
- if not self.config.pageactions then
- self.config.pageactions = { }
- end
- self:ReleaseActionID(self.config.pageactions[page])
- self.config.pageactions[page] = id
- self:AcquireActionID(self.config.pageactions[page])
- self.frame:SetAttribute("action-page"..page,id)
- else
- self:ReleaseActionID(self.config.actionID)
- self.config.actionID = id
- self:AcquireActionID(self.config.actionID)
- self.frame:SetAttribute("action",id)
- self.frame:SetAttribute("default-action",id)
- if self.config.pageactions then
- self.config.pageactions[1] = id
- self.frame:SetAttribute("action-page1",id)
- end
- end
-end
-
-function Action:RefreshPages( force )
- local nPages = self:GetBarConfig().nPages
- if nPages and (nPages ~= self.nPages or force) then
- local f = self:GetFrame()
- local c = self.config.pageactions
- if nPages > 1 and not c then
- c = { }
- self.config.pageactions = c
- end
- for i = 1, nPages do
- if i > 1 then
- c[i] = self:AcquireActionID(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons())
- else
- c[i] = self.config.actionID -- page 1 is the same as the base actionID
- end
- f:SetAttribute("action-page"..i,c[i])
- end
- for i = nPages+1, #c do
- self:ReleaseActionID(c[i])
- c[i] = nil
- f:SetAttribute("action-page"..i,nil)
- end
- self.nPages = nPages
- end
-end
-
-function Action.SetupBarHeader( bar, config ) -- call this as a static method
- local f = bar:GetFrame()
- f:SetAttribute("mindcontrol",config.mindcontrol)
- f:SetAttribute("vehicle",config.vehicle)
- f:Execute(
- [[
- doMindControl = self:GetAttribute("mindcontrol")
- doVehicle = self:GetAttribute("vehicle")
- control:ChildUpdate()
- ]])
-
- f:SetAttribute("_onstate-mc", _onstate_mc)
- RegisterStateDriver(f, "mc", "[vehicleui] vehicle; [bonusbar:5] mc; none")
-
- f:SetAttribute("lockbuttons",config.lockButtons)
- f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat)
- f:Execute(
- [[
- lockButtons = self:GetAttribute("lockbuttons")
- lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
- ]])
-end
-
-
-function Action.SetButtonLock( bar, lock, lockCombat ) -- call this as a static method
- local f = bar:GetFrame()
- f:SetAttribute("lockbuttons",lock)
- f:SetAttribute("lockbuttonscombat",lockCombat)
- f:Execute(
- [[
- lockButtons = self:GetAttribute("lockbuttons")
- lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
- ]])
-end
-
-
-function Action:ShowVehicleExit(show)
- self.vehicleExitMode = show and self:GetBarConfig().vehicle
- self:UpdateIcon()
-end
-
-function Action:OnEnter( )
- self:SetTooltip()
-end
-
-function Action:OnLeave( )
- GameTooltip:Hide()
-end
-
-function Action:OnAttributeChanged( attr, value )
- if attr ~= "statehidden" then
- self:UpdateAction()
- end
-end
-
-function Action:PostClick( )
- self:UpdateCheckedState()
-end
-
-function Action:OnUpdate( elapsed )
- self:RunFlash(elapsed)
- self:RunRangeFinder(elapsed)
-end
-
-function Action:OnDragStart()
- self:UpdateCheckedState()
- self:UpdateFlash()
-end
-
-function Action:OnReceiveDrag()
- self:UpdateCheckedState()
- self:UpdateFlash()
-end
-
-function Action:OnEvent(event, ...)
- if self[event] then
- self[event](self, event, ...)
- end
-end
-
-function Action:ACTIONBAR_SLOT_CHANGED(event, action)
- if action == 0 or action == self.actionID then
- self:UpdateAll()
- end
-end
-
-function Action:PLAYER_ENTERING_WORLD()
- self:UpdateAction()
-end
-
-function Action:ACTIONBAR_PAGE_CHANGED()
- self:UpdateAction()
-end
-
-function Action:UPDATE_BONUS_ACTIONBAR()
- self:UpdateAction()
-end
-
-function Action:UPDATE_BINDINGS()
- self:UpdateHotkey()
-end
-
-function Action:PLAYER_TARGET_CHANGED()
- self.rangeTimer = -1
-end
-
-function Action:ACTIONBAR_UPDATE_STATE()
- self:UpdateCheckedState()
-end
-
-function Action:TRADE_SKILL_SHOW()
- self:UpdateCheckedState()
-end
-Action.TRADE_SKILL_CLOSE = Action.TRADE_SKILL_CLOSE
-
-function Action:UNIT_ENTERED_VEHICLE(event,unit)
- if unit == "player" then
- self:UpdateCheckedState()
- end
-end
-Action.UNIT_EXITED_VEHICLE = Action.UNIT_ENTERED_VEHICLE
-
-function Action:COMPANION_UPDATE(event,unit)
- if unit == "mount" then
- self:UpdateCheckedState()
- end
-end
-
-function Action:ACTIONBAR_UPDATE_USABLE()
- self:UpdateUsable()
-end
-
-function Action:ACTIONBAR_UPDATE_COOLDOWN()
- self:UpdateCooldown()
-end
-
-function Action:PLAYER_ENTER_COMBAT()
- if IsAttackAction(self.actionID) then
- self:SetFlash(true)
- end
-end
-
-function Action:PLAYER_LEAVE_COMBAT()
- if IsAttackAction(self.actionID) then
- self:SetFlash(false)
- end
-end
-
-function Action:START_AUTOREPEAT_SPELL()
- if IsAutoRepeatAction(self.actionID) then
- self:SetFlash(true)
- end
-end
-
-function Action:STOP_AUTOREPEAT_SPELL()
- if not IsAttackAction(self.actionID) then
- self:SetFlash(false)
- end
-end
-
-function Action:UNIT_INVENTORY_CHANGED(unit)
- if unit == "player" then
- self:UpdateTooltip()
- end
-end
-
-function Action:LEARNED_SPELL_IN_TAB()
- self:UpdateTooltip()
-end
diff -r b2b105747466 -r 920d17851a93 classes/BagButton.lua
--- a/classes/BagButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local ContainerIDToInventoryID = ContainerIDToInventoryID
-local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
-local IsModifiedClick = IsModifiedClick
-local CursorHasItem = CursorHasItem
-local GetInventoryItemTexture = GetInventoryItemTexture
-local GetInventorySlotInfo = GetInventorySlotInfo
-local PickupBagFromSlot = PickupBagFromSlot
-local CursorCanGoInSlot = CursorCanGoInSlot
-
--- class declarations
-local Super = ReAction.Button
-local BagBase = setmetatable( { }, { __index = Super } )
-local Bag = setmetatable( { }, { __index = BagBase } )
-local Backpack = setmetatable( { }, { __index = BagBase } )
-local Keyring = setmetatable( { }, { __index = BagBase } )
-
-ReAction.Button.Bag = BagBase
-
---
--- Bag Button base class
---
-
-function BagBase:New( idx, moduleConfig, bar, idHint )
- local name = format("ReAction_%s_Bag_%d",bar:GetName(),idx)
-
- -- use a variable private leaf implementation class
- -- unlike traditional OO programming, we can initialize the leaf
- -- class before initializing its derived class
- local class = Bag
- if idx == 1 then
- class = Backpack
- elseif idx == 6 then
- class = Keyring
- end
- self = class:New(name,moduleConfig.buttons[bar:GetName()][idx], bar, idx)
- self.moduleConfig = moduleConfig
-
- local f = self:GetFrame()
- local config = self:GetConfig()
-
- -- set up the bag ID pool
- self:SetActionIDPool("bag",6)
- config.bagID = self:AcquireActionID(config.bagID, idHint, true)
-
- -- non secure scripts
- f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
- f:SetScript("OnEnter", function(frame) self:OnEnter() end)
- f:SetScript("OnLeave", function(frame) self:OnLeave() end)
- f:SetScript("OnReceiveDrag", function(frame, ...) self:OnReceiveDrag(...) end)
- f:SetScript("OnClick", function(frame, ...) self:OnClick(...) end)
-
- -- secure handlers
- -- (none)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForClicks("LeftButtonUp","RightButtonUp")
- f:RegisterEvent("UPDATE_BINDINGS")
-
- -- frame setup
- f:SetID(self:GetBagID())
-
- if not f.hotkey then
- local h = f:CreateFontString(name.."HotKey","ARTWORK","NumberFontNormalSmallGray")
- h:SetWidth(30)
- h:SetHeight(10)
- h:SetJustifyH("RIGHT")
- h:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
- h:Show()
- f.hotkey = h
- end
-
- if not _G[name.."ItemAnim"] then
- local anim = CreateFrame("Model",name.."ItemAnim",f,"ItemAnimTemplate")
- anim:SetPoint("BOTTOMRIGHT",f,"BOTTOMRIGHT",-10,0)
- anim:Hide()
- end
-
- if not f.border then
- local b = f:CreateTexture(name.."Border","OVERLAY")
- b:SetAllPoints()
- b:SetWidth(f:GetWidth()*(62/36))
- b:SetHeight(f:GetHeight()*(62/36))
- b:SetTexture("Interface\\Buttons\UI-ActionButton-Border")
- b:SetBlendMode("ADD")
- b:Hide()
- f.border = b
- end
-
- self.frames.count:SetDrawLayer("ARTWORK")
-
- self.frames.hotkey = f.hotkey
- self.frames.border = _G[name.."Border"]
- self.frames.icon = _G[name.."IconTexture"]
- self.frames.anim = _G[name.."ItemAnim"]
-
- -- initial display
- if ReAction:GetConfigMode() then
- self:GetFrame():Show()
- end
-
- self:Refresh()
-
- return self
-end
-
-function BagBase:GetModuleConfig()
- -- this is the Bag module config structure,
- -- not the config structure of the bar itself
- return self.moduleConfig
-end
-
-function BagBase:GetActionID()
- return self.config.bagID
-end
-
-function BagBase:GetBagID()
- return self:GetActionID() - 1
-end
-
-function BagBase:Refresh()
- Super.Refresh(self)
- self:UpdateHotkey()
- self:Update()
-end
-
-function BagBase:Update()
- self:UpdateChecked()
-end
-
-function BagBase:UpdateChecked(force)
- if force == nil then
- for i=1, NUM_CONTAINER_FRAMES do
- local c = _G["ContainerFrame"..i]
- if c:GetID() == self:GetBagID() and c:IsShown() then
- self:GetFrame():SetChecked(1)
- return
- end
- end
- self:GetFrame():SetChecked(0)
- end
- self:GetFrame():SetChecked(force)
-end
-
-function BagBase:OnEvent(evt, ...)
- if self[evt] then
- self[evt](self, ...)
- end
-end
-
-function BagBase:OnEnter()
- self:SetTooltip()
-end
-
-function BagBase:OnLeave()
- GameTooltip:Hide()
-end
-
-function BagBase:UPDATE_BINDINGS()
- self:UpdateHotkey()
-end
-
-
---
--- Bag Button class
---
-function Bag:New(name, cfg, bar, idx)
- self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
- local f = self:GetFrame()
-
- f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
-
- f:RegisterEvent("CURSOR_UPDATE")
- f:RegisterEvent("BAG_UPDATE")
- f:RegisterEvent("BAG_CLOSED")
- f:SetScript("OnDragStart", function(frame, ...) self:OnDragStart(...) end)
- f:RegisterForDrag("LeftButton")
-
- -- attach to skinner
- bar:SkinButton(self,
- {
- Icon = _G[name.."IconTexture"]
- }
- )
-
- return self
-end
-
-function Bag:GetInventorySlot()
- return ContainerIDToInventoryID(self:GetBagID())
-end
-
-function Bag:GetInventorySlotName()
- return "Bag"..(self:GetBagID()-1).."Slot"
-end
-
-function Bag:SetTooltip()
- GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
- if not GameTooltip:SetInventoryItem("player", self:GetInventorySlot()) then
- GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
- end
-end
-
-function Bag:Update()
- local texture = GetInventoryItemTexture("player", self:GetInventorySlot())
- if texture then
- self.frames.icon:SetTexture(texture)
- self.frames.icon:Show()
- self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
- else
- local _, bgTex = GetInventorySlotInfo(self:GetInventorySlotName())
- self.frames.icon:SetTexture(bgTex)
- self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
- end
- self:UpdateChecked()
-end
-
-function Bag:OnClick()
- if IsModifiedClick("OPENALLBAGS") then
- OpenAllBags()
- else
- if not PutItemInBag(self:GetInventorySlot()) then
- ToggleBag(self:GetBagID())
- end
- end
- self:UpdateChecked()
-end
-
-function Bag:OnReceiveDrag()
- if CursorHasItem() then
- PutItemInBag(self:GetInventorySlot())
- end
-end
-
-function Bag:OnDragStart()
- PickupBagFromSlot(self:GetInventorySlot())
- self:Update()
-end
-
-function Bag:BAG_UPDATE(bag)
- if bag == self:GetBagID() then
- self:Update()
- end
-end
-
-function Bag:CURSOR_UPDATE()
- if CursorCanGoInSlot(self:GetInventorySlot()) then
- self:GetFrame():LockHighlight()
- else
- self:GetFrame():UnlockHighlight()
- end
-end
-
-function Bag:BAG_CLOSED(bag)
- if bag == self:GetBagID() then
- self:Update()
- end
-end
-
-
---
--- Backpack Button class
---
-function Backpack:New(name, cfg, bar, idx)
- self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
- local f = self:GetFrame()
- local icon = _G[name.."IconTexture"]
- icon:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
- icon:Show()
- f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
- f:RegisterEvent("PLAYER_ENTERING_WORLD");
- f:RegisterEvent("CVAR_UPDATE");
- f:SetScript("OnShow", function(frame, ...) self:OnShow(...) end)
-
- -- attach to skinner
- bar:SkinButton(self,
- {
- Icon = _G[name.."IconTexture"]
- }
- )
-
- return self
-end
-
-function Backpack:Update()
- self:UpdateFreeSlots()
- self:UpdateChecked()
-end
-
-function Backpack:UpdateFreeSlots()
- if GetCVar("displayFreeBagSlots") == "1" then
- local total = 0
- for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
- local free, family = GetContainerNumFreeSlots(i)
- if family == 0 then
- total = total + free
- end
- end
-
- self.freeSlots = total
- self.frames.count:SetText(format("(%s)", self.freeSlots))
- self.frames.count:Show()
- elseif self.frames.count:IsShown() then
- self.frames.count:Hide()
- end
-end
-
-function Backpack:SetTooltip()
- GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
- GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)
- GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (self.freeSlots or 0)))
- GameTooltip:Show();
-end
-
-function Backpack:OnShow()
- self:UpdateFreeSlots()
-end
-
-function Backpack:OnClick()
- if IsModifiedClick("OPENALLBAGS") then
- OpenAllBags()
- else
- if not PutItemInBackpack() then
- ToggleBackpack()
- end
- end
- self:UpdateChecked()
-end
-
-function Backpack:OnReceiveDrag()
- if CursorHasItem() then
- PutItemInBackpack()
- end
-end
-
-function Backpack:PLAYER_ENTERING_WORLD()
- self:CVAR_UPDATE("DISPLAY_FREE_BAG_SLOTS", GetCVar("displayFreeBagSlots"))
-end
-
-function Backpack:CVAR_UPDATE( cvar, value )
- if cvar == "DISPLAY_FREE_BAG_SLOTS" then
- if value == "1" then
- self:GetFrame():RegisterEvent("BAG_UPDATE")
- else
- self:GetFrame():UnregisterEvent("BAG_UPDATE")
- end
- self:UpdateFreeSlots()
- end
-end
-
-function Backpack:BAG_UPDATE(bag)
- if bag >= BACKPACK_CONTAINER and bag <= NUM_BAG_SLOTS then
- self:UpdateFreeSlots()
- end
-end
-
-
---
--- Keyring Button class
---
-function Keyring:New(name, cfg, bar, idx)
- self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
- local f = self:GetFrame()
-
- f:SetWidth(18)
- f:SetHeight(39)
-
- local tex = f:GetNormalTexture()
- tex:ClearAllPoints()
- tex:SetAllPoints()
-
- f:SetNormalTexture("Interface\\Buttons\\UI-Button-KeyRing")
- f:SetHighlightTexture("Interface\\Buttons\\UI-Button-KeyRing-Highlight")
- f:SetPushedTexture("Interface\\Buttons\\UI-Button-KeyRing-Down")
- f:GetNormalTexture():SetTexCoord(0,0.5625,0,0.609375)
- f:GetHighlightTexture():SetTexCoord(0,0.5625,0,0.609375)
- f:GetPushedTexture():SetTexCoord(0,0.5625,0,0.609375)
-
- if not HasKey() then
- f:Hide()
- end
-
- -- DO NOT attach to skinner
-
- return self
-end
-
-function Keyring:GetBagID()
- return KEYRING_CONTAINER
-end
-
-function Keyring:Refresh()
- local f = self:GetFrame()
- self.bar:PlaceButton( self, f:GetHeight(), f:GetHeight() ) -- use height x height since it's an odd size
- self:UpdateHotkey()
- self:Update()
-end
-
-function Keyring:SetTooltip()
- GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT");
- GameTooltip:SetText(KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
- GameTooltip:AddLine();
-end
-
-function Keyring:OnReceiveDrag()
- if CursorHasItem() then
- PutKeyInKeyRing()
- end
-end
-
-function Keyring:OnClick()
- if CursorHasItem() then
- PutKeyInKeyRing()
- else
- ToggleKeyRing()
- end
- self:UpdateChecked()
-end
-
-function Keyring:ShowGridTemp(show)
- if not HasKey() then
- if show then
- self:GetFrame():Show()
- else
- self:GetFrame():Hide()
- end
- end
-end
-
diff -r b2b105747466 -r 920d17851a93 classes/Bar.lua
--- a/classes/Bar.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,826 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local LKB = ReAction.LKB
-local _G = _G
-local CreateFrame = CreateFrame
-local floor = math.floor
-local fmod = math.fmod
-local format = string.format
-
-local LSG = LibStub("ReAction-LibShowActionGrid-1.0")
-
----- Secure snippets ----
-local _reaction_init =
-[[
- anchorKeys = newtable("point","relPoint","x","y")
-
- state = nil
- set_state = nil
- state_override = nil
- unit_exists = nil
-
- showAll = false
- hidden = false
-
- defaultAlpha = 1.0
- defaultScale = 1.0
- defaultAnchor = newtable()
-
- activeStates = newtable()
- settings = newtable()
- extensions = newtable()
-]]
-
-local _reaction_refresh =
-[[
- local oldState = state
- state = state_override or set_state or state
-
- local hide = nil
- if state then
- local settings = settings[state]
- if settings then
- -- show/hide
- hide = settings.hide
- -- re-anchor
- local old_anchor = activeStates.anchor
- activeStates.anchor = settings.anchorEnable and state
- if old_anchor ~= activeStates.anchor or not set_state then
- if activeStates.anchor then
- if settings.anchorPoint then
- self:ClearAllPoints()
- local f = self:GetAttribute("frameref-anchor-"..state)
- if f then
- self:SetPoint(settings.anchorPoint, f, settings.anchorRelPoint, settings.anchorX, settings.anchorY)
- end
- end
- elseif defaultAnchor.point then
- self:ClearAllPoints()
- self:SetPoint(defaultAnchor.point, defaultAnchor.frame,
- defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
- end
- end
- -- re-scale
- local old_scale = activeStates.scale
- activeStates.scale = settings.enableScale and state
- if old_scale ~= activeStates.scale or not set_state then
- self:SetScale(activeStates.scale and settings.scale or defaultScale)
- end
- -- alpha
- local old_alpha = activeStates.alpha
- activeStates.alpha = settings.enableAlpha and state
- if old_alpha ~= activeStates.alpha or not set_state then
- self:SetAlpha(activeStates.alpha and settings.alpha or defaultAlpha)
- end
- end
- end
-
- -- hide if state or unit_exists says to
- hide = not showAll and (hide or unithide)
- if hide ~= hidden then
- hidden = hide
- if hide then
- self:Hide()
- else
- self:Show()
- end
- end
-
- for _, attr in pairs(extensions) do
- control:RunAttribute(attr)
- end
-
- control:ChildUpdate()
-
- if showAll then
- control:CallMethod("UpdateHiddenLabel", state and settings[state] and settings[state].hide)
- end
-
- if oldState ~= state then
- control:CallMethod("StateRefresh", state)
- end
-]]
-
-local _onstate_reaction = -- function( self, stateid, newstate )
-[[
- set_state = newstate
-]] .. _reaction_refresh
-
-local _onstate_showgrid = -- function( self, stateid, newstate )
-[[
- control:ChildUpdate(stateid,newstate)
- control:CallMethod("UpdateShowGrid")
-]]
-
-local _onstate_unitexists = -- function( self, stateid, newstate )
-[[
- unithide = not newstate or newstate == "hide"
-]] .. _reaction_refresh
-
-local _onclick = -- function( self, button, down )
-[[
- if state_override == button then
- state_override = nil -- toggle
- else
- state_override = button
- end
-]] .. _reaction_refresh
-
--- For reference
--- the option field names must match the field names of the options table, below
-local stateProperties = {
- hide = true,
- --keybindState = true, TODO: broken
- anchorEnable = true,
- anchorFrame = true,
- anchorPoint = true,
- anchorRelPoint = true,
- anchorX = true,
- anchorY = true,
- enableScale = true,
- scale = true,
- enableAlpha = true,
- alpha = true,
-}
-
-
----- Utility functions ----
-
--- traverse a table tree by key list and fetch the result or first nil
-local function tfetch(t, ...)
- for i = 1, select('#', ...) do
- t = t and t[select(i, ...)]
- end
- return t
-end
-
--- traverse a table tree by key list and build tree as necessary
-local function tbuild(t, ...)
- for i = 1, select('#', ...) do
- local key = select(i, ...)
- if not t[key] then t[key] = { } end
- t = t[key]
- end
- return t
-end
-
--- return a new array of keys of table 't', sorted by comparing
--- sub-fields (obtained via tfetch) of the table values
-local function fieldsort( t, ... )
- local r = { }
- for k in pairs(t) do
- table.insert(r,k)
- end
- local path = { ... }
- table.sort(r, function(lhs, rhs)
- local olhs = tfetch(t[lhs], unpack(path)) or 0
- local orhs = tfetch(t[rhs], unpack(path)) or 0
- return olhs < orhs
- end)
- return r
-end
-
-
----- Bar class ----
-local Bar = { }
-local weak = { __mode = "k" }
-local frameList = { }
-
-ReAction.Bar = Bar -- export to ReAction
-
-function Bar:New( name, config )
- if type(config) ~= "table" then
- error("ReAction.Bar: config table required")
- end
-
- -- create new self
- self = setmetatable(
- {
- config = config,
- name = name,
- buttons = setmetatable( { }, weak ),
- width = config.width or 480,
- height = config.height or 40,
- },
- {__index = self} )
-
- -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
- -- not mouse-clickable by the user.
- local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
- name = name and "ReAction-"..name
- local f = name and frameList[name]
- if not f then
- f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
- if name then
- frameList[name] = f
- end
- end
- f:SetFrameStrata("MEDIUM")
- f:SetWidth(self.width)
- f:SetHeight(self.height)
- f:SetAlpha(config.alpha or 1.0)
- f:Show()
- f:EnableMouse(false)
- f:SetClampedToScreen(true)
- LSG:AddFrame(f)
-
- -- secure handlers
- f:Execute(_reaction_init)
- f:SetAttribute("_onstate-reaction", _onstate_reaction)
- f:SetAttribute("_onstate-showgrid", _onstate_showgrid)
- f:SetAttribute("_onstate-unitexists", _onstate_unitexists)
- f:SetAttribute("_onclick", _onclick)
-
- -- secure handler CallMethod()s
- f.UpdateShowGrid = function() self:UpdateShowGrid() end
- f.StateRefresh = function() self:RefreshControls() end
- f.UpdateHiddenLabel = function(f,hidden) self:SetLabelSubtext(hidden and L["Hidden"]) end
-
- -- Override the default frame accessor to provide strict read-only access
- function self:GetFrame()
- return f
- end
-
- self:ApplyAnchor()
- self:SetConfigMode(ReAction:GetConfigMode())
- self:SetKeybindMode(ReAction:GetKeybindMode())
-
- ReAction.RegisterCallback(self, "OnConfigModeChanged")
-
- return self
-end
-
-function Bar:Destroy()
- local f = self:GetFrame()
- f:UnregisterAllEvents()
- self:ShowControls(false)
- ReAction.UnregisterAllCallbacks(self)
- LKB.UnregisterAllCallbacks(self)
- LSG:RemoveFrame(f)
- f:SetParent(UIParent)
- f:ClearAllPoints()
- f:Hide()
-end
-
---
--- Events
---
-
-function Bar:OnConfigModeChanged(event, mode)
- self:SetConfigMode(mode)
-end
-
---
--- Accessors
---
-
-function Bar:GetName()
- return self.name
-end
-
--- only ReAction:RenameBar() should call this function. Calling from any other
--- context will desync the bar list in the ReAction class.
-function Bar:SetName(name)
- self.name = name
- if self.overlay then
- self.overlay:SetLabel(self.name)
- end
-end
-
-function Bar:GetFrame()
- -- this method is included for documentation purposes. It is overridden
- -- for each object in the :New() method.
- error("Invalid Bar object: used without initialization")
-end
-
-function Bar:GetConfig()
- return self.config
-end
-
-function Bar:GetAnchor()
- local c = self.config
- return (c.point or "CENTER"),
- (c.anchor or self:GetFrame():GetParent():GetName()),
- (c.relpoint or c.point or "CENTER"),
- (c.x or 0),
- (c.y or 0)
-end
-
-function Bar:SetAnchor(point, frame, relativePoint, x, y)
- local c = self.config
- c.point = point or c.point
- c.anchor = frame or c.anchor
- c.relpoint = relativePoint or c.relpoint
- c.x = x or c.x
- c.y = y or c.y
- self:ApplyAnchor()
- ReAction:RefreshBar(self)
-end
-
-function Bar:GetSize()
- local f = self:GetFrame()
- return f:GetWidth(), f:GetHeight()
-end
-
-function Bar:SetSize(w,h)
- local f = self:GetFrame()
- self.config.width = w
- self.config.height = h
- f:SetWidth(w)
- f:SetHeight(h)
-end
-
-function Bar:GetButtonSize()
- local w = self.config.btnWidth or 32
- local h = self.config.btnHeight or 32
- -- TODO: get from modules?
- return w,h
-end
-
-function Bar:SetButtonSize(w,h)
- if w > 0 and h > 0 then
- self.config.btnWidth = w
- self.config.btnHeight = h
- end
- ReAction:RefreshBar(self)
-end
-
-function Bar:GetNumButtons()
- local r,c = self:GetButtonGrid()
- return r*c
-end
-
-function Bar:GetButtonGrid()
- local cfg = self.config
- local r = cfg.btnRows or 1
- local c = cfg.btnColumns or 1
- local s = cfg.spacing or 4
- return r,c,s
-end
-
-function Bar:SetButtonGrid(r,c,s)
- if r > 0 and c > 0 and s > 0 then
- local cfg = self.config
- cfg.btnRows = r
- cfg.btnColumns = c
- cfg.spacing = s
- end
- ReAction:RefreshBar(self)
-end
-
-function Bar:GetAlpha()
- return self.config.alpha or 1.0
-end
-
-function Bar:SetAlpha(value)
- self.config.alpha = value
- self:GetFrame():SetAlpha(value or 1.0)
- self:UpdateDefaultStateAlpha()
- ReAction:RefreshBar(self)
-end
-
-function Bar:IterateButtons()
- -- iterator returns button, idx and does NOT iterate in index order
- return pairs(self.buttons)
-end
-
---
--- Methods
---
-
-function Bar:SetConfigMode(mode)
- self:SetSecureData("showAll",mode)
- self:ShowControls(mode)
- for b in self:IterateButtons() do
- b:ShowGridTemp(mode)
- b:UpdateActionIDLabel(mode)
- end
-end
-
-function Bar:SetKeybindMode(mode)
- self:SetSecureData("showAll",mode)
- for b in self:IterateButtons() do
- b:SetKeybindMode(mode)
- end
-end
-
-function Bar:ApplyAnchor()
- local f = self:GetFrame()
- local c = self.config
- local p = c.point
-
- f:SetWidth(c.width)
- f:SetHeight(c.height)
- f:ClearAllPoints()
-
- if p then
- local a = f:GetParent()
- if c.anchor then
- local bar = ReAction:GetBar(c.anchor)
- if bar then
- a = bar:GetFrame()
- else
- a = _G[c.anchor]
- end
- end
- local fr = a or f:GetParent()
- f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
- else
- f:SetPoint("CENTER")
- end
-
- self:UpdateDefaultStateAnchor()
-end
-
-function Bar:ClipNButtons( n )
- local cfg = self.config
- local r = cfg.btnRows or 1
- local c = cfg.btnColumns or 1
-
- cfg.btnRows = ceil(n/c)
- cfg.btnColumns = min(n,c)
-end
-
-function Bar:AddButton(idx, button)
- local f = self:GetFrame()
-
- -- store in a weak reverse-index array
- self.buttons[button] = idx
-
- -- Store a properly wrapped reference to the child frame as an attribute
- -- (accessible via "frameref-btn#")
- f:SetFrameRef(format("btn%d",idx), button:GetFrame())
-end
-
-function Bar:RemoveButton(button)
- local idx = self.buttons[button]
- if idx then
- self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
- self.buttons[button] = nil
- end
-end
-
-function Bar:PlaceButton(button, baseW, baseH)
- local idx = self.buttons[button]
- if idx then
- local r, c, s = self:GetButtonGrid()
- local bh, bw = self:GetButtonSize()
- local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
- local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
- local scale = bw/baseW
- local b = button:GetFrame()
-
- b:ClearAllPoints()
- b:SetPoint("TOPLEFT",x/scale,y/scale)
- b:SetScale(scale)
- end
-end
-
-function Bar:SkinButton()
- -- does nothing by default
-end
-
-function Bar:UpdateShowGrid()
- for button in self:IterateButtons() do
- button:UpdateShowGrid()
- end
-end
-
-function Bar:ShowControls(show)
- if show then
- if not self.overlay then
- self.overlay = Bar.Overlay:New(self) -- see Overlay.lua
- end
- self.overlay:Show()
- self:RefreshSecureState()
- elseif self.overlay then
- self.overlay:Hide()
- end
-end
-
-function Bar:RefreshControls()
- if self.overlay and self.overlay:IsShown() then
- self.overlay:RefreshControls()
- end
-end
-
-function Bar:SetLabelSubtext(text)
- if self.overlay then
- self.overlay:SetLabelSubtext(text)
- end
-end
-
---
--- Secure state functions
---
-
-function Bar:GetSecureState()
- local env = GetManagedEnvironment(self:GetFrame())
- return env and env.state
-end
-
-function Bar:GetStateProperty(state, propname)
- -- override in modules/State.lua for now
-end
-
-function Bar:SetStateProperty(state, propname, value)
- -- override in modules/State.lua for now
-end
-
-function Bar:RefreshSecureState()
- self:GetFrame():Execute(_reaction_refresh)
-end
-
--- usage: SetSecureData(globalname, [tblkey1, tblkey2, ...], value)
-function Bar:SetSecureData( ... )
- local n = select('#',...)
- if n < 2 then
- error("ReAction.Bar:SetSecureData() requires at least 2 arguments")
- end
- local f = self:GetFrame()
- f:SetAttribute("data-depth",n-1)
- f:SetAttribute("data-value",select(n,...))
- for i = 1, n-1 do
- local key = select(i,...)
- if key == nil then
- error("ReAction.Bar:SetSecureData() - nil table key in argument list (#"..i..")")
- end
- f:SetAttribute("data-key-"..i, key)
- end
- f:Execute(
- [[
- local n = self:GetAttribute("data-depth")
- if n > 0 then
- local value = self:GetAttribute("data-value")
- local t = _G
- for i = 1, n do
- local key = self:GetAttribute("data-key-"..i)
- if not key then return end
- if not t[key] then
- t[key] = newtable()
- end
- if i == n then
- t[key] = value
- else
- t = t[key]
- end
- end
- end
- ]])
- self:RefreshSecureState()
-end
-
-function Bar:SetSecureStateData( state, key, value )
- self:SetSecureData("settings",state,key,value)
-end
-
--- sets a snippet to be run as an extension to _onstate-reaction
-function Bar:SetSecureStateExtension( id, snippet )
- if id == nil then
- error("ReAction.Bar:SetSecureStateExtension() requires an id")
- end
- local f = self:GetFrame()
- f:SetAttribute("input-secure-ext-id",id)
- f:SetAttribute("secure-ext-"..id,snippet)
- f:Execute(
- [[
- local id = self:GetAttribute("input-secure-ext-id")
- if id then
- extensions[id] = self:GetAttribute("secure-ext-"..id) or nil
- end
- ]])
- self:RefreshSecureState()
-end
-
-function Bar:SetFrameRef( name, refFrame )
- if refFrame then
- local _, explicit = refFrame:IsProtected()
- if not explicit then
- refFrame = nil
- end
- end
- if refFrame then
- self:GetFrame():SetFrameRef(name,refFrame)
- else
- self:GetFrame():SetAttribute("frameref-"..name,nil)
- end
-end
-
-function Bar:SetStateDriver( states )
- if states then
- for state, props in pairs(states) do
- self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
- for propname, value in pairs(props) do
- if propname == "anchorFrame" then
- self:SetFrameRef("anchor-"..state, _G[value])
- elseif propname == "rule" then
- -- do nothing
- else
- self:SetSecureStateData(state, propname, value)
- end
- end
- end
- end
- local rule = states and self:BuildStateRule(states)
- if rule then
- RegisterStateDriver(self:GetFrame(),"reaction",rule)
- elseif self.statedriver then
- UnregisterStateDriver(self:GetFrame(),"reaction")
- end
- self.statedriver = rule
- self:BuildStateKeybinds(states)
- self:RefreshSecureState()
-end
-
--- pass unit=nil to set up the unit elsewhere, if you want something more complex
-function Bar:RegisterUnitWatch( unit, enable )
- local f = self:GetFrame()
- if unit then
- f:SetAttribute("unit",unit)
- end
- if enable then
- RegisterUnitWatch(self:GetFrame(),true)
- elseif self.unitwatch then
- UnregisterUnitWatch(self:GetFrame())
- end
- self.unitwatch = enable
- self:RefreshSecureState()
-end
-
-function Bar:SetStateKeybind( key, state )
- local f = self:GetFrame()
- local binds = self.statebinds
- if not binds then
- binds = { }
- self.statebinds = binds
- end
-
- -- clear the old binding, if any
- if binds[state] then
- SetOverrideBinding(f, false, binds[state], nil)
- end
-
- if key then
- SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
- end
- binds[state] = key
-end
-
-function Bar:GetStateKeybind( state )
- if self.statebinds and state then
- return self.statebinds[state]
- end
-end
-
-function Bar:UpdateDefaultStateAnchor()
- local point, frame, relPoint, x, y = self:GetAnchor()
- local f = self:GetFrame()
- f:SetAttribute("defaultAnchor-point",point)
- f:SetAttribute("defaultAnchor-relPoint",relPoint)
- f:SetAttribute("defaultAnchor-x",x)
- f:SetAttribute("defaultAnchor-y",y)
- self:SetFrameRef("defaultAnchor",_G[frame or "UIParent"])
- f:Execute([[
- for _, k in pairs(anchorKeys) do
- defaultAnchor[k] = self:GetAttribute("defaultAnchor-"..k)
- end
- defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
- ]])
-end
-
-function Bar:UpdateDefaultStateAlpha()
- local f = self:GetFrame()
- f:SetAttribute("defaultAlpha",self:GetAlpha())
- f:Execute([[
- defaultAlpha = self:GetAttribute("defaultAlpha")
- ]])
-end
-
----- secure state driver rules ----
-
-local playerClass = select(2, UnitClass("player"))
-local function ClassFilter(...)
- for i = 1, select('#',...) do
- if playerClass == select(i,...) then
- return false
- end
- end
- return true
-end
-
-local ruleformats = {
- stealth = { format = "stealth", filter = ClassFilter("ROGUE","DRUID") },
- nostealth = { format = "nostealth", filter = ClassFilter("ROGUE","DRUID") },
- shadowdance = { format = "bonusbar:2", filter = ClassFilter("ROGUE") },
- shadowform = { format = "form:1", filter = ClassFilter("PRIEST") },
- noshadowform = { format = "noform", filter = ClassFilter("PRIEST") },
- battle = { format = "stance:1", filter = ClassFilter("WARRIOR") },
- defensive = { format = "stance:2", filter = ClassFilter("WARRIOR") },
- berserker = { format = "stance:3", filter = ClassFilter("WARRIOR") },
- caster = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
- bear = { format = "form:1", filter = ClassFilter("DRUID") },
- cat = { format = "form:3", filter = ClassFilter("DRUID") },
- tree = { format = "form:5", filter = ClassFilter("DRUID") },
- moonkin = { format = "form:5", filter = ClassFilter("DRUID") },
- demon = { format = "form:2", filter = ClassFilter("WARLOCK") },
- nodemon = { format = "noform", filter = ClassFilter("WARLOCK") },
- pet = { format = "pet" },
- nopet = { format = "nopet" },
- harm = { format = "@target,harm" },
- help = { format = "@target,help" },
- notarget = { format = "@target,noexists" },
- focusharm = { format = "@focus,harm" },
- focushelp = { format = "@focus,help" },
- nofocus = { format = "@focus,noexists" },
- raid = { format = "group:raid" },
- party = { format = "group:party" },
- solo = { format = "nogroup" },
- combat = { format = "combat" },
- nocombat = { format = "nocombat" },
- possess = { format = "@vehicle,noexists,bonusbar:5" },
- vehicle = { format = "@vehicle,exists,bonusbar:5" },
-}
-
-function Bar.InitRuleFormats()
- local forms = { }
- for i = 1, GetNumShapeshiftForms() do
- local _, name = GetShapeshiftFormInfo(i)
- forms[name] = i;
- end
- -- use 9 if not found since 9 is never a valid stance/form
- local defensive = forms[GetSpellInfo(71)] or 9
- local berserker = forms[GetSpellInfo(2458)] or 9
- local bear = forms[GetSpellInfo(5487)] or 9
- local aquatic = forms[GetSpellInfo(1066)] or 9
- local cat = forms[GetSpellInfo(768)] or 9
- local travel = forms[GetSpellInfo(783)] or 9
- local tree = forms[GetSpellInfo(33891)] or 9
- local moonkin = forms[GetSpellInfo(24858)] or 9
- local flight = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
-
- ruleformats.defensive.format = "stance:"..defensive
- ruleformats.berserker.format = "stance:"..berserker
- ruleformats.caster.format = format("form:0/%d/%d/%d", aquatic, travel, flight)
- ruleformats.bear.format = "form:"..bear
- ruleformats.cat.format = "form:"..cat
- ruleformats.tree.format = "form:"..tree
- ruleformats.moonkin.format = "form:"..moonkin
-end
-
-function Bar:BuildStateRule(states)
- -- states is a table :
- -- states[statename].rule = {
- -- order = #,
- -- type = "default"/"custom"/"any"/"all",
- -- values = { ... }, -- keys of ruleformats[]
- -- custom = "...",
- -- }
- local rules = { }
- local default
-
- for idx, state in ipairs(fieldsort(states, "rule", "order")) do
- local c = states[state].rule
- local type = c.type
- if type == "default" then
- default = default or state
- elseif type == "custom" then
- if c.custom then
- -- strip out all spaces from the custom rule
- table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
- end
- elseif type == "any" or type == "all" then
- if c.values then
- local clauses = { }
- for key, value in pairs(c.values) do
- if ruleformats[key] and not ruleformats[key].filter then
- table.insert(clauses, ruleformats[key].format)
- end
- end
- if #clauses > 0 then
- local sep = (type == "any") and "][" or ","
- table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
- end
- end
- end
- end
- -- make sure that the default, if any, is last
- if default then
- table.insert(rules, default)
- end
- return table.concat(rules,";")
-end
-
-function Bar:BuildStateKeybinds( states )
- if states then
- for name, state in pairs(states) do
- local rule = tfetch(state, "rule")
- if rule and rule.type == "keybind" then
- self:SetStateKeybind(rule.keybind, name)
- else
- self:SetStateKeybind(nil, name) -- this clears an existing keybind
- end
- end
- end
-end
-
diff -r b2b105747466 -r 920d17851a93 classes/Button.lua
--- a/classes/Button.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
---[[
- ReAction Button base class
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local LKB = ReAction.LKB
-local _G = _G
-local CreateFrame = CreateFrame
-local GetBindingKey = GetBindingKey
-local format = string.format
-
--- libraries
-local LBF = LibStub("LibButtonFacade",true) -- optional
-
--- private
-local trash = CreateFrame("Frame")
-local frameList = { }
-local idPools = { }
-
-local function kb_onEnter( frame )
- LKB:Set(frame)
-end
-
--- Button class
-local Button = { }
-
-ReAction.Button = Button -- export to ReAction
-
-function Button:New( name, config, bar, idx, inherits, buttonType )
- buttonType = buttonType or "CheckButton"
-
- -- create new self
- self = setmetatable(
- {
- bar = bar,
- idx = idx,
- config = config,
- name = name,
- },
- { __index = self } )
-
- -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
- -- existing globals. Can't set to nil in the global because it's then tainted.
- -- Caller is responsible for ensuring global uniqueness of names.
- local f = name and frameList[name]
- if f then
- f:SetParent(bar:GetFrame())
- else
- f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
- if name then
- frameList[name] = f
- end
- end
-
- self.frame = f
-
- local frames = { }
- self.frames = frames
- frames.icon = _G[name.."Icon"]
- frames.flash = _G[name.."Flash"]
- frames.hotkey = _G[name.."HotKey"]
- frames.count = _G[name.."Count"]
- frames.name = _G[name.."Name"]
- frames.border = _G[name.."Border"]
- frames.cooldown = _G[name.."Cooldown"]
- frames.normalTexture = _G[name.."NormalTexture"]
-
- if config then
- config.name = name
- end
-
- -- install LibKeyBound handlers onto frame
- function f:GetActionName()
- return format("%s:%s", bar:GetName(), idx)
- end
-
- local clickBinding = format("CLICK %s:LeftButton", name)
- function f:GetHotkey()
- return LKB:ToShortKey(GetBindingKey(clickBinding))
- end
-
- return self
-end
-
-function Button:Destroy()
- local f = self:GetFrame()
- f:UnregisterAllEvents()
- self:ReleaseActionID(self:GetActionID())
- if f then
- f:Hide()
- f:SetParent(trash)
- f:ClearAllPoints()
- end
-end
-
-function Button:GetBar()
- return self.bar
-end
-
-function Button:GetFrame()
- return self.frame
-end
-
-function Button:GetName()
- return self.name
-end
-
-function Button:GetConfig()
- return self.config
-end
-
-function Button:GetActionID()
- -- derived classes should override this
- return nil
-end
-
-function Button:SetActionIDPool( poolID, maxID )
- self.actionPoolID = poolID
- self.actionMaxID = maxID
-end
-
-function Button:AcquireActionID( id, hint, unique )
- local poolID = self.actionPoolID
- local maxID = self.actionMaxID
- if not poolID or not maxID then
- error("AcquireActionID: must setup pool first with SetActionIDPool")
- end
- local pool = idPools[poolID]
- if not pool then
- pool = { nWraps = 0, useCount = { } }
- for i = 1, maxID do
- pool.useCount[i] = 0
- end
- idPools[poolID] = pool
- end
- local useCount = pool.useCount
- if id == nil then
- repeat
- local nWraps = pool.nWraps or 0
- if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then
- id = hint
- else
- local start = hint or 1
- for i = start, maxID do
- if useCount[i] == nil or useCount[i] == nWraps then
- id = i
- break
- end
- end
- if not id then
- for i = 1, start do
- if useCount[i] == nil or useCount[i] == nWraps then
- id = i
- break
- end
- end
- end
- end
- if id == nil then
- if unique then
- return nil
- end
- pool.nWraps = nWraps + 1
- end
- until id ~= nil
- end
- useCount[id] = (useCount[id] or 0) + 1
- return id
-end
-
-function Button:ReleaseActionID( id )
- local poolID = self.actionPoolID
- if not poolID then
- error("ReleaseActionID: must setup pool first with SetActionIDPool")
- end
- local pool = idPools[poolID]
- if pool and id and pool.useCount[id] then
- pool.useCount[id] = pool.useCount[id] - 1
- pool.nWraps = min(pool.useCount[id], pool.nWraps)
- end
-end
-
-function Button:Refresh()
- local f = self:GetFrame()
- self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
-end
-
-function Button:SetKeybindMode( mode )
- local f = self.frame
- if mode then
- self.oldOnEnter = f:GetScript("OnEnter")
- f:SetScript("OnEnter", kb_onEnter)
- elseif self.oldOnEnter then
- f:SetScript("OnEnter", self.oldOnEnter)
- self.oldOnEnter = nil
- end
- self:ShowGridTemp(mode)
- self:UpdateKeybindModeDisplay( mode )
-end
-
-function Button:UpdateKeybindModeDisplay( mode )
- local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
- if border then
- if mode then
- border:SetVertexColor(LKB:GetColorKeyBoundMode())
- border:Show()
- else
- border:Hide()
- end
- end
-end
-
-function Button:UpdateHotkey( hotkey )
- hotkey = hotkey or self.frames.hotkey
- if not hotkey then
- hotkey = _G[self:GetName().."HotKey"]
- self.frames.hotkey = hotkey
- end
- if hotkey then
- local txt = self.frame:GetHotkey()
- hotkey:SetText( txt )
- if txt == nil or txt == "" then
- hotkey:Hide()
- else
- hotkey:Show()
- end
- end
-end
-
-function Button:GetActionIDLabel( create )
- local f = self:GetFrame()
- if not f.actionIDLabel and create then
- local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
- label:SetAllPoints()
- label:SetJustifyH("CENTER")
- label:SetShadowColor(0,0,0,1)
- label:SetShadowOffset(2,-2)
- f.actionIDLabel = label -- store the label with the frame for recycling
- end
- return f.actionIDLabel
-end
-
-function Button:UpdateActionIDLabel( show )
- local label = self:GetActionIDLabel( show )
- if label then
- if show then
- local id = self:GetActionID()
- if id then
- label:SetText(tostring(id))
- label:Show()
- return
- end
- end
- label:Hide()
- end
-end
-
-function Button:SetNormalVertexColor( r, g, b, a )
- if LBF then
- LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
- else
- self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
- end
-end
-
-function Button:GetNormalVertexColor()
- if LBF then
- return LBF:GetNormalVertexColor(self:GetFrame())
- else
- return self:GetFrame():GetNormalTexture():GetVertexColor()
- end
-end
-
-function Button:UpdateShowGrid()
- -- does nothing by default
-end
-
-function Button:ShowGridTemp(show)
- -- does nothing by default
-end
-
-function Button:ShowGrid(show)
- -- does nothing by default
-end
diff -r b2b105747466 -r 920d17851a93 classes/MultiCastButton.lua
--- a/classes/MultiCastButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,744 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local unpack = unpack
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local InCombatLockdown = InCombatLockdown
-local IsUsableSpell = IsUsableSpell
-local IsUsableAction = IsUsableAction
-local IsSpellKnown = IsSpellKnown
-local IsSpellInRange = IsSpellInRange
-local IsActionInRange = IsActionInRange
-local GetSpellInfo = GetSpellInfo
-local GetSpellCooldown = GetSpellCooldown
-local GetActionCooldown = GetActionCooldown
-local GetSpellTexture = GetSpellTexture
-local GetActionTexture = GetActionTexture
-local GetMultiCastTotemSpells = GetMultiCastTotemSpells
-
---[[
- Blizzard Constants:
- - NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4
- - NUM_MULTI_CAST_PAGES = 3
- - SHAMAN_TOTEM_PRIORITIES = { } -- sets the order of the totems
- - TOTEM_MULTI_CAST_SUMMON_SPELLS = { } -- list of summon spellIDs
- - TOTEM_MULTI_CAST_RECALL_SPELLS = { } -- list of recall spellIDs
-
- Blizzard Events:
- - UPDATE_MULTI_CAST_ACTIONBAR
-
- Blizzard APIs:
- - GetMultiCastBarOffset() : returns 6
-
- - SetMultiCastSpell(actionID, spellID) (protected) OR
- SetAttribute("type","multispell")
- SetAttribute("action",actionID)
- SetAttribute("spell",spellID)
-
- note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
- so that's action ID 132-144.
-
- - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
- returns spellIDs for all known totems that fit that slot. This function is available in
- the secure environment.
-
- Blizzard textures:
- All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
- texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
- this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
-
- Each totem button and arrow has a colored border indicating its elemental type.
-
- TODO:
- - make whether to show the colored border configurable (looks really bad with ButtonFacade:Zoomed)
- - apply ButtonFacade to the flyout buttons? Or at least zoom the textures slightly?
- - use a multiplier with SetTexCoord on totem bar texture?
-
- Design Notes:
- - Only the header has a secure context. All other frames execute in its context.
-
- - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are
- GetBonusBarOffset()=6, 132-144) with 3 pages of 4 buttons. The paging is controlled by
- the summon flyout, which is also paged with the summon spells (the recall button is not paged)
-
- - A spell list is updated in the secure context at setup time (TODO: redo setup when learning new
- spells) with the list of spells known for each slot.
-
- - Each button (except recall) has an arrow button which appears on mouseover and when clicked
- opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
- appear.
-
- - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
- of the bar. Each time the flyout panel is opened, the individual buttons grab their corresponding
- spell/type from the list, according to the slot which opened the flyout. Each button either sets
- the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
- actually cast any spells (though, I suppose we could modify this so that e.g. configurable
- right-click casts the spell). The flyout also has a close button which closes the flyout: the
- flyout-open code positions the close button anchored to the last button in the flyout (which
- changes dynamically because each slot has a different number of items in the list).
-
- - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of
- the summon spells is cast from elsewhere.
-
- - The default UI has Call of the Elements always selected on UI load. This module remembers the last
- selected one and restores it.
-
-
-]]--
-
-
---
--- Secure snippets
---
-
--- bar
-local _bar_init = -- function(self)
-[[
- -- set up some globals in the secure environment
- flyout = self:GetFrameRef("flyout")
- flyoutSlot = nil
- summonSlot = self:GetAttribute("summonSlot")
- recallSlot = self:GetAttribute("recallSlot")
- baseActionID = self:GetAttribute("baseActionID")
- slotsPerPage = self:GetAttribute("slotsPerPage")
- currentPage = currentPage or self:GetAttribute("lastSummon") or 1
-
- totemIDsBySlot = newtable()
- for i = 1, slotsPerPage do
- totemIDsBySlot[i] = self:GetAttribute("TOTEM_PRIORITY_"..i)
- end
-
- -- these are set up in bar:SetupBarHeader()
- flyoutChildren = flyoutChildren or newtable()
- summonSpells = summonSpells or newtable()
-]]
-
-local _onstate_multispellpage = -- function(self, stateid, newstate)
-[[
- currentPage = tonumber(newstate)
- control:CallMethod("UpdateLastSummon",currentPage)
- control:ChildUpdate()
-]]
-
-
--- buttons
-local _childupdate = -- function(self, snippetid, message)
-[[
- local t = self:GetAttribute("type")
- self:SetAttribute(t, self:GetAttribute(t.."-page"..currentPage))
-]]
-
-local _onEnter = -- function(self)
- -- for whatever reason, RegisterAutoHide is unreliable
- -- unless you re-anchor the frame prior to calling it.
- -- Even then, it's still not terribly reliable.
-[[
- local slot = self:GetAttribute("bar-idx")
- local arrow = owner:GetFrameRef("arrow-"..slot)
- if arrow and not arrow:IsShown() and not (flyout:IsVisible() and flyoutSlot == slot) then
- arrow:ClearAllPoints()
- arrow:SetPoint("BOTTOM",self,"TOP",0,0)
- arrow:Show()
- arrow:RegisterAutoHide(0)
- arrow:AddToAutoHide(self)
- end
-]]
-
-
--- flyout arrow
-local _arrow_openFlyout = -- function(self)
-[[
- local slot = self:GetAttribute("bar-idx")
- local totemID = totemIDsBySlot[slot - (summonSlot or 0)]
- if totemID == 0 then
- totemID = "summon"
- end
-
- local lastButton, lastPage
- for page, b in ipairs(flyoutChildren) do
- b:Hide()
- b:SetAttribute("totemSlot",totemID)
- if slot == summonSlot then
- local spellID = self:GetParent():GetAttribute("spell-page"..page)
- if spellID then
- b:SetAttribute("type","changePage")
- b:SetAttribute("spell",spellID)
- b:Show()
- lastButton = b
- lastPage = page
- end
- else
- local spell = select(page, 0, GetMultiCastTotemSpells(totemID) )
- if spell then
- b:SetAttribute("type","multispell")
- b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
- b:SetAttribute("spell", spell)
- b:Show()
- lastButton = b
- lastPage = page
- end
- end
- end
-
- local close = owner:GetFrameRef("close")
- if lastButton and close then
- close:ClearAllPoints()
- close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
- close:Show()
- control:CallMethod("UpdateFlyoutTextures",totemID)
- end
-
- flyout:ClearAllPoints()
- flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring
- if lastPage then
- flyout:SetHeight(lastPage * 27 + (close and close:GetHeight() or 0))
- end
- flyout:Show()
- flyout:RegisterAutoHide(1) -- TODO: configurable
- flyout:AddToAutoHide(owner)
- flyoutSlot = slot
- self:Hide()
-]]
-
-local _closeFlyout = -- function(self)
-[[
- flyout:Hide()
-]]
-
-
--- flyout child buttons
-local _flyout_child_preClick = -- function(self, button, down)
-[[
- local button = button
- if self:GetAttribute("type") == "changePage" then
- owner:SetAttribute("state-multispellpage",self:GetAttribute("index"))
- self:GetParent():Hide()
- return false
- else
- return nil, "close"
- end
-]]
-
-local _flyout_child_postClick = -- function(self, message, button, down)
-[[
- if message == "close" then
- self:GetParent():Hide() -- hide flyout after selecting
- end
-]]
-
-
---
--- The Blizzard totem bar textures are all actually one big texture,
--- with texcoord offsets. Shamelessly stolen from FrameXML/MultiCastActionBarFrame.lua
---
-local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
-local FLYOUT_UP_BUTTON_HL_TCOORDS = { 72/128, 92/128, 88/256, 98/256 }
-local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128, 92/128, 69/256, 79/256 }
-
-local SLOT_EMPTY_TCOORDS = {
- [EARTH_TOTEM_SLOT] = { 66/128, 96/128, 3/256, 33/256 },
- [FIRE_TOTEM_SLOT] = { 67/128, 97/128, 100/256, 130/256 },
- [WATER_TOTEM_SLOT] = { 39/128, 69/128, 209/256, 239/256 },
- [AIR_TOTEM_SLOT] = { 66/128, 96/128, 36/256, 66/256 },
-}
-
-local SLOT_OVERLAY_TCOORDS = {
- [EARTH_TOTEM_SLOT] = { 1/128, 35/128, 172/256, 206/256 },
- [FIRE_TOTEM_SLOT] = { 36/128, 70/128, 172/256, 206/256 },
- [WATER_TOTEM_SLOT] = { 1/128, 35/128, 207/256, 240/256 },
- [AIR_TOTEM_SLOT] = { 36/128, 70/128, 137/256, 171/256 },
-}
-
-local FLYOUT_UP_BUTTON_TCOORDS = {
- ["summon"] = { 99/128, 127/128, 84/256, 102/256 },
- [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 160/256, 178/256 },
- [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 122/256, 140/256 },
- [WATER_TOTEM_SLOT] = { 99/128, 127/128, 199/256, 217/256 },
- [AIR_TOTEM_SLOT] = { 99/128, 127/128, 237/256, 255/256 },
-}
-
-local FLYOUT_DOWN_BUTTON_TCOORDS = {
- ["summon"] = { 99/128, 127/128, 65/256, 83/256 },
- [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 141/256, 159/256 },
- [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 103/256, 121/256 },
- [WATER_TOTEM_SLOT] = { 99/128, 127/128, 180/256, 198/256 },
- [AIR_TOTEM_SLOT] = { 99/128, 127/128, 218/256, 236/256 },
-}
-
-local FLYOUT_TOP_TCOORDS = {
- ["summon"] = { 33/128, 65/128, 1/256, 23/256 },
- [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 46/256, 68/256 },
- [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 46/256, 68/256 },
- [WATER_TOTEM_SLOT] = { 0/128, 32/128, 1/256, 23/256 },
- [AIR_TOTEM_SLOT] = { 0/128, 32/128, 91/256, 113/256 },
-}
-
-local FLYOUT_MIDDLE_TCOORDS = {
- ["summon"] = { 33/128, 65/128, 23/256, 43/256 },
- [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 68/256, 88/256 },
- [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 68/256, 88/256 },
- [WATER_TOTEM_SLOT] = { 0/128, 32/128, 23/256, 43/256 },
- [AIR_TOTEM_SLOT] = { 0/128, 32/128, 113/256, 133/256 },
-}
-
-local eventList = {
- "ACTIONBAR_SLOT_CHANGED",
- "ACTIONBAR_UPDATE_STATE",
- "ACTIONBAR_UPDATE_USABLE",
- "ACTIONBAR_UPDATE_COOLDOWN",
- "UPDATE_BINDINGS",
- "UPDATE_MULTI_CAST_ACTIONBAR",
-}
-
---
--- MultiCast Button class
--- Inherits implementation methods from Action button class, but circumvents the constructor
--- and redefines/removes some methods.
---
-local Super = ReAction.Button
-local Action = ReAction.Button.Action
-local MultiCast = setmetatable( { }, { __index = Action } )
-ReAction.Button.MultiCast = MultiCast
-
-function MultiCast:New( idx, btnConfig, bar )
- local maxIndex = bar.nTotemSlots or 0
- if bar.summonSlot then
- maxIndex = maxIndex + 1
- end
- if bar.recallSlot then
- maxIndex = maxIndex + 1
- end
-
- if not bar.hasMulticast or idx > maxIndex then
- return false
- end
-
- if idx < 1 then
- error("invalid index")
- end
-
- local name = format("ReAction_%s_Totem_%d",bar:GetName(),idx)
-
- self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-
- local barFrame = bar:GetFrame()
- local f = self:GetFrame()
-
- -- attributes
- local page = (idx == bar.recallSlot) and 1 or bar:GetConfig().lastSummon or 1
- if idx == bar.recallSlot or idx == bar.summonSlot then
- f:SetAttribute("type","spell")
- local spells = (idx == bar.summonSlot) and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
- f:SetAttribute("spell",spells[page])
- for i, spell in ipairs(spells) do
- if spell and IsSpellKnown(spell) then
- f:SetAttribute("spell-page"..i, spell)
- end
- end
- else
- local offset = bar.summonSlot and 1 or 0
- local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
- local baseAction = barFrame:GetAttribute("baseActionID") + slot
- self.totemSlot = slot
- f:SetAttribute("type","action")
- f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
- for i = 1, NUM_MULTI_CAST_PAGES do
- f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
- end
- if not f.overlayTex then
- local tx = f:CreateTexture("OVERLAY")
- tx:SetTexture(TOTEM_TEXTURE)
- tx:SetTexCoord(unpack(SLOT_OVERLAY_TCOORDS[self.totemSlot]))
- tx:SetWidth(34)
- tx:SetHeight(34)
- tx:SetPoint("CENTER")
- tx:Show()
- f.overlayTex = tx
- end
- end
- f:SetAttribute("bar-idx",idx)
-
- -- non secure scripts
- f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
- f:SetScript("OnEnter", function(frame) self:OnEnter() end)
- f:SetScript("OnLeave", function(frame) self:OnLeave() end)
- f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
- f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
-
- -- secure handlers
- if idx ~= bar.recallSlot then
- f:SetAttribute("_childupdate",_childupdate)
- end
- barFrame:WrapScript(f, "OnEnter", _onEnter)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForClicks("AnyUp")
- for _, evt in pairs(eventList) do
- f:RegisterEvent(evt)
- end
-
- -- Set up a proxy for the icon texture for use with ButtonFacade
- local SetTexCoordRaw = self.frames.icon.SetTexCoord
- self.frames.icon.SetTexCoord = function( tx, ... )
- if self:GetIconTexture() == TOTEM_TEXTURE then
- SetTexCoordRaw(tx,select(2,self:GetIconTexture()))
- else
- SetTexCoordRaw(tx,...)
- end
- end
-
- -- attach to skinner
- bar:SkinButton(self)
-
- f:Show()
-
- -- open arrow and flyout background textures
- if idx ~= bar.recallSlot then
- local arrow = f._arrowFrame or CreateFrame("Button", nil, f, "SecureFrameTemplate")
- f._arrowFrame = arrow
- arrow:SetWidth(28)
- arrow:SetHeight(18)
- arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
- arrow:SetNormalTexture(TOTEM_TEXTURE)
- local slot = self.totemSlot or "summon"
- arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS[slot]) )
- arrow:SetHighlightTexture(TOTEM_TEXTURE)
- arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
- arrow:SetAttribute("bar-idx",idx)
- arrow:Hide()
- barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
- barFrame:SetFrameRef("arrow-"..idx,arrow)
- end
-
- self:Refresh()
-
- return self
-end
-
-function MultiCast:Destroy()
- local barFrame = self.bar:GetFrame()
- local f = self:GetFrame()
- pcall( barFrame.UnwrapScript, barFrame, f, "OnEnter" ) -- ignore errors
- if f._arrowFrame then
- pcall( barFrame.UnwrapScript, barFrame, f._arrowFrame,"OnClick" ) -- ignore errors
- end
- Super.Destroy(self)
-end
-
-function MultiCast:Refresh()
- Super.Refresh(self)
- self:UpdateAction()
-end
-
-function MultiCast:ShowGrid( show )
-end
-
-function MultiCast:ShowGridTemp( show )
-end
-
-function MultiCast:AcquireActionID()
-end
-
-function MultiCast:ReleaseActionID()
-end
-
-function MultiCast:UpdateShowGrid()
-end
-
-function MultiCast:UpdateBorder()
-end
-
-function MultiCast:UpdateMacroText()
-end
-
-function MultiCast:UpdateCount()
-end
-
-function MultiCast:UpdateCheckedState()
- local action = self:GetActionID()
- if action and IsCurrentAction(action) then
- self:GetFrame():SetChecked(1)
- else
- self:GetFrame():SetChecked(0)
- end
-end
-
-function MultiCast:RefreshHasActionAttributes()
-end
-
-function MultiCast:UpdateFlash()
-end
-
-function MultiCast:GetIconTexture()
- local tx
- if self.spellID then
- tx = GetSpellTexture(GetSpellInfo(self.spellID))
- elseif self.actionID then
- tx = GetActionTexture(self.actionID)
- end
- if tx then
- return tx
- else
- return TOTEM_TEXTURE, unpack(SLOT_EMPTY_TCOORDS[self.totemSlot or 1])
- end
-end
-
-function MultiCast:UpdateAction()
- local action = self:GetActionID()
- if action then
- if action ~= self.actionID then
- self.actionID = action
- self:UpdateAll()
- end
- else
- local spellID = self:GetSpellID()
- if spellID ~= self.spellID then
- self.spellID = spellID
- self:UpdateAll()
- end
- end
-end
-
-function MultiCast:GetActionID(page)
- return self:GetFrame():GetAttribute("action")
-end
-
-function MultiCast:GetSpellID(page)
- return self:GetFrame():GetAttribute("spell")
-end
-
-function MultiCast:SetActionID( id )
- error("Can not set action ID of multicast buttons")
-end
-
-function MultiCast:SetTooltip()
- local barFrame = self:GetFrame()
- if GetCVar("UberTooltips") == "1" then
- GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
- else
- GameTooltip:SetOwner(barFrame)
- end
- if self.spellID then
- GameTooltip:SetSpellByID(self.spellID,false,true)
- elseif self.actionID then
- GameTooltip:SetAction(self.actionID)
- end
-end
-
-function MultiCast:GetUsable()
- if self.spellID then
- return IsUsableSpell((GetSpellInfo(self.spellID)))
- elseif self.actionID then
- return IsUsableAction(self.actionID)
- end
-end
-
-function MultiCast:GetInRange()
- if self.spellID then
- return IsSpellInRange((GetSpellInfo(self.spellID))) == 0
- elseif self.actionID then
- return IsActionInRange(self.actionID) == 0
- end
-end
-
-function MultiCast:GetCooldown()
- if self.spellID then
- return GetSpellCooldown((GetSpellInfo(self.spellID)))
- elseif self.actionID then
- return GetActionCooldown(self.actionID)
- else
- return 0, 0, 0
- end
-end
-
-function MultiCast:UPDATE_MULTI_CAST_ACTIONBAR()
- self:UpdateAll()
-end
-
-
---
--- flyout setup
---
-local function ShowFlyoutTooltip(frame)
- if GetCVar("UberTooltips") == "1" then
- GameTooltip_SetDefaultAnchor(GameTooltip, frame)
- else
- GameTooltip:SetOwner(frame)
- end
- local spell = frame:GetAttribute("spell")
- if spell == nil or spell == 0 then
- GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
- else
- GameTooltip:SetSpellByID(spell,false,true)
- end
-end
-
-local function HideFlyoutTooltip()
- GameTooltip:Hide()
-end
-
-local function UpdateFlyoutIcon(frame)
- local spellID = frame:GetAttribute("spell")
- if spellID == 0 or spellID == nil then
- frame.icon:SetTexture(TOTEM_TEXTURE)
- local slot = tonumber(frame:GetAttribute("totemSlot")) or 1
- frame.icon:SetTexCoord( unpack(SLOT_EMPTY_TCOORDS[slot]) )
- else
- frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
- frame.icon:SetTexCoord(0,1,0,1)
- end
-end
-
-function MultiCast.SetupBarHeader( bar ) -- call this as a static method
- local slot = 0
- local nTotemSlots = 0
- local summonSlot = nil
- local recallSlot = nil
-
- -- figure out the capabilities of the character
- for i, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do
- if spell and IsSpellKnown(spell) then
- slot = 1
- summonSlot = 1
- end
- end
-
- for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
- local totem = SHAMAN_TOTEM_PRIORITIES[i];
- if GetTotemInfo(totem) and GetMultiCastTotemSpells(totem) then
- nTotemSlots = nTotemSlots + 1
- slot = slot + 1
- end
- end
-
- slot = slot + 1
- for i, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do
- if spell and IsSpellKnown(spell) then
- recallSlot = slot
- end
- end
-
- if nTotemSlots == 0 then
- bar.hasMulticast = false -- no multicast capability
- return
- end
-
- bar.hasMulticast = true
- bar.summonSlot = summonSlot
- bar.recallSlot = recallSlot
- bar.nTotemSlots = nTotemSlots
-
-
- local f = bar:GetFrame()
-
- -- init bar secure environment
- f:SetAttribute("lastSummon", bar:GetConfig().lastSummon)
- f:SetAttribute("summonSlot", summonSlot)
- f:SetAttribute("recallSlot", recallSlot)
- f:SetAttribute("slotsPerPage", NUM_MULTI_CAST_BUTTONS_PER_PAGE)
- f:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
- for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
- f:SetAttribute("TOTEM_PRIORITY_"..i,p)
- end
- f:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
-
- function f:UpdateLastSummon(value)
- bar:GetConfig().lastSummon = value
- end
-
- -- create flyout container frame and close arrow
- local flyout = bar._flyoutFrame
- if not flyout then
- flyout = CreateFrame("Frame", nil, f, "SecureFrameTemplate")
- bar._flyoutFrame = flyout
- f:SetFrameRef("flyout",flyout)
- flyout.buttons = { }
- flyout:Hide()
- flyout:SetWidth(24)
- flyout:SetHeight(1)
- flyout:SetPoint("BOTTOM",f,"TOP",0,0)
-
- local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
- close:SetWidth(28)
- close:SetHeight(18)
- close:SetPoint("BOTTOM",flyout,"TOP")
- close:SetNormalTexture(TOTEM_TEXTURE)
- close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS["summon"]))
- close:SetHighlightTexture(TOTEM_TEXTURE)
- close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
- f:SetFrameRef("close",close)
- f:WrapScript(close, "OnClick", _closeFlyout)
- close:Show()
-
- local midTx = flyout:CreateTexture("BACKGROUND")
- midTx:SetWidth(32)
- midTx:SetHeight(20)
- midTx:SetPoint("BOTTOM")
- midTx:SetTexture(TOTEM_TEXTURE)
- midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS["summon"]))
- midTx:Show()
-
- local topTx = flyout:CreateTexture("BACKGROUND")
- topTx:SetWidth(32)
- topTx:SetHeight(20)
- topTx:SetTexture(TOTEM_TEXTURE)
- midTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS["summon"]))
- topTx:SetPoint("BOTTOM",midTx,"TOP",0,-10)
- topTx:Show()
-
- function flyout:UpdateTextures(slot)
- slot = slot or "summon"
- close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS[slot]))
- midTx:ClearAllPoints()
- midTx:SetPoint("BOTTOM")
- midTx:SetPoint("TOP",close,"BOTTOM",0,0)
- midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS[slot]))
- topTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS[slot]))
- end
-
- -- create flyout buttons
- for i = 1, 10 do -- maximum 9 spells + 1 empty slot
- local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
- b:SetWidth(24)
- b:SetHeight(24)
- local prev = flyout.buttons[i-1]
- b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
- b.icon = b:CreateTexture("BACKGROUND")
- b.icon:SetAllPoints()
- b.icon:Show()
- b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
- b:GetHighlightTexture():SetBlendMode("ADD")
- b:RegisterForClicks("AnyUp")
- b:SetScript("OnShow",UpdateFlyoutIcon)
- b:SetScript("OnEnter",ShowFlyoutTooltip)
- b:SetScript("OnLeave",HideFlyoutTooltip)
- b:SetAttribute("index",i)
- f:SetAttribute("flyout-child-idx",i)
- f:SetFrameRef("flyout-child",b)
- f:Execute([[
- flyoutChildren = flyoutChildren or newtable()
- flyoutChildren[self:GetAttribute("flyout-child-idx")] = self:GetFrameRef("flyout-child")
- ]])
- f:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
- b:Show()
- flyout.buttons[i] = b
- end
- end
-
- -- scale flyout frame
- local scale = bar:GetButtonSize() / 36
- flyout:SetScale(scale)
-
- function f:UpdateFlyoutTextures(slot)
- flyout:UpdateTextures(slot)
- end
-
- f:Execute(_bar_init)
-end
-
diff -r b2b105747466 -r 920d17851a93 classes/Overlay.lua
--- a/classes/Overlay.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,754 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local LKB = ReAction.LKB
-local CreateFrame = CreateFrame
-local InCombatLockdown = InCombatLockdown
-local floor = math.floor
-local min = math.min
-local format = string.format
-local GameTooltip = GameTooltip
-local Bar = ReAction.Bar
-local GetSize = Bar.GetSize
-local SetSize = Bar.SetSize
-local GetButtonSize = Bar.GetButtonSize
-local GetButtonGrid = Bar.GetButtonGrid
-local SetButtonSize = Bar.SetButtonSize
-local SetButtonGrid = Bar.SetButtonGrid
-local ApplyAnchor = Bar.ApplyAnchor
-local GameTooltipTextRight1 = GameTooltipTextRight1
-local GameTooltipTextRight2 = GameTooltipTextRight2
-local GameTooltipTextRight3 = GameTooltipTextRight3
-
---
--- Wrap some of the bar manipulators to make them state-aware
---
-local function SetAnchor( bar, point, frame, relPoint, x, y )
- local state = bar:GetSecureState()
- if state then
- local anchorstate = bar:GetStateProperty(state, "anchorEnable")
- if anchorstate then
- bar:SetStateProperty(state, "anchorFrame", frame)
- bar:SetStateProperty(state, "anchorPoint", point)
- bar:SetStateProperty(state, "anchorRelPoint", relPoint)
- bar:SetStateProperty(state, "anchorX", x or 0)
- bar:SetStateProperty(state, "anchorY", y or 0)
- bar:SetAnchor(bar:GetAnchor())
- return
- end
- end
- bar:SetAnchor(point, frame, relPoint, x, y)
-end
-
-local function GetStateScale( bar )
- local state = bar:GetSecureState()
- if state and bar:GetStateProperty(state, "enableScale") then
- return bar:GetStateProperty(state, "scale")
- end
-end
-
-local function SetStateScale( bar, scale )
- local state = bar:GetSecureState()
- if state and bar:GetStateProperty(state, "enableScale") then
- bar:SetStateProperty(state, "scale", scale)
- end
-end
-
-
---
--- Bar config overlay
---
-
-local function GetNormalTextColor()
- return 1.0, 1.0, 1.0, 1.0
-end
-
-local function GetAnchoredTextColor()
- return 1.0, 1.0, 1.0, 1.0
-end
-
-local function GetNormalBgColor()
- return 0.7, 0.7, 1.0, 0.3
-end
-
-local function GetAnchoredBgColor()
- return 0.9, 0.2, 0.7, 0.3
-end
-
-local function StoreSize(bar)
- local f = bar:GetFrame()
- SetSize( bar, f:GetWidth(), f:GetHeight() )
-end
-
-local function StoreExtents(bar)
- local f = bar:GetFrame()
- local p, fr, rp, x, y = f:GetPoint(1)
- fr = fr and fr:GetName() or "UIParent"
- SetAnchor( bar, p, fr, rp, x, y )
- SetSize( bar, f:GetWidth(), f:GetHeight() )
-end
-
-local function RecomputeButtonSize(bar)
- local w, h = GetSize(bar)
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
-
- local scaleW = (floor(w/c) - s) / bw
- local scaleH = (floor(h/r) - s) / bh
- local scale = min(scaleW, scaleH)
-
- SetButtonSize(bar, scale * bw, scale * bh, s)
-end
-
-local function ComputeBarScale(bar, overlay)
- local w, h = overlay:GetWidth() - 8, overlay:GetHeight() - 8
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
-
- local scaleW = w / (c*(bw+s))
- local scaleH = h / (r*(bh+s))
- local scale = min(scaleW, scaleH)
-
- if scale > 2.5 then
- scale = 2.5
- elseif scale < 0.25 then
- scale = 0.25
- end
-
- return scale
-end
-
-local function RecomputeButtonSpacing(bar)
- local w, h = GetSize(bar)
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
-
- SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
-end
-
-local function RecomputeGrid(bar)
- local w, h = GetSize(bar)
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
-
- SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
-end
-
-local function ClampToButtons(bar)
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
- SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1)
-end
-
-local function HideGameTooltip()
- GameTooltip:Hide()
-end
-
-local anchorInside = { inside = true }
-local anchorOutside = { outside = true }
-local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" }
-local oppositeEdges = {
- TOP = "BOTTOM",
- BOTTOM = "TOP",
- LEFT = "RIGHT",
- RIGHT = "LEFT"
-}
-local pointsOnEdge = {
- BOTTOM = { "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", },
- TOP = { "TOP", "TOPLEFT", "TOPRIGHT", },
- RIGHT = { "RIGHT", "BOTTOMRIGHT", "TOPRIGHT", },
- LEFT = { "LEFT", "BOTTOMLEFT", "TOPLEFT", },
-}
-local edgeSelector = {
- BOTTOM = 1, -- select x of x,y
- TOP = 1, -- select x of x,y
- LEFT = 2, -- select y of x,y
- RIGHT = 2, -- select y of x,y
-}
-local snapPoints = {
- [anchorOutside] = {
- BOTTOMLEFT = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"},
- BOTTOM = {"TOP"},
- BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"},
- RIGHT = {"LEFT"},
- TOPRIGHT = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"},
- TOP = {"BOTTOM"},
- TOPLEFT = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"},
- LEFT = {"RIGHT"},
- CENTER = {"CENTER"}
- },
- [anchorInside] = {
- BOTTOMLEFT = {"BOTTOMLEFT"},
- BOTTOM = {"BOTTOM"},
- BOTTOMRIGHT = {"BOTTOMRIGHT"},
- RIGHT = {"RIGHT"},
- TOPRIGHT = {"TOPRIGHT"},
- TOP = {"TOP"},
- TOPLEFT = {"TOPLEFT"},
- LEFT = {"LEFT"},
- CENTER = {"CENTER"}
- }
-}
-local insidePointOffsetFuncs = {
- BOTTOMLEFT = function(x, y) return x, y end,
- BOTTOM = function(x, y) return 0, y end,
- BOTTOMRIGHT = function(x, y) return -x, y end,
- RIGHT = function(x, y) return -x, 0 end,
- TOPRIGHT = function(x, y) return -x, -y end,
- TOP = function(x, y) return 0, -y end,
- TOPLEFT = function(x, y) return x, -y end,
- LEFT = function(x, y) return x, 0 end,
- CENTER = function(x, y) return x, y end,
-}
-local pointCoordFuncs = {
- BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end,
- BOTTOM = function(f) return nil, f:GetBottom() end,
- BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
- RIGHT = function(f) return f:GetRight(), nil end,
- TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end,
- TOP = function(f) return nil, f:GetTop() end,
- TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end,
- LEFT = function(f) return f:GetLeft(), nil end,
- CENTER = function(f) return f:GetCenter() end,
-}
-local edgeBoundsFuncs = {
- BOTTOM = function(f) return f:GetLeft(), f:GetRight() end,
- LEFT = function(f) return f:GetBottom(), f:GetTop() end
-}
-edgeBoundsFuncs.TOP = edgeBoundsFuncs.BOTTOM
-edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT
-local cornerTexCoords = {
- -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
- TOPLEFT = { 1, 1, 1, 0, 0, 1, 0, 0 },
- TOPRIGHT = { 1, 0, 0, 0, 1, 1, 0, 1 },
- BOTTOMLEFT = { 0, 1, 1, 1, 0, 0, 1, 0 },
- BOTTOMRIGHT = { 0, 0, 0, 1, 1, 0, 1, 1 },
-}
-
--- Returns absolute coordinates x,y of the named point 'p' of frame 'f'
-local function GetPointCoords( f, p )
- local x, y = pointCoordFuncs[p](f)
- if not(x and y) then
- local cx, cy = f:GetCenter()
- x = x or cx
- y = y or cy
- end
- return x, y
-end
-
-
--- Returns true if frame 'f1' can be anchored to frame 'f2'
-local function CheckAnchorable( f1, f2 )
- -- can't anchor a frame to itself or to nil
- if f1 == f2 or f2 == nil then
- return false
- end
-
- -- can always anchor to UIParent
- if f2 == UIParent then
- return true
- end
-
- -- also can't do circular anchoring of frames
- -- walk the anchor chain, which generally shouldn't be that expensive
- -- (who nests draggables that deep anyway?)
- for i = 1, f2:GetNumPoints() do
- local _, f = f2:GetPoint(i)
- if not f then f = f2:GetParent() end
- return CheckAnchorable(f1,f)
- end
-
- return true
-end
-
--- Returns true if frames f1 and f2 specified edges overlap
-local function CheckEdgeOverlap( f1, f2, e )
- local l1, u1 = edgeBoundsFuncs[e](f1)
- local l2, u2 = edgeBoundsFuncs[e](f2)
- return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2
-end
-
--- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2
-local function CheckPointEdgeOverlap( f1, p1, f2, e2 )
- local l, u = edgeBoundsFuncs[e2](f2)
- local x, y = GetPointCoords(f1,p1)
- x = select(edgeSelector[e2], x, y)
- return l <= x and x <= u
-end
-
--- Returns the distance between corresponding edges. It is
--- assumed that the passed in edges e1 and e2 are the same or opposites
-local function GetEdgeDistance( f1, f2, e1, e2 )
- local x1, y1 = pointCoordFuncs[e1](f1)
- local x2, y2 = pointCoordFuncs[e2](f2)
- return math.abs((x1 or y1) - (x2 or y2))
-end
-
-local globalSnapTargets = { [UIParent] = anchorInside }
-
-local function GetClosestFrameEdge(f1,f2,a)
- local dist, edge, opp
- if f2:IsVisible() and CheckAnchorable(f1,f2) then
- for _, e in pairs(edges) do
- local o = a.inside and e or oppositeEdges[e]
- if CheckEdgeOverlap(f1,f2,e) then
- local d = GetEdgeDistance(f1, f2, e, o)
- if not dist or (d < dist) then
- dist, edge, opp = d, e, o
- end
- end
- end
- end
- return dist, edge, opp
-end
-
-local function GetClosestVisibleEdge( f )
- local r, o, e1, e2
- local a = anchorOutside
- for _, b in ReAction:IterateBars() do
- local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a)
- if d and (not r or d < r) then
- r, o, e1, e2 = d, b:GetFrame(), e, opp
- end
- end
- for f2, a2 in pairs(globalSnapTargets) do
- local d, e, opp = GetClosestFrameEdge(f,f2,a2)
- if d and (not r or d < r) then
- r, o, e1, e2, a = d, f2, e, opp, a2
- end
- end
- return o, e1, e2, a
-end
-
-local function GetClosestVisiblePoint(f1)
- local f2, e1, e2, a = GetClosestVisibleEdge(f1)
- if f2 then
- local rsq, p, rp, x, y
- -- iterate pointsOnEdge in order and use < to prefer edge centers to corners
- for _, p1 in ipairs(pointsOnEdge[e1]) do
- if CheckPointEdgeOverlap(f1,p1,f2,e2) then
- for _, p2 in pairs(snapPoints[a][p1]) do
- local x1, y1 = GetPointCoords(f1,p1)
- local x2, y2 = GetPointCoords(f2,p2)
- local dx = x1 - x2
- local dy = y1 - y2
- local rsq2 = dx*dx + dy*dy
- if not rsq or rsq2 < rsq then
- rsq, p, rp, x, y = rsq2, p1, p2, dx, dy
- end
- end
- end
- end
- return f2, p, rp, x, y
- end
-end
-
-local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff)
- local o, p, rp, x, y = GetClosestVisiblePoint(f1)
- local s = false
-
- local insideOffsetFunc = p and insidePointOffsetFuncs[p]
- local coordFunc = p and pointCoordFuncs[p]
- if not insideOffsetFunc or not coordFunc then
- return
- end
-
- local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0)
- local xx, yy = coordFunc(f1)
- if xx and yy then
- if math.abs(x) <= rx then
- if math.abs(y) <= ry then
- x = sx
- y = sy
- s = true
- elseif CheckEdgeOverlap(f1,o,"LEFT") then
- x = sx
- s = true
- end
- elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then
- y = sy
- s = true
- end
- elseif xx then
- if math.abs(x) <= rx then
- x = sx
- s = true
- if math.abs(y) <= ry then
- y = sy
- end
- end
- elseif yy then
- if math.abs(y) <= ry then
- y = sy
- s = true
- if math.abs(x) <= rx then
- x = sx
- end
- end
- end
-
- -- correct for some Lua oddities with doubles
- if x == -0 then x = 0 end
- if y == -0 then y = 0 end
-
- if s then
- return o, p, rp, math.floor(x), math.floor(y)
- end
-end
-
-local function CreateSnapIndicator()
- local si = CreateFrame("Frame",nil,UIParent)
- si:SetFrameStrata("HIGH")
- si:SetHeight(16)
- si:SetWidth(16)
- local tex = si:CreateTexture()
- tex:SetAllPoints()
- tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
- tex:SetBlendMode("ADD")
- tex:SetDrawLayer("OVERLAY")
- return si
-end
-
-local si1 = CreateSnapIndicator()
-local si2 = CreateSnapIndicator()
-
-local function DisplaySnapIndicator( f, rx, ry, xOff, yOff )
- local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff)
- if o then
- si1:ClearAllPoints()
- si2:ClearAllPoints()
- si1:SetPoint("CENTER", f, p, 0, 0)
- local xx, yy = pointCoordFuncs[rp](o)
- x = math.abs(x) <=rx and xx and 0 or x
- y = math.abs(y) <=ry and yy and 0 or y
- si2:SetPoint("CENTER", o, rp, x, y)
- si1:Show()
- si2:Show()
- else
- if si1:IsVisible() then
- si1:Hide()
- si2:Hide()
- end
- end
- return o, p
-end
-
-local function HideSnapIndicator()
- if si1:IsVisible() then
- si1:Hide()
- si2:Hide()
- end
-end
-
-local function UpdateLabelString(overlay)
- local label = overlay.labelString
- if label then
- local name = overlay.labelName
- if name and overlay.labelSubtext then
- name = format("%s (%s)", name, overlay.labelSubtext)
- end
- label:SetText(name or "")
- end
-end
-
-local function CreateControls(bar)
- local f = bar:GetFrame()
-
- f:SetMovable(true)
- f:SetResizable(true)
-
- -- child of UIParent so that alpha and scale doesn't propagate to it
- local overlay = CreateFrame("Button", nil, UIParent)
- overlay:EnableMouse(true)
- overlay:SetFrameLevel(10) -- set it above the buttons
- overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4)
- overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4)
- overlay:SetBackdrop({
- edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
- tile = true,
- tileSize = 16,
- edgeSize = 16,
- insets = { left = 0, right = 0, top = 0, bottom = 0 },
- })
-
- -- textures
- local bgTex = overlay:CreateTexture(nil,"BACKGROUND")
- bgTex:SetTexture(0.7,0.7,1.0,0.2)
- bgTex:SetPoint("TOPLEFT",4,-4)
- bgTex:SetPoint("BOTTOMRIGHT",-4,4)
- local hTex = overlay:CreateTexture(nil,"HIGHLIGHT")
- hTex:SetTexture(0.7,0.7,1.0,0.2)
- hTex:SetPoint("TOPLEFT",4,-4)
- hTex:SetPoint("BOTTOMRIGHT",-4,4)
- hTex:SetBlendMode("ADD")
- local aTex = overlay:CreateTexture(nil,"ARTWORK")
- aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
- aTex:SetWidth(16)
- aTex:SetHeight(16)
- aTex:Hide()
-
- -- label
- local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
- label:SetAllPoints()
- label:SetJustifyH("CENTER")
- label:SetShadowColor(0,0,0,1)
- label:SetShadowOffset(3,-3)
- label:SetTextColor(GetNormalTextColor())
- label:SetText(bar:GetName())
- label:Show()
- overlay.labelString = label
- overlay.labelName = bar:GetName()
-
- local function UpdateAnchorDecoration()
- local point, anchor, relPoint, x, y = f:GetPoint(1)
- if point then
- local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
- if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then
- bgTex:SetTexture( GetAnchoredBgColor() )
- hTex:SetTexture( GetAnchoredBgColor() )
- label:SetTextColor( GetAnchoredTextColor() )
- aTex:ClearAllPoints()
- aTex:SetPoint(point)
- aTex:Show()
- return
- end
- end
- bgTex:SetTexture( GetNormalBgColor() )
- hTex:SetTexture( GetNormalBgColor() )
- label:SetTextColor( GetNormalTextColor() )
- aTex:Hide()
- end
-
- local function StopResize()
- f:StopMovingOrSizing()
- f.isMoving = false
- f:SetScript("OnUpdate",nil)
- StoreSize(bar)
- ClampToButtons(bar)
- ReAction:RefreshEditor()
- end
-
- local function CornerUpdate()
- local bw, bh = GetButtonSize(bar)
- local r, c, s = GetButtonGrid(bar)
- local ss = GetStateScale(bar)
- if IsShiftKeyDown() then
- if ss then
- f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss )
- f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss )
- scale = ComputeBarScale(bar, overlay)
- else
- f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
- f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 )
- RecomputeButtonSize(bar)
- end
- elseif not ss and IsAltKeyDown() then
- f:SetMinResize( bw*c, bh*r )
- f:SetMaxResize( 2*bw*c, 2*bh*r )
- RecomputeButtonSpacing(bar)
- else
- f:SetMinResize( bw+s+1, bh+s+1 )
- f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 )
- RecomputeGrid(bar)
- end
- GameTooltipTextRight2:SetText(format("%d x %d",r,c))
-
- local ss = GetStateScale(bar)
- if ss then
- GameTooltipTextRight4:SetText(format("%d%%", scale*100))
- else
- local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
- GameTooltipTextRight3:SetText(size)
- GameTooltipTextRight4:SetText(tostring(s))
- end
- end
-
- -- corner drag handles
- for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
- local corner = CreateFrame("Frame",nil,overlay)
- corner:EnableMouse(true)
- corner:SetWidth(16)
- corner:SetHeight(16)
- corner:SetPoint(point)
-
- local tex = corner:CreateTexture(nil,"HIGHLIGHT")
- tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner")
- tex:SetTexCoord(unpack(cornerTexCoords[point]))
- tex:SetBlendMode("ADD")
- tex:SetAlpha(0.6)
- tex:SetAllPoints()
-
- corner:SetScript("OnMouseDown",
- function(_,btn)
- f:SetScript("OnUpdate", CornerUpdate)
- f:StartSizing(point)
- end
- )
- corner:SetScript("OnMouseUp",
- function()
- local ss = GetStateScale(bar)
- if ss then
- SetStateScale(bar, ComputeBarScale(bar, overlay))
- end
- StopResize()
- end)
- corner:SetScript("OnEnter",
- function()
- local bw, bh = GetButtonSize(bar)
- local r, c, s = bar:GetButtonGrid()
- local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
- local ss = GetStateScale(bar)
- local state = bar:GetSecureState()
- GameTooltip:SetOwner(f, "ANCHOR_"..point)
- if ss then
- GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
- else
- GameTooltip:AddLine(bar:GetName())
- end
- GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c))
- if ss then
- GameTooltip:AddLine(L["State Scale Override"])
- GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100))
- else
- GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size)))
- GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"], L["to change spacing:"]), tostring(floor(s)))
- end
- GameTooltip:Show()
- end
- )
- corner:SetScript("OnLeave",
- function()
- GameTooltip:Hide()
- f:SetScript("OnUpdate",nil)
- end
- )
- end
-
- overlay:RegisterForDrag("LeftButton")
- overlay:RegisterForClicks("RightButtonUp")
-
- overlay:SetScript("OnDragStart",
- function()
- f:StartMoving()
- f.isMoving = true
- local w,h = bar:GetButtonSize()
- f:ClearAllPoints()
- UpdateAnchorDecoration()
- f:SetScript("OnUpdate", function()
- if IsShiftKeyDown() then
- local f, p = DisplaySnapIndicator(f,w,h)
- else
- HideSnapIndicator()
- end
- end)
- end
- )
-
- local function UpdateDragTooltip()
- GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
- local ss = GetStateScale(bar)
- local state = bar:GetSecureState()
- if ss then
- GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
- else
- GameTooltip:AddLine(bar:GetName())
- end
- GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"]))
- GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"]))
- GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."]))
- local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1)
- if point then
- local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
- if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then
- frame = frame or UIParent
- GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName()))
- end
- end
- GameTooltip:Show()
- end
-
- overlay:SetScript("OnDragStop",
- function()
- f:StopMovingOrSizing()
- f.isMoving = false
- f:SetScript("OnUpdate",nil)
-
- if IsShiftKeyDown() then
- local w, h = bar:GetButtonSize()
- local a, p, rp, x, y = GetClosestPointSnapped(f,w,h)
- if a then
- f:ClearAllPoints()
- f:SetPoint(p,a,rp,x,y)
- end
- HideSnapIndicator()
- end
-
- StoreExtents(bar)
- ReAction:RefreshEditor()
- UpdateDragTooltip()
- UpdateAnchorDecoration()
- end
- )
-
- overlay:SetScript("OnEnter",
- function()
- UpdateDragTooltip()
- end
- )
-
- overlay:SetScript("OnLeave", HideGameTooltip)
-
- overlay:SetScript("OnClick",
- function()
- ReAction:ShowEditor(bar)
- end
- )
-
- function overlay:RefreshControls()
- UpdateAnchorDecoration()
- end
-
- overlay:SetScript("OnShow", overlay.RefreshControls)
-
- if ReAction:GetKeybindMode() then
- overlay:SetFrameLevel(1)
- end
-
- UpdateLabelString(overlay)
- UpdateAnchorDecoration()
-
- return overlay
-end
-
-
--- export methods to the Bar prototype
-Bar.Overlay = { }
-function Bar.Overlay:New( bar )
- return setmetatable( {frame = CreateControls(bar)}, {__index=self} )
-end
-
-function Bar.Overlay:SetLabel(name)
- self.frame.labelName = name
- UpdateLabelString(self.frame)
-end
-
-function Bar.Overlay:SetLabelSubtext(text)
- self.frame.labelSubtext = text
- UpdateLabelString(self.frame)
-end
-
-function Bar.Overlay:Show()
- self.frame:Show()
-end
-
-function Bar.Overlay:Hide()
- self.frame:Hide()
-end
-
-function Bar.Overlay:IsShown()
- return self.frame:IsShown()
-end
-
-function Bar.Overlay:RefreshControls()
- self.frame:RefreshControls()
-end
\ No newline at end of file
diff -r b2b105747466 -r 920d17851a93 classes/PetActionButton.lua
--- a/classes/PetActionButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,286 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local InCombatLockdown = InCombatLockdown
-local GetPetActionInfo = GetPetActionInfo
-local GetPetActionSlotUsable = GetPetActionSlotUsable
-local GetPetActionCooldown = GetPetActionCooldown
-local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
-local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
-local SetDesaturation = SetDesaturation
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-
---
--- Secure snippets
--- These are run within the context of the bar's sandbox, as the
--- buttons themselves do not have their own sandbox.
---
-local _onDragStart = -- function(self, button, kind, value, ...)
-[[
- if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
- return kind, value, ...
- else
- return "petaction", self:GetAttribute("action")
- end
-]]
-
-local _onReceiveDrag = -- function(self, button, kind, value, ...)
-[[
- if kind then -- pet spells on the cursor return nil from GetCursorInfo(), which is very strange
- return kind, value, ...
- end
- return "petaction", self:GetAttribute("action")
-]]
-
---
--- private
---
-local eventList = {
-"PLAYER_CONTROL_LOST",
-"PLAYER_CONTROL_GAINED",
-"PLAYER_FARSIGHT_FOCUS_CHANGED",
-"UNIT_PET",
-"UNIT_FLAGS",
-"UNIT_AURA",
-"PET_BAR_UPDATE",
-"PET_BAR_UPDATE_COOLDOWN",
-"PET_BAR_UPDATE_USABLE",
-"UPDATE_BINDINGS",
-}
-
---
--- Pet Action Button class
---
-local Super = ReAction.Button
-local Pet = setmetatable( { }, { __index = Super } )
-ReAction.Button.PetAction = Pet
-
-function Pet:New( idx, config, bar, idHint )
- local name = format("ReAction_%s_PetAction_%d",bar:GetName(),idx)
-
- self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-
- local f = self:GetFrame()
- if not f.autoCastTexture then
- -- store autocast stuff with the frame for recycling
- local tex = f:CreateTexture(nil,"OVERLAY")
- tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]])
- tex:SetHeight(58)
- tex:SetWidth(58)
- tex:SetPoint("CENTER")
- f.autoCastTexture = tex
- f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") -- create after autocast texture so it's on top
- -- move the cooldown around
- local cd = self.frames.cooldown
- cd:ClearAllPoints()
- cd:SetWidth(33)
- cd:SetHeight(33)
- cd:SetPoint("CENTER", f, "CENTER", -2, -1)
- -- resize to 30x30
- f:SetHeight(30)
- f:SetWidth(30)
- local nt = _G[name.."NormalTexture"]
- nt:SetHeight(54)
- nt:SetWidth(54)
- end
- local barFrame = bar:GetFrame()
-
- -- set up the base action ID
- self:SetActionIDPool("pet",10)
- config.actionID = self:AcquireActionID(config.actionID, idHint, true)
-
- -- attribute setup
- -- There's no secure way to do PetAutoCastToggle by actionID, so use
- -- a click-through proxy to the Blizzard pet buttons for right-click
- -- Note that technically this doesn't do PetStopAttack() when
- -- IsPetAttackActive() is true: however that's only true when using
- -- Eyes of the Beast and appears not to really do anything (at least
- -- I can't find any difference)
- f:SetAttribute("type","pet")
- f:SetAttribute("type2","click")
- f:SetAttribute("clickbutton2",_G["PetActionButton"..config.actionID])
- f:SetAttribute("action",config.actionID)
- f:SetAttribute("checkselfcast", true)
- f:SetAttribute("checkfocuscast", true)
-
- -- non secure scripts
- f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
- f:SetScript("OnEnter", function(frame) self:OnEnter() end)
- f:SetScript("OnLeave", function(frame) self:OnLeave() end)
- f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
- f:SetScript("PreClick", function(frame) self:PreClick() end)
- f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
- f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
-
- -- secure handlers
- barFrame:WrapScript(f, "OnDragStart", _onDragStart)
- barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForDrag("LeftButton", "RightButton")
- f:RegisterForClicks("AnyUp")
- for _, evt in pairs(eventList) do
- f:RegisterEvent(evt)
- end
-
- -- attach to skinner
- bar:SkinButton(self,
- {
- AutoCast = f.autoCastShine,
- AutoCastable = f.autoCastTexture
- })
-
- self:Refresh()
- f:Show()
-
- return self
-end
-
-function Pet:Refresh()
- Super.Refresh(self)
- self:Update()
- self:UpdateHotkey()
-end
-
-function Pet:GetActionID()
- return self.config.actionID
-end
-
-function Pet:SetActionID(id)
- if not InCombatLockdown() then
- if id < 0 or id > 10 then
- ReAction:UserError(L["Pet action ID range is 1-10"])
- return
- end
- self.config.actionID = id
- f:SetAttribute("clickbutton2",_G["PetActionButton"..id])
- f:SetAttribute("action",id)
- self:Update()
- self:UpdateHotkey()
- end
-end
-
-function Pet:Update()
- local action = self.config.actionID
- local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(action)
- local f = self:GetFrame()
- local icon = self.frames.icon
-
- if isToken then
- icon:SetTexture(_G[texture])
- self.tooltipName = _G[name]
- else
- icon:SetTexture(texture)
- self.tooltipName = name
- end
-
- self.isToken = isToken
- self.tooltipSubtext = subtext
- f:SetChecked( isActive and 1 or 0 )
-
- if autoCastAllowed then
- f.autoCastTexture:Show()
- else
- f.autoCastTexture:Hide()
- end
-
- if autoCastEnabled then
- AutoCastShine_AutoCastStart(f.autoCastShine)
- else
- AutoCastShine_AutoCastStop(f.autoCastShine)
- end
-
- if texture then
- if GetPetActionSlotUsable(action) then
- SetDesaturation(icon,nil)
- else
- SetDesaturation(icon,1)
- end
- icon:Show()
- f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
- else
- icon:Hide()
- f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
- end
-
- self:UpdateCooldown()
-end
-
-function Pet:UpdateCooldown()
- CooldownFrame_SetTimer(self.frames.cooldown, GetPetActionCooldown(self.config.actionID))
-end
-
-function Pet:SetTooltip()
- if self.tooltipName then
- local f = self:GetFrame()
- local uber = GetCVar("UberTooltips")
- if self.isToken or (uber == "0") then
- if uber == "0" then
- GameTooltip:SetOwner(f, "ANCHOR_RIGHT")
- else
- GameTooltip_SetDefaultAnchor(GameTooltip, f)
- end
- GameTooltip:SetText(self.tooltipName)
- if self.tooltipSubtext then
- GameTooltip:AddLine(self.tooltipSubtext, "", 0.5, 0.5, 0.5)
- end
- GameTooltip:Show()
- else
- GameTooltip_SetDefaultAnchor(GameTooltip, f)
- GameTooltip:SetPetAction(self.config.actionID)
- end
- else
- GameTooltip:Hide()
- end
-end
-
-function Pet:OnEvent(event, unit)
- if event =="PET_BAR_UPDATE_COOLDOWN" then
- self:UpdateCooldown()
- elseif event == "UPDATE_BINDINGS" then
- self:UpdateHotkey()
- elseif event == "UNIT_PET" then
- if unit == "player" then
- self:Update()
- end
- elseif event == "UNIT_FLAGS" or event == "UNIT_AURA" then
- if unit == "pet" then
- self:Update()
- end
- else
- self:Update()
- end
-end
-
-function Pet:OnEnter()
- self:SetTooltip()
-end
-
-function Pet:OnLeave()
- GameTooltip:Hide()
-end
-
-function Pet:OnAttributeChanged(attr,value)
- self:Update()
-end
-
-function Pet:PreClick()
- self:GetFrame():SetChecked(0)
-end
-
-function Pet:OnDragStart()
- self:SetChecked(0)
- self:Update()
-end
-
-function Pet:OnReceiveDrag()
- self:SetChecked(0)
- self:Update()
-end
-
diff -r b2b105747466 -r 920d17851a93 classes/StanceButton.lua
--- a/classes/StanceButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local InCombatLockdown = InCombatLockdown
-local GetNumShapeshiftForms = GetNumShapeshiftForms
-local GetShapeshiftFormInfo = GetShapeshiftFormInfo
-local IsUsableSpell = IsUsableSpell
-local GetSpellInfo = GetSpellInfo
-
---
--- private
---
-local playerClass = select(2,UnitClass("player"))
-
-local eventList = {
- "PLAYER_REGEN_ENABLED",
- "PLAYER_ENTERING_WORLD",
- "UPDATE_SHAPESHIFT_FORM",
- "UPDATE_SHAPESHIFT_FORMS",
- "UPDATE_SHAPESHIFT_USABLE",
- "UPDATE_SHAPESHIFT_COOLDOWN",
- "UPDATE_BINDINGS",
-}
-
---
--- Stance Button class
---
-local Super = ReAction.Button
-local Stance = setmetatable( { }, { __index = Super } )
-ReAction.Button.Stance = Stance
-
-function Stance:New( idx, moduleConfig, bar, idHint )
- local name = format("ReAction_%s_Stance_%d",bar:GetName(),idx)
-
- self = Super.New(self, name, moduleConfig.buttons[bar:GetName()][idx], bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
- self.moduleConfig = moduleConfig
-
- local f = self:GetFrame()
- local barFrame = bar:GetFrame()
- local config = self:GetConfig()
-
- -- set up the base stance ID
- self:SetActionIDPool("stance",8)
- config.stanceID = self:AcquireActionID(config.stanceID, idHint, true)
-
- -- attribute setup
- f:SetAttribute("type","spell")
-
- -- non secure scripts
- f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
- f:SetScript("OnEnter", function(frame) self:OnEnter() end)
- f:SetScript("OnLeave", function(frame) self:OnLeave() end)
- f:SetScript("PreClick", function(frame, ...) self:PreClick(...) end)
-
- -- secure handlers
- -- (none)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForClicks("AnyUp")
- for _, evt in pairs(eventList) do
- f:RegisterEvent(evt)
- end
-
- -- attach to skinner
- bar:SkinButton(self)
-
- -- initial display
- if ReAction:GetConfigMode() then
- self:GetFrame():Show()
- end
-
- self:Refresh()
-
- return self
-end
-
-function Stance:GetActionID()
- return self.config.stanceID
-end
-
-function Stance:UpdateAction()
- if InCombatLockdown() then
- self.updatePending = true
- else
- self.updatePending = false
- local idx = self:GetActionID()
- local f = self:GetFrame()
- if idx > GetNumShapeshiftForms() then
- f:Hide()
- else
- f:SetAttribute("spell", select(2,GetShapeshiftFormInfo(idx)))
- f:Show()
- self:Update()
- end
- end
-end
-
-function Stance:Refresh()
- Super.Refresh(self)
- self:UpdateHotkey()
- self:UpdateAction()
-end
-
-function Stance:Update()
- local texture, _, isActive, isCastable = GetShapeshiftFormInfo(self:GetActionID())
-
- local icon = self.frames.icon
- icon:SetTexture(texture)
- self:GetFrame():SetChecked( isActive and 1 or 0 )
- if isCastable then
- self.frames.hotkey:Show()
- icon:SetVertexColor(1.0, 1.0, 1.0)
- else
- icon:SetVertexColor(0.4, 0.4, 0.4)
- end
-
- self:UpdateCooldown()
-end
-
-function Stance:UpdateCooldown()
- local start, duration, enabled = GetShapeshiftFormCooldown(self:GetActionID())
- if start then
- CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enabled)
- end
-end
-
-function Stance:SetTooltip()
- if GetCVar("UberTooltips") == "1" then
- GameTooltip_SetDefaultAnchor(GameTooltip, self:GetFrame())
- else
- GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT")
- end
- GameTooltip:SetShapeshift(self:GetActionID())
-end
-
-function Stance:OnEnter()
- self:SetTooltip()
-end
-
-function Stance:OnLeave()
- GameTooltip:Hide()
-end
-
-function Stance:PreClick()
- local f = self:GetFrame()
- f:SetChecked( not f:GetChecked() )
-end
-
-function Stance:OnEvent(event, arg)
- if event == "PLAYER_REGEN_ENABLED" then
- if self.updatePending then
- self:UpdateAction()
- end
- elseif event == "UPDATE_SHAPESHIFT_COOLDOWN" then
- self:UpdateCooldown()
- elseif event == "UPDATE_SHAPESHIFT_FORMS" then
- self:UpdateAction()
- elseif event == "UNIT_AURA" then
- if arg == "player" then
- self:Update()
- end
- elseif event == "UPDATE_BINDINGS" then
- self:UpdateHotkey()
- else
- self:Update()
- end
-end
-
-function Stance:ShowGridTemp(show)
- if show then
- self:GetFrame():Show()
- else
- self:UpdateAction()
- end
-end
diff -r b2b105747466 -r 920d17851a93 classes/VehicleExitButton.lua
--- a/classes/VehicleExitButton.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local format = string.format
-
---
--- VExitButton Button class
---
-local Super = ReAction.Button
-local VExitButton = setmetatable( { }, { __index = Super } )
-ReAction.Button.VehicleExit = VExitButton
-
-function VExitButton:New( idx, config, bar )
- local name = format("ReAction_%s_VehicleExit_%d",bar:GetName(),idx)
-
- self = Super.New(self, name, config, bar, idx, "SecureFrameTemplate, ActionButtonTemplate", "Button")
-
- -- frame setup
- local f = self:GetFrame()
- self.frames.icon:SetTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up")
- self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
-
- -- attribute setup
- -- (none)
-
- -- non secure scripts
- f:SetScript("OnClick", VehicleExit)
- f:SetScript("OnEnter", function(frame) GameTooltip_AddNewbieTip(frame, LEAVE_VEHICLE, 1.0, 1.0, 1.0, nil) end)
- f:SetScript("OnLeave", GameTooltip_Hide)
- f:SetScript("OnEvent", function(frame, evt, ...) self:OnEvent(evt,...) end)
-
- -- event registration
- f:EnableMouse(true)
- f:RegisterForClicks("AnyUp")
- f:RegisterEvent("UPDATE_BINDINGS")
-
- -- attach to skinner
- bar:SkinButton(self)
-
- self:Refresh()
- self:UpdateHotkey()
-
- return self
-end
-
-function VExitButton:GetActionID()
- return 1
-end
-
-function VExitButton:Refresh()
- Super.Refresh(self)
- -- it seems that setscale kills the texcoord, have to refresh it
- self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
-end
-
-function VExitButton:OnEvent(event, ...)
- if self[event] then
- self[event](self, event, ...)
- end
-end
-
-function VExitButton:UPDATE_BINDINGS()
- self:UpdateHotkey()
-end
diff -r b2b105747466 -r 920d17851a93 classes/classes.xml
--- a/classes/classes.xml Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r b2b105747466 -r 920d17851a93 locale/enUS.lua
--- a/locale/enUS.lua Thu Nov 18 13:11:08 2010 -0800
+++ b/locale/enUS.lua Tue Apr 12 16:06:31 2011 -0700
@@ -4,7 +4,6 @@
for _, string in pairs({
-- ReAction.lua
-"Bar ",
"ReAction: name '%s' already in use",
"ReAction config mode disabled during combat.",
@@ -80,13 +79,20 @@
"Y offset",
"Transparency",
--- PetActionButton.lua
-"Pet action ID range is 1-10",
-
--- ActionButton.lua
+-- classes/ActionButton.lua
+"Action Bar",
"Action ID range is 1-120",
--- Overlay.lua
+-- classes/BagButton.lua --
+"Bag Bar",
+
+-- classes/Bar.lua
+"Hidden",
+
+-- classes/Button.lua --
+"Button Bar",
+
+-- classes/Overlay.lua
"Hold Shift",
"Hold Alt",
"Right-click",
@@ -102,10 +108,20 @@
"State",
"State Scale Override",
--- Bar.lua
-"Hidden",
+-- classes/MultiCastButton.lua
+"Totem Bar",
--- State.lua
+-- classes/PetActionButton.lua
+"Pet Action Bar",
+"Pet action ID range is 1-10",
+
+-- classes/StanceButton.lua
+"Stance Bar",
+
+-- classes/VehicleExitButton.lua
+"Exit Vehicle Floater",
+
+-- modules/State.lua
"State named '%s' already exists",
"Battle Stance",
"Defensive Stance",
@@ -187,8 +203,7 @@
"Create State",
"State named '%s' already exists",
--- Action
-"Action Bar",
+-- modules/Action.lua
"Action Bars",
"Hide Empty Buttons",
"Lock Buttons",
@@ -219,12 +234,10 @@
"Show Page #",
"Action Buttons",
--- PetAction
-"Pet Action Bar",
+-- modules/PetAction.lua
"Pet Buttons",
--- Stance
-"Stance Bar",
+-- modules/Stance.lua
"Stance Buttons",
"Show Aspects",
"Show Hunter aspects as stances",
@@ -235,15 +248,7 @@
"Hide Auras",
"Do not show Paladin Auras as stances",
--- Totem
-"Totem Bar",
-"Totem Buttons",
-
--- Bag
-"Bag Bar",
-
--- VehicleExit
-"Exit Vehicle Floater",
+-- modules/VehicleExit.lua
"Exit Vehicle",
"Show only when passenger",
"Only show the button when riding as a passenger in a vehicle (no vehicle controls)",
diff -r b2b105747466 -r 920d17851a93 modules/Action.lua
--- a/modules/Action.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,611 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local wipe = wipe
-
-local weak = { __mode="k" }
-
--- module declaration
-local moduleID = "Action"
-local module = ReAction:NewModule( moduleID )
-
--- Class declarations
-local Button = ReAction.Button.Action -- see /classes/ActionButton.lua
-local Handle = { }
-local PropHandler = { }
-
--- Event handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- bars = { },
- }
- }
- )
- self.handles = setmetatable({ }, weak)
-
- ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
-
- ReAction.RegisterCallback(self, "OnCreateBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Action Bar"],
- {
- type = moduleID,
- defaultButtonSize = 36,
- defaultBarRows = 1,
- defaultBarCols = 12,
- defaultBarSpacing = 3
- }, true)
- ReAction:GetModule("State"):RegisterStateProperty("page", nil, PropHandler.GetOptions(), PropHandler)
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Action Bar"])
- ReAction:GetModule("State"):UnregisterStateProperty("page")
-end
-
-function module:OnCreateBar(event, bar, name)
- if bar.config.type == moduleID then
- local profile = self.db.profile
- if profile.bars[name] == nil then
- profile.bars[name] = {
- buttons = { }
- }
- end
- if self.handles[bar] == nil then
- self.handles[bar] = Handle:New(bar, profile.bars[name])
- end
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if self.handles[bar] then
- self.handles[bar]:Refresh()
- end
-end
-
-function module:OnDestroyBar(event, bar, name)
- if self.handles[bar] then
- self.handles[bar]:Destroy()
- self.handles[bar] = nil
- end
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.bars[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldname, newname)
- b = self.db.profile.bars
- b[newname], b[oldname] = b[oldname], nil
-end
-
----- Interface ----
-function module:GetBarOptions(bar)
- local h = self.handles[bar]
- if h then
- return h:GetOptions()
- end
-end
-
-
----- Bar Handle ----
-
-do
- local options = {
- hideEmpty = {
- name = L["Hide Empty Buttons"],
- order = 1,
- type = "toggle",
- width = "double",
- get = "GetHideEmpty",
- set = "SetHideEmpty",
- },
- lockButtons = {
- name = L["Lock Buttons"],
- desc = L["Prevents picking up/dragging actions (use SHIFT to override this behavior)"],
- order = 2,
- type = "toggle",
- get = "GetLockButtons",
- set = "SetLockButtons",
- },
- lockOnlyCombat = {
- name = L["Only in Combat"],
- desc = L["Only lock the buttons when in combat"],
- order = 3,
- type = "toggle",
- disabled = "LockButtonsCombatDisabled",
- get = "GetLockButtonsCombat",
- set = "SetLockButtonsCombat",
- },
- pages = {
- name = L["# Pages"],
- desc = L["Use the Dynamic State tab to specify page transitions"],
- order = 4,
- type = "range",
- min = 1,
- max = 10,
- step = 1,
- get = "GetNumPages",
- set = "SetNumPages",
- },
- mindcontrol = {
- name = L["Mind Control Support"],
- desc = L["When possessing a target (e.g. via Mind Control), map the first 12 buttons of this bar to the possessed target's actions."],
- order = 5,
- type = "toggle",
- width = "double",
- set = "SetMindControl",
- get = "GetMindControl",
- },
- vehicle = {
- name = L["Vehicle Support"],
- desc = L["When on a vehicle, map the first 6 buttons of this bar to the vehicle actions. The vehicle-exit button is mapped to the 7th button. Pitch controls are not supported."],
- order = 6,
- type = "toggle",
- width = "double",
- get = "GetVehicle",
- set = "SetVehicle",
- },
- actions = {
- name = L["Edit Action IDs"],
- order = 7,
- type = "group",
- inline = true,
- args = {
- method = {
- name = L["Assign"],
- order = 1,
- type = "select",
- width = "double",
- values = { [0] = L["Choose Method..."],
- [1] = L["Individually"],
- [2] = L["All at Once"], },
- get = "GetActionEditMethod",
- set = "SetActionEditMethod",
- },
- rowSelect = {
- name = L["Row"],
- desc = L["Rows are numbered top to bottom"],
- order = 2,
- type = "select",
- width = "half",
- hidden = "IsButtonSelectHidden",
- values = "GetRowList",
- get = "GetSelectedRow",
- set = "SetSelectedRow",
- },
- colSelect = {
- name = L["Col"],
- desc = L["Columns are numbered left to right"],
- order = 3,
- type = "select",
- width = "half",
- hidden = "IsButtonSelectHidden",
- values = "GetColumnList",
- get = "GetSelectedColumn",
- set = "SetSelectedColumn",
- },
- pageSelect = {
- name = L["Page"],
- order = 4,
- type = "select",
- width = "half",
- hidden = "IsPageSelectHidden",
- values = "GetPageList",
- get = "GetSelectedPage",
- set = "SetSelectedPage",
- },
- single = {
- name = L["Action ID"],
- usage = L["Specify ID 1-120"],
- order = 5,
- type = "input",
- width = "half",
- hidden = "IsButtonSelectHidden",
- get = "GetActionID",
- set = "SetActionID",
- validate = "ValidateActionID",
- },
- multi = {
- name = L["ID List"],
- usage = L["Specify a comma-separated list of IDs for each button in the bar (in order). Separate multiple pages with semicolons (;)"],
- order = 6,
- type = "input",
- multiline = true,
- width = "double",
- hidden = "IsMultiIDHidden",
- get = "GetMultiID",
- set = "SetMultiID",
- validate = "ValidateMultiID",
- },
- },
- },
- }
-
- local meta = { __index = Handle }
-
- function Handle:New( bar, config )
- local self = setmetatable(
- {
- bar = bar,
- config = config,
- btns = { }
- },
- meta)
-
- if self.config.buttons == nil then
- self.config.buttons = { }
- end
- self:Refresh()
- return self
- end
-
- function Handle:Refresh()
- local r, c = self.bar:GetButtonGrid()
- local n = r*c
- local btnCfg = self.config.buttons
- if n ~= #self.btns then
- for i = 1, n do
- if btnCfg[i] == nil then
- btnCfg[i] = {}
- end
- if self.btns[i] == nil then
- local lastButton = self:GetLastButton()
- local hint = lastButton and lastButton.config.actionID
- local b = Button:New(i, self.config, self.bar, hint)
- self.btns[i] = b
- self.bar:AddButton(i,b)
- end
- end
- for i = n+1, #self.btns do
- if self.btns[i] then
- self.bar:RemoveButton(self.btns[i])
- self.btns[i]:Destroy()
- self.btns[i] = nil
- btnCfg[i] = nil
- end
- end
- end
- for _, b in ipairs(self.btns) do
- b:Refresh()
- end
- Button.SetupBarHeader(self.bar,self.config)
- self:UpdateButtonLock()
- end
-
- function Handle:Destroy()
- for _,b in pairs(self.btns) do
- if b then
- b:Destroy()
- end
- end
- end
-
- function Handle:UpdateButtonLock()
- Button.SetButtonLock(self.bar, self.config.lockButtons, self.config.lockButtonsCombat)
- end
-
- function Handle:GetLastButton()
- return self.btns[#self.btns]
- end
-
- -- options handlers
- function Handle:GetOptions()
- return {
- type = "group",
- name = L["Action Buttons"],
- handler = self,
- args = options
- }
- end
-
- function Handle:SetHideEmpty(info, value)
- if value ~= self.config.hideEmpty then
- self.config.hideEmpty = value
- for _, b in pairs(self.btns) do
- b:ShowGrid(not value)
- end
- end
- end
-
- function Handle:GetHideEmpty()
- return self.config.hideEmpty
- end
-
- function Handle:GetLockButtons()
- return self.config.lockButtons
- end
-
- function Handle:SetLockButtons(info, value)
- self.config.lockButtons = value
- self:UpdateButtonLock()
- end
-
- function Handle:GetLockButtonsCombat()
- return self.config.lockButtonsCombat
- end
-
- function Handle:SetLockButtonsCombat(info, value)
- self.config.lockButtonsCombat = value
- self:UpdateButtonLock()
- end
-
- function Handle:LockButtonsCombatDisabled()
- return not self.config.lockButtons
- end
-
- function Handle:GetNumPages()
- return self.config.nPages
- end
-
- function Handle:SetNumPages(info, value)
- self.config.nPages = value
- self:Refresh()
- end
-
- function Handle:GetMindControl()
- return self.config.mindcontrol
- end
-
- function Handle:SetMindControl(info, value)
- self.config.mindcontrol = value
- self:Refresh()
- end
-
- function Handle:GetVehicle()
- return self.config.vehicle
- end
-
- function Handle:SetVehicle(info, value)
- self.config.vehicle = value
- self:Refresh()
- end
-
- function Handle:GetActionEditMethod()
- return self.editMethod or 0
- end
-
- function Handle:SetActionEditMethod(info, value)
- self.editMethod = value
- end
-
- function Handle:IsButtonSelectHidden()
- return self.editMethod ~= 1
- end
-
- function Handle:GetRowList()
- local r,c = self.bar:GetButtonGrid()
- if self.rowList == nil or #self.rowList ~= r then
- local list = { }
- for i = 1, r do
- table.insert(list,i)
- end
- self.rowList = list
- end
- return self.rowList
- end
-
- function Handle:GetSelectedRow()
- local r, c = self.bar:GetButtonGrid()
- local row = self.selectedRow or 1
- if row > r then
- row = 1
- end
- self.selectedRow = row
- return row
- end
-
- function Handle:SetSelectedRow(info, value)
- self.selectedRow = value
- end
-
- function Handle:GetColumnList()
- local r,c = self.bar:GetButtonGrid()
- if self.columnList == nil or #self.columnList ~= c then
- local list = { }
- for i = 1, c do
- table.insert(list,i)
- end
- self.columnList = list
- end
- return self.columnList
- end
-
- function Handle:GetSelectedColumn()
- local r, c = self.bar:GetButtonGrid()
- local col = self.selectedColumn or 1
- if col > c then
- col = 1
- end
- self.selectedColumn = col
- return col
- end
-
- function Handle:SetSelectedColumn(info, value)
- self.selectedColumn = value
- end
-
- function Handle:IsPageSelectHidden()
- return self.editMethod ~= 1 or (self.config.nPages or 1) < 2
- end
-
- function Handle:GetPageList()
- local n = self.config.nPages or 1
- if self.pageList == nil or #self.pageList ~= n then
- local p = { }
- for i = 1, n do
- table.insert(p,i)
- end
- self.pageList = p
- end
- return self.pageList
- end
-
- function Handle:GetSelectedPage()
- local p = self.selectedPage or 1
- if p > (self.config.nPages or 1) then
- p = 1
- end
- self.selectedPage = p
- return p
- end
-
- function Handle:SetSelectedPage(info, value)
- self.selectedPage = value
- end
-
- function Handle:GetActionID()
- local row = self.selectedRow or 1
- local col = self.selectedColumn or 1
- local r, c = self.bar:GetButtonGrid()
- local n = (row-1) * c + col
- local btn = self.btns[n]
- if btn then
- return tostring(btn:GetActionID(self.selectedPage or 1))
- end
- end
-
- function Handle:SetActionID(info, value)
- local row = self.selectedRow or 1
- local col = self.selectedColumn or 1
- local r, c = self.bar:GetButtonGrid()
- local n = (row-1) * c + col
- local btn = self.btns[n]
- if btn then
- btn:SetActionID(tonumber(value), self.selectedPage or 1)
- end
- end
-
- function Handle:ValidateActionID(info, value)
- value = tonumber(value)
- if value == nil or value < 1 or value > 120 then
- return L["Specify ID 1-120"]
- end
- return true
- end
-
- function Handle:IsMultiIDHidden()
- return self.editMethod ~= 2
- end
-
- function Handle:GetMultiID()
- local p = { }
- for i = 1, self.config.nPages or 1 do
- local b = { }
- for _, btn in ipairs(self.btns) do
- table.insert(b, btn:GetActionID(i))
- end
- table.insert(p, table.concat(b,","))
- end
- return table.concat(p,";\n")
- end
-
-
- local function ParseMultiID(nBtns, nPages, s)
- if s:match("[^%d%s,;]") then
- return nil
- end
- local p = { }
- for list in s:gmatch("[^;]+") do
- local pattern = ("^%s?$"):format(("%s*(%d+)%s*,"):rep(nBtns))
- local ids = { list:match(pattern) }
- if #ids ~= nBtns then
- return nil
- end
- table.insert(p,ids)
- end
- if #p ~= nPages then
- return nil
- end
- return p
- end
-
- function Handle:SetMultiID(info, value)
- local p = ParseMultiID(#self.btns, self.config.nPages or 1, value)
- for page, b in ipairs(p) do
- for button, id in ipairs(b) do
- self.btns[button]:SetActionID(id, page)
- end
- end
- end
-
- function Handle:ValidateMultiID(info, value)
- local bad = L["Invalid action ID list string"]
- if value == nil or ParseMultiID(#self.btns, self.config.nPages or 1, value) == nil then
- return bad
- end
- return true
- end
-end
-
-
------- State property options ------
-do
- local pageOptions = {
- page = {
- name = L["Show Page #"],
- order = 11,
- type = "select",
- width = "half",
- disabled = "IsPageDisabled",
- hidden = "IsPageHidden",
- values = "GetPageValues",
- set = "SetProp",
- get = "GetPage",
- },
- }
-
- local function GetBarConfig(bar)
- return module.db.profile.bars[bar:GetName()]
- end
-
- function PropHandler.GetOptions()
- return pageOptions
- end
-
- function PropHandler:IsPageDisabled()
- local c = GetBarConfig(self.bar)
- local n = c and c.nPages or 1
- return not (n > 1)
- end
-
- function PropHandler:IsPageHidden()
- return not GetBarConfig(self.bar)
- end
-
- function PropHandler:GetPageValues()
- if not self._pagevalues then
- self._pagevalues = { }
- end
- local c = GetBarConfig(self.bar)
- if c then
- local n = c.nPages
- -- cache the results
- if self._npages ~= n then
- self._npages = n
- wipe(self._pagevalues)
- for i = 1, n do
- self._pagevalues["page"..i] = i
- end
- end
- end
- return self._pagevalues
- end
-
- function PropHandler:GetPage(info)
- return self:GetProp(info) or 1
- end
-
-end
-
diff -r b2b105747466 -r 920d17851a93 modules/Bag.lua
--- a/modules/Bag.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
---[[
- ReAction Bag button module
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-
--- Bag button
-local Button = ReAction.Button.Bag
-
--- module declaration
-local moduleID = "Bag"
-local module = ReAction:NewModule( moduleID
- -- mixins go here
-)
-
--- handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- buttons = { }
- }
- }
- )
-
- self.buttons = { }
-
- ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Bag Bar"],
- {
- type = moduleID ,
- defaultButtonSize = 30,
- defaultBarRows = 1,
- defaultBarCols = 6,
- defaultBarSpacing = 4
- })
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Bag Bar"])
-end
-
-function module:OnDestroyBar(event, bar, name)
- local btns = self.buttons[bar]
- if btns then
- for _,b in pairs(btns) do
- if b then
- b:Destroy()
- end
- end
- self.buttons[bar] = nil
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if bar.config.type == moduleID then
- local btns = self.buttons[bar]
- if btns == nil then
- btns = { }
- self.buttons[bar] = btns
- end
- local profile = self.db.profile
- if profile.buttons[name] == nil then
- profile.buttons[name] = {}
- end
- local btnCfg = profile.buttons[name]
-
- local r, c = bar:GetButtonGrid()
- local n = r*c
- for i = 1, n do
- if btnCfg[i] == nil then
- btnCfg[i] = {}
- end
- if btns[i] == nil then
- local success, r = pcall(Button.New,Button,i,profile,bar,i>1 and btnCfg[i-1].bagID)
- if success and r then
- btns[i] = r
- bar:AddButton(i,r)
- else
- n = i - 1
- bar:ClipNButtons(n)
- break
- end
- end
- btns[i]:Refresh()
- end
- for i = n+1, #btns do
- if btns[i] then
- bar:RemoveButton(btns[i])
- btns[i] = btns[i]:Destroy()
- if btnCfg[i] then
- btnCfg[i] = nil
- end
- end
- end
- end
-
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.buttons[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldName, newName)
- local b = self.db.profile.buttons
- b[newname], b[oldname] = b[oldname], nil
-end
-
-
--- hook some functions to propagate to our bag buttons
-hooksecurefunc("Disable_BagButtons",
- function()
- for _, buttons in pairs(module.buttons) do
- for _, b in pairs(buttons) do
- local f = b:GetFrame()
- f:Disable()
- SetDesaturation(b.frames.icon,1)
- end
- end
- end)
-
-hooksecurefunc("Enable_BagButtons",
- function()
- for _, buttons in pairs(module.buttons) do
- for _, b in pairs(buttons) do
- local f = b:GetFrame()
- f:Enable()
- SetDesaturation(b.frames.icon,nil)
- end
- end
- end)
-
-hooksecurefunc("ContainerFrame_OnHide",
- function()
- for _, buttons in pairs(module.buttons) do
- for _, b in pairs(buttons) do
- b:Update()
- end
- end
- end)
-
-hooksecurefunc("ContainerFrame_OnShow",
- function()
- for _, buttons in pairs(module.buttons) do
- for _, b in pairs(buttons) do
- b:Update()
- end
- end
- end)
diff -r b2b105747466 -r 920d17851a93 modules/HideBlizzard.lua
--- a/modules/HideBlizzard.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
---[[
- ReAction 'Hide Blizzard' module
-
- Hides Blizzard action bars. This hides the extra action bars, stance bar, pet bar, and
- main menu bar, which in turn hides the experience bar, bag bar, micro menu bar, and lag meter.
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-
--- module declaration
-local moduleID = "HideBlizzard"
-local module = ReAction:NewModule( moduleID )
-
-
--- module methods
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- hide = false
- }
- }
- )
- self.db.RegisterCallback(self,"OnProfileChanged")
- self.db.RegisterCallback(self,"OnProfileCopied", "OnProfileChanged")
- self.db.RegisterCallback(self,"OnProfileReset", "OnProfileChanged")
-
- self.hiddenFrame = CreateFrame("Frame")
- self.hiddenFrame:Hide()
-
- -- It's fairly normal to use the Blizzard vehicle bar, and to have
- -- your regular buttons in the same location. If you do this, and don't
- -- bother to hide your buttons, they'll obscure some parts of the vehicle bar.
- VehicleMenuBar:SetFrameLevel(VehicleMenuBar:GetFrameLevel()+3)
-
-end
-
-function module:OnEnable()
- self:UpdateFrames()
-end
-
-function module:OnDisable()
- self:UpdateFrames(true)
-end
-
-function module:OnProfileChanged()
- self:UpdateFrames()
-end
-
-local frames = {
- [ MainMenuBar ] = { },
- [ MultiBarLeft ] = { },
- [ MultiBarRight ] = { },
- [ MultiBarBottomLeft ] = { },
- [ MultiBarBottomRight ] = { },
- [ VehicleMenuBar ] = { field = "hideVehicle" },
-}
-
-function module:UpdateFrames( show )
- show = show or not self.db.profile.hide
- for frame, info in pairs(frames) do
- local show = show -- make a local copy for this frame
- if info.field then
- show = show or not self.db.profile[info.field]
- end
-
- if show then
- if info.parent then
- frame:SetParent(info.parent)
- end
- if frame:IsShown() then
- frame:Show() -- refresh
- end
- else
- if not info.parent then
- info.parent = frame:GetParent()
- end
- frame:SetParent(self.hiddenFrame)
- end
- end
-end
-
-function module:IsHidden(info)
- if info then
- return self.db.profile.hide and self.db.profile[info[#info]]
- else
- return self.db.profile.hide
- end
-end
-
-function module:SetHidden(info,value)
- self.db.profile[info[#info]] = value
- self:UpdateFrames()
-end
-
-function module:OptionDisabled(info)
- local disabled = InCombatLockdown()
- if not disabled and info[#info] ~= "hide" then
- disabled = not self.db.profile.hide
- end
- return disabled
-end
-
-
--- reroute blizzard action bar config to ReAction config window
-InterfaceOptionsActionBarsPanel:HookScript("OnShow",
- function()
- if module:IsEnabled() and module:IsHidden() then
- ReAction:ShowOptions()
- end
- end )
diff -r b2b105747466 -r 920d17851a93 modules/LBF.lua
--- a/modules/LBF.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-
--- module declaration
-local moduleID = "ButtonFacade"
-local module = ReAction:NewModule( moduleID )
-
--- handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- -- default profile goes here
- }
- }
- )
-
- self.groups = { }
-
- self.LBF = LibStub("LibButtonFacade",true)
-
- if not self.LBF then -- no more initialization
- return
- end
-
- -- override a method of ReAction.Bar
- -- note that 'self' in this context refers to the bar
- function ReAction.Bar:SkinButton( button, data )
- module:GetGroup(self:GetName()):AddButton(button:GetFrame(), data)
- end
-
- -- register some common events
- ReAction.RegisterCallback(self, "OnCreateBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-
- self.LBF:RegisterSkinCallback("ReAction", self.OnSkinChanged, self)
-end
-
-function module:OnEnable()
-
-end
-
-function module:OnDisable()
-
-end
-
-function module:OnCreateBar(event, bar, name)
- local c = self.db.profile[name]
- if not c then
- c = {
- skinID = "Blizzard",
- backdrop = true,
- gloss = 0,
- colors = {},
- }
- self.db.profile[name] = c
- end
-
- local g = self:GetGroup(name)
- g.SkinID = c.skinID or "Blizzard"
- g.Backdrop = c.backdrop
- g.Gloss = c.gloss
- g.Colors = c.colors
-end
-
-function module:OnDestroyBar(event, bar, name)
- if self.groups[name] then
- self.groups[name]:Delete()
- self.groups[name] = nil
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- local c = self.db.profile[name]
- local g = self.groups[name]
- if c and g then
- g:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
- end
-end
-
-function module:OnEraseBar(event, bar, name)
- self:OnDestroyBar(event, bar, name)
- self.db.profile[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldName, newName)
- if self.groups[name] then
- self.groups[name]:Delete(true)
- self.db.profile[oldName], self.db.profile[newName] = nil, self.db.profile[oldName]
- self:OnCreateBar(event, bar, newName)
- end
-end
-
-function module:OnSkinChanged( skinID, gloss, backdrop, group, button, colors )
- local c = self.db.profile[group]
- if c then
- c.skinID = skinID
- c.gloss = gloss
- c.backdrop = backdrop
- c.colors = colors
- end
-end
-
-function module:GetGroup( name )
- if not self.groups[name] then
- self.groups[name] = self.LBF:Group("ReAction", name)
- end
- return self.groups[name]
-end
diff -r b2b105747466 -r 920d17851a93 modules/ModuleTemplate.lua
--- a/modules/ModuleTemplate.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
---[[
- ReAction module template
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-
--- module declaration
-local moduleID = "MyModuleName"
-local module = ReAction:NewModule( moduleID
- -- mixins go here
-)
-
--- handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- -- default profile goes here
- }
- }
- )
-
- -- register some common events
- ReAction.RegisterCallback(self, "OnCreateBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
-
-end
-
-function module:OnDisable()
-
-end
-
--- apply module features and settings to a bar object (see Bar.lua for Bar API)
-function module:OnCreateBar(event, bar, name)
-
-end
-
--- remove module features and settings from a bar object
-function module:OnDestroyBar(event, bar, name)
-
-end
-
--- refresh module features and settings on a bar object
-function module:OnRefreshBar(event, bar, name)
-
-end
-
--- erase any local configuration entries for the supplied bar name
-function module:OnEraseBar(event, bar, name)
-
-end
-
--- update any local configuration/option entries with the new bar name index
-function module:OnRenameBar(event, bar, oldName, newName)
-
-end
-
-
diff -r b2b105747466 -r 920d17851a93 modules/PetAction.lua
--- a/modules/PetAction.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
---[[
- ReAction Pet Action button module
-
- The button module implements standard action button functionality by wrapping Blizzard's
- PetActionButton frame and associated functions.
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-
--- module declaration
-local moduleID = "PetAction"
-local module = ReAction:NewModule( moduleID )
-
--- Button class
-local Button = ReAction.Button.PetAction
-
--- private
-local function UpdateButtonLock(bar)
- local f = bar:GetFrame()
- f:SetAttribute("lockbuttons",bar.config.lockButtons)
- f:SetAttribute("lockbuttonscombat",bar.config.lockButtonsCombat)
- f:Execute(
- [[
- lockButtons = self:GetAttribute("lockbuttons")
- lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
- ]])
-end
-
--- module methods
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- buttons = { }
- }
- }
- )
- self.buttons = { }
-
- ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
-
- ReAction.RegisterCallback(self, "OnCreateBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Pet Action Bar"],
- {
- type = moduleID ,
- defaultButtonSize = 30,
- defaultBarRows = 1,
- defaultBarCols = 10,
- defaultBarSpacing = 8
- })
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Pet Action Bar"])
-end
-
-function module:OnCreateBar(event, bar, name)
- if bar.config.type == moduleID then
- -- auto show/hide when pet exists
- bar:RegisterUnitWatch("pet",true)
- self:OnRefreshBar(event, bar, name)
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if bar.config.type == moduleID then
- if self.buttons[bar] == nil then
- self.buttons[bar] = { }
- end
- local btns = self.buttons[bar]
- local profile = self.db.profile
- if profile.buttons[name] == nil then
- profile.buttons[name] = {}
- end
- local btnCfg = profile.buttons[name]
-
- local r, c = bar:GetButtonGrid()
- local n = r*c
- for i = 1, n do
- if btnCfg[i] == nil then
- btnCfg[i] = {}
- end
- if btns[i] == nil then
- local success, r = pcall(Button.New,Button,i,btnCfg[i],bar,i>1 and btnCfg[i-1].actionID)
- if success and r then
- btns[i] = r
- bar:AddButton(i,r)
- else
- n = i - 1
- bar:ClipNButtons(n)
- break
- end
- end
- btns[i]:Refresh()
- end
- for i = n+1, #btns do
- if btns[i] then
- bar:RemoveButton(btns[i])
- btns[i] = btns[i]:Destroy()
- if btnCfg[i] then
- btnCfg[i] = nil
- end
- end
- end
- UpdateButtonLock(bar)
- end
-end
-
-function module:OnDestroyBar(event, bar, name)
- if self.buttons[bar] then
- local btns = self.buttons[bar]
- for _,b in pairs(btns) do
- if b then
- b:Destroy()
- end
- end
- self.buttons[bar] = nil
- end
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.buttons[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldname, newname)
- local b = self.db.profile.buttons
- b[newname], b[oldname] = b[oldname], nil
-end
-
-
----- Options ----
-local Handler = { }
-local meta = { __index = Handler }
-
-function Handler:New(bar)
- return setmetatable(
- {
- bar = bar,
- config = bar.config
- }, meta)
-end
-
-function Handler:GetLockButtons()
- return self.config.lockButtons
-end
-
-function Handler:SetLockButtons(info, value)
- self.config.lockButtons = value
- UpdateButtonLock(self.bar)
-end
-
-function Handler:GetLockButtonsCombat()
- return self.config.lockButtonsCombat
-end
-
-function Handler:SetLockButtonsCombat(info, value)
- self.config.lockButtonsCombat = value
- UpdateButtonLock(self.bar)
-end
-
-function Handler:LockButtonsCombatDisabled()
- return not self.config.lockButtons
-end
-
-
-function module:GetBarOptions(bar)
- if bar.config.type == moduleID then
- return {
- type = "group",
- name = L["Pet Buttons"],
- handler = Handler:New(bar),
- args = {
- lockButtons = {
- name = L["Lock Buttons"],
- desc = L["Prevents picking up/dragging actions (use SHIFT to override this behavior)"],
- order = 2,
- type = "toggle",
- get = "GetLockButtons",
- set = "SetLockButtons",
- },
- lockOnlyCombat = {
- name = L["Only in Combat"],
- desc = L["Only lock the buttons when in combat"],
- order = 3,
- type = "toggle",
- disabled = "LockButtonsCombatDisabled",
- get = "GetLockButtonsCombat",
- set = "SetLockButtonsCombat",
- },
- }
- }
- end
-end
-
-
diff -r b2b105747466 -r 920d17851a93 modules/Stance.lua
--- a/modules/Stance.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
---[[
- ReAction Stance button module
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-
--- Stance button
-local Button = ReAction.Button.Stance
-
--- module declaration
-local moduleID = "Stance"
-local module = ReAction:NewModule( moduleID
- -- mixins go here
-)
-
--- handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- buttons = { }
- }
- }
- )
-
- self.buttons = { }
-
- ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Stance Bar"],
- {
- type = moduleID ,
- defaultButtonSize = 36,
- defaultBarRows = 1,
- defaultBarCols = 6,
- defaultBarSpacing = 3
- })
-
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Stance Bar"])
-end
-
-function module:OnDestroyBar(event, bar, name)
- local btns = self.buttons[bar]
- if btns then
- for _,b in pairs(btns) do
- if b then
- b:Destroy()
- end
- end
- self.buttons[bar] = nil
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if bar.config.type == moduleID then
- local btns = self.buttons[bar]
- if btns == nil then
- btns = { }
- self.buttons[bar] = btns
- end
- local profile = self.db.profile
- if profile.buttons[name] == nil then
- profile.buttons[name] = {}
- end
- local btnCfg = profile.buttons[name]
-
- local r, c = bar:GetButtonGrid()
- local n = r*c
- for i = 1, n do
- if btnCfg[i] == nil then
- btnCfg[i] = {}
- end
- if btns[i] == nil then
- local success, r = pcall(Button.New,Button,i,profile,bar,i>1 and btnCfg[i-1].stanceID)
- if success and r then
- btns[i] = r
- bar:AddButton(i,r)
- else
- n = i - 1
- bar:ClipNButtons(n)
- break
- end
- end
- btns[i]:Refresh()
- end
- for i = n+1, #btns do
- if btns[i] then
- bar:RemoveButton(btns[i])
- btns[i] = btns[i]:Destroy()
- if btnCfg[i] then
- btnCfg[i] = nil
- end
- end
- end
- end
-
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.buttons[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldName, newName)
- local b = self.db.profile.buttons
- b[newname], b[oldname] = b[oldname], nil
-end
-
-function module:RefreshAll()
- for bar in pairs(self.buttons) do
- self:OnRefreshBar(nil,bar,bar:GetName())
- end
-end
-
diff -r b2b105747466 -r 920d17851a93 modules/State.lua
--- a/modules/State.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,915 +0,0 @@
---[[
- ReAction bar state driver interface
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local format = string.format
-local InCombatLockdown = InCombatLockdown
-local RegisterStateDriver = RegisterStateDriver
-
--- module declaration
-local moduleID = "State"
-local module = ReAction:NewModule( moduleID, "AceEvent-3.0" )
-
--- Utility --
-
--- traverse a table tree by key list and fetch the result or first nil
-local function tfetch(t, ...)
- for i = 1, select('#', ...) do
- t = t and t[select(i, ...)]
- end
- return t
-end
-
--- traverse a table tree by key list and build tree as necessary
-local function tbuild(t, ...)
- for i = 1, select('#', ...) do
- local key = select(i, ...)
- if not t[key] then t[key] = { } end
- t = t[key]
- end
- return t
-end
-
--- return a new array of keys of table 't', sorted by comparing
--- sub-fields (obtained via tfetch) of the table values
-local function fieldsort( t, ... )
- local r = { }
- for k in pairs(t) do
- table.insert(r,k)
- end
- local path = { ... }
- table.sort(r, function(lhs, rhs)
- local olhs = tfetch(t[lhs], unpack(path)) or 0
- local orhs = tfetch(t[rhs], unpack(path)) or 0
- return olhs < orhs
- end)
- return r
-end
-
-
-local ApplyStates, CleanupStates, SetProperty, GetProperty, RegisterProperty
-
--- PRIVATE --
-do
- function GetProperty( bar, state, propname )
- return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname)
- end
-
- function SetProperty( bar, state, propname, value )
- local s = tbuild(module.db.profile.bars, bar:GetName(), "states", state)
- s[propname] = value
- bar:SetSecureStateData(state, propname, value)
- end
-
- function RegisterProperty( propname, snippet )
- for _, bar in ReAction:IterateBars() do
- if type(snippet) == "string" then
- bar:SetSecureStateExtension(propname,snippet)
- end
- ApplyStates(bar)
- end
- end
-
- function UnregisterProperty( propname )
- for _, bar in ReAction:IterateBars() do
- bar:SetSecureStateExtension(propname,nil)
- ApplyStates(bar)
- end
- end
-
- function ApplyStates( bar )
- local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
- if states then
- bar:SetStateDriver(states)
- end
- end
-
- function CleanupStates( bar )
- bar:SetStateDriver(nil)
- end
-end
-
-
-
--- module event handlers --
-
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- bars = { },
- }
- }
- )
-
- self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
-
- ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
-
- ReAction.RegisterCallback(self, "OnCreateBar","OnRefreshBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui
-end
-
-function module:UPDATE_SHAPESHIFT_FORMS()
- -- Re-parse the rules table according to the new form list.
- -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
- -- as well as when gaining new abilities.
- ReAction.Bar.InitRuleFormats()
- for _, bar in ReAction:IterateBars() do
- ApplyStates(bar)
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- local c = self.db.profile.bars[name]
- if c then
- ApplyStates(bar)
- end
-end
-
-function module:OnDestroyBar(event, bar, name)
- CleanupStates(bar)
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.bars[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldname, newname)
- local bars = self.db.profile.bars
- bars[newname], bars[oldname] = bars[oldname], nil
-end
-
-
-
--- Options --
-
-local CreateBarOptions, RegisterPropertyOptions
-do
- -- pre-sorted by the order they should appear in
- local rules = {
- -- rule fields
- { "stance", { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
- { "form", { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
- { "stealth", { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]}, {shadowdance = L["Shadow Dance"]} } },
- { "shadow", { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
- { "demon", { {demon = L["Demon Form"]}, {nodemon = L["No Demon Form"]} } },
- { "pet", { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
- { "target", { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
- { "focus", { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
- { "possess", { {possess = L["Mind Control"]} } },
- { "vehicle", { {vehicle = L["In a Vehicle"]} } },
- { "group", { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
- { "combat", { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
- }
-
- local ruleSelect = { }
- local ruleMap = { }
- local optionMap = setmetatable({},{__mode="k"})
-
- local pointTable = {
- NONE = " ",
- CENTER = L["Center"],
- LEFT = L["Left"],
- RIGHT = L["Right"],
- TOP = L["Top"],
- BOTTOM = L["Bottom"],
- TOPLEFT = L["Top Left"],
- TOPRIGHT = L["Top Right"],
- BOTTOMLEFT = L["Bottom Left"],
- BOTTOMRIGHT = L["Bottom Right"],
- }
-
- -- unpack rules table into ruleSelect and ruleMap
- for _, c in ipairs(rules) do
- local rule, fields = unpack(c)
- for _, field in ipairs(fields) do
- local key, label = next(field)
- table.insert(ruleSelect, label)
- table.insert(ruleMap, key)
- end
- end
-
- local stateOptions = {
- ordering = {
- name = L["Info"],
- order = 1,
- type = "group",
- args = {
- delete = {
- name = L["Delete this State"],
- order = -1,
- type = "execute",
- func = "DeleteState",
- },
- rename = {
- name = L["Name"],
- order = 1,
- type = "input",
- get = "GetName",
- set = "SetStateName",
- pattern = "^%w*$",
- usage = L["State names must be alphanumeric without spaces"],
- },
- ordering = {
- name = L["Evaluation Order"],
- desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
- order = 2,
- type = "group",
- inline = true,
- args = {
- up = {
- name = L["Up"],
- order = 1,
- type = "execute",
- width = "half",
- func = "MoveStateUp",
- },
- down = {
- name = L["Down"],
- order = 2,
- type = "execute",
- width = "half",
- func = "MoveStateDown",
- }
- }
- }
- }
- },
- properties = {
- name = L["Properties"],
- order = 2,
- type = "group",
- args = {
- desc = {
- name = L["Set the properties for the bar when in this state"],
- order = 1,
- type = "description"
- },
- hide = {
- name = L["Hide Bar"],
- order = 90,
- type = "toggle",
- set = "SetProp",
- get = "GetProp",
- },
- --[[ BROKEN
- keybindState = {
- name = L["Override Keybinds"],
- desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
- order = 91,
- type = "toggle",
- set = "SetProp",
- get = "GetProp",
- }, ]]
- position = {
- name = L["Position"],
- order = 92,
- type = "group",
- inline = true,
- args = {
- anchorEnable = {
- name = L["Reposition"],
- order = 1,
- type = "toggle",
- set = "SetProp",
- get = "GetProp",
- },
- anchorFrame = {
- name = L["Anchor Frame"],
- order = 2,
- type = "select",
- values = "GetAnchorFrames",
- set = "SetAnchorFrame",
- get = "GetAnchorFrame",
- disabled = "GetAnchorDisabled",
- hidden = "GetAnchorDisabled",
- },
- anchorPoint = {
- name = L["Point"],
- order = 3,
- type = "select",
- values = pointTable,
- set = "SetAnchorPointProp",
- get = "GetAnchorPointProp",
- disabled = "GetAnchorDisabled",
- hidden = "GetAnchorDisabled",
- },
- anchorRelPoint = {
- name = L["Relative Point"],
- order = 4,
- type = "select",
- values = pointTable,
- set = "SetAnchorPointProp",
- get = "GetAnchorPointProp",
- disabled = "GetAnchorDisabled",
- hidden = "GetAnchorDisabled",
- },
- anchorX = {
- name = L["X Offset"],
- order = 5,
- type = "range",
- min = -100,
- max = 100,
- step = 1,
- set = "SetProp",
- get = "GetProp",
- disabled = "GetAnchorDisabled",
- hidden = "GetAnchorDisabled",
- },
- anchorY = {
- name = L["Y Offset"],
- order = 6,
- type = "range",
- min = -100,
- max = 100,
- step = 1,
- set = "SetProp",
- get = "GetProp",
- disabled = "GetAnchorDisabled",
- hidden = "GetAnchorDisabled",
- },
- },
- },
- scale = {
- name = L["Scale"],
- order = 93,
- type = "group",
- inline = true,
- args = {
- enableScale = {
- name = L["Set New Scale"],
- order = 1,
- type = "toggle",
- set = "SetProp",
- get = "GetProp",
- },
- scale = {
- name = L["Scale"],
- order = 2,
- type = "range",
- min = 0.25,
- max = 2.5,
- step = 0.05,
- isPercent = true,
- set = "SetProp",
- get = "GetScale",
- disabled = "GetScaleDisabled",
- hidden = "GetScaleDisabled",
- },
- },
- },
- alpha = {
- name = L["Transparency"],
- order = 94,
- type = "group",
- inline = true,
- args = {
- enableAlpha = {
- name = L["Set Transparency"],
- order = 1,
- type = "toggle",
- set = "SetProp",
- get = "GetProp",
- },
- alpha = {
- name = L["Transparency"],
- order = 2,
- type = "range",
- min = 0,
- max = 1,
- step = 0.01,
- bigStep = 0.05,
- isPercent = true,
- set = "SetProp",
- get = "GetAlpha",
- disabled = "GetAlphaDisabled",
- hidden = "GetAlphaDisabled",
- },
- },
- },
- },
- plugins = { }
- },
- rules = {
- name = L["Rule"],
- order = 3,
- type = "group",
- args = {
- mode = {
- name = L["Select this state"],
- order = 2,
- type = "select",
- style = "radio",
- values = {
- default = L["by default"],
- any = L["when ANY of these"],
- all = L["when ALL of these"],
- custom = L["via custom rule"],
- keybind = L["via keybinding"],
- },
- set = "SetType",
- get = "GetType",
- },
- clear = {
- name = L["Clear All"],
- order = 3,
- type = "execute",
- hidden = "GetClearAllDisabled",
- disabled = "GetClearAllDisabled",
- func = "ClearAllConditions",
- },
- inputs = {
- name = L["Conditions"],
- order = 4,
- type = "multiselect",
- hidden = "GetConditionsDisabled",
- disabled = "GetConditionsDisabled",
- values = ruleSelect,
- set = "SetCondition",
- get = "GetCondition",
- },
- custom = {
- name = L["Custom Rule"],
- order = 5,
- type = "input",
- multiline = true,
- hidden = "GetCustomDisabled",
- disabled = "GetCustomDisabled",
- desc = L["Syntax like macro rules: see preset rules for examples"],
- set = "SetCustomRule",
- get = "GetCustomRule",
- validate = "ValidateCustomRule",
- },
- keybind = {
- name = L["Keybinding"],
- order = 6,
- inline = true,
- hidden = "GetKeybindDisabled",
- disabled = "GetKeybindDisabled",
- type = "group",
- args = {
- desc = {
- name = L["Invoking a state keybind toggles an override of all other transition rules."],
- order = 1,
- type = "description",
- },
- keybind = {
- name = L["State Hotkey"],
- desc = L["Define an override toggle keybind"],
- order = 2,
- type = "keybinding",
- set = "SetKeybind",
- get = "GetKeybind",
- },
- },
- },
- },
- },
- }
-
- local handlers = { }
- local meta = {
- __index = function(self, key)
- for _, h in pairs(handlers) do
- if h[key] then
- return h[key]
- end
- end
- end,
- }
- local StateHandler = setmetatable({ }, meta)
- local proto = { __index = StateHandler }
-
- function RegisterPropertyOptions( field, options, handler )
- stateOptions.properties.plugins[field] = options
- handlers[field] = handler
- end
-
- function UnregisterPropertyOptions( field )
- stateOptions.properties.plugins[field] = nil
- handlers[field] = nil
- end
-
- function StateHandler:New( bar, opts )
- local self = setmetatable(
- {
- bar = bar
- },
- proto )
-
- function self:GetName()
- return opts.name
- end
-
- function self:SetName(name)
- opts.name = name
- end
-
- function self:GetOrder()
- return opts.order
- end
-
- -- get reference to states table: even if the bar
- -- name changes the states table ref won't
- self.states = tbuild(module.db.profile.bars, bar:GetName(), "states")
- self.state = tbuild(self.states, opts.name)
-
- opts.order = self:GetRuleField("order")
- if opts.order == nil then
- -- add after the highest
- opts.order = 100
- for _, state in pairs(self.states) do
- local x = tonumber(tfetch(state, "rule", "order"))
- if x and x >= opts.order then
- opts.order = x + 1
- end
- end
- self:SetRuleField("order",opts.order)
- end
-
- return self
- end
-
- -- helper methods
-
- function StateHandler:SetRuleField( key, value, ... )
- tbuild(self.state, "rule", ...)[key] = value
- end
-
- function StateHandler:GetRuleField( ... )
- return tfetch(self.state, "rule", ...)
- end
-
- function StateHandler:FixAll( setkey )
- -- if multiple selections in the same group are chosen when 'all' is selected,
- -- keep only one of them. If changing the mode, the first in the fields list will
- -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
- -- it will be retained.
- local notified = false
- if self:GetRuleField("type") == "all" then
- for _, c in ipairs(rules) do
- local rule, fields = unpack(c)
- local once = false
- if setkey then
- for idx, field in ipairs(fields) do
- if next(field) == setkey then
- once = true
- end
- end
- end
- for idx, field in ipairs(fields) do
- local key = next(field)
- if self:GetRuleField("values",key) then
- if once and key ~= setkey then
- self:SetRuleField(key,false,"values")
- if not setkey and not notified then
- ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
- notified = true
- end
- end
- once = true
- end
- end
- end
- end
- end
-
- function StateHandler:GetNeighbors()
- local before, after
- for k, v in pairs(self.states) do
- local o = tonumber(tfetch(v, "rule", "order"))
- if o and k ~= self:GetName() then
- local obefore = tfetch(self.states,before,"rule","order")
- local oafter = tfetch(self.states,after,"rule","order")
- if o < self:GetOrder() and (not obefore or obefore < o) then
- before = k
- end
- if o > self:GetOrder() and (not oafter or oafter > o) then
- after = k
- end
- end
- end
- return before, after
- end
-
- function StateHandler:SwapOrder( a, b )
- -- do options table
- local args = optionMap[self.bar].args
- args[a].order, args[b].order = args[b].order, args[a].order
- -- do profile
- a = tbuild(self.states, a, "rule")
- b = tbuild(self.states, b, "rule")
- a.order, b.order = b.order, a.order
- end
-
- -- handler methods
-
- function StateHandler:GetProp( info )
- -- gets property of the same name as the options arg
- return GetProperty(self.bar, self:GetName(), info[#info])
- end
-
- function StateHandler:SetProp( info, value )
- -- sets property of the same name as the options arg
- SetProperty(self.bar, self:GetName(), info[#info], value)
- end
-
- function StateHandler:DeleteState()
- if self.states[self:GetName()] then
- self.states[self:GetName()] = nil
- ApplyStates(self.bar)
- end
- optionMap[self.bar].args[self:GetName()] = nil
- end
-
- function StateHandler:SetStateName(info, value)
- -- check for existing state name
- if self.states[value] then
- ReAction:UserError(format(L["State named '%s' already exists"],value))
- return
- end
- local args = optionMap[self.bar].args
- local name = self:GetName()
- self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil
- self:SetName(value)
- ApplyStates(self.bar)
- ReAction:ShowEditor(self.bar, moduleID, value)
- end
-
- function StateHandler:MoveStateUp()
- local before, after = self:GetNeighbors()
- if before then
- self:SwapOrder(before, self:GetName())
- ApplyStates(self.bar)
- end
- end
-
- function StateHandler:MoveStateDown()
- local before, after = self:GetNeighbors()
- if after then
- self:SwapOrder(self:GetName(), after)
- ApplyStates(self.bar)
- end
- end
-
- function StateHandler:GetAnchorDisabled()
- return not GetProperty(self.bar, self:GetName(), "anchorEnable")
- end
-
- function StateHandler:GetAnchorFrames(info)
- self._anchorframes = self._anchorframes or { }
- table.wipe(self._anchorframes)
-
- table.insert(self._anchorframes, "UIParent")
- for name, bar in ReAction:IterateBars() do
- table.insert(self._anchorframes, bar:GetFrame():GetName())
- end
- return self._anchorframes
- end
-
- function StateHandler:GetAnchorFrame(info)
- local value = self:GetProp(info)
- for k,v in pairs(self._anchorframes) do
- if v == value then
- return k
- end
- end
- end
-
- function StateHandler:SetAnchorFrame(info, value)
- local f = _G[self._anchorframes[value]]
- if f then
- self.bar:SetFrameRef("anchor-"..self:GetName(), f)
- self:SetProp(info, f:GetName())
- end
- end
-
- function StateHandler:SetAnchorPointProp(info, value)
- self:SetProp(info, value ~= "NONE" and value or nil)
- end
-
- function StateHandler:GetAnchorPointProp(info)
- return self:GetProp(info) or "NONE"
- end
-
- function StateHandler:GetScale(info)
- return self:GetProp(info) or 1.0
- end
-
- function StateHandler:GetScaleDisabled()
- return not GetProperty(self.bar, self:GetName(), "enableScale")
- end
-
- function StateHandler:GetAlpha(info)
- return self:GetProp(info) or 1.0
- end
-
- function StateHandler:GetAlphaDisabled()
- return not GetProperty(self.bar, self:GetName(), "enableAlpha")
- end
-
- function StateHandler:SetType(info, value)
- self:SetRuleField("type", value)
- self:FixAll()
- ApplyStates(self.bar)
- end
-
- function StateHandler:GetType()
- return self:GetRuleField("type")
- end
-
- function StateHandler:GetClearAllDisabled()
- local t = self:GetRuleField("type")
- return not( t == "any" or t == "all" or t == "custom")
- end
-
- function StateHandler:ClearAllConditions()
- local t = self:GetRuleField("type")
- if t == "custom" then
- self:SetRuleField("custom","")
- elseif t == "any" or t == "all" then
- self:SetRuleField("values", {})
- end
- ApplyStates(self.bar)
- end
-
- function StateHandler:GetConditionsDisabled()
- local t = self:GetRuleField("type")
- return not( t == "any" or t == "all")
- end
-
- function StateHandler:SetCondition(info, key, value)
- self:SetRuleField(ruleMap[key], value or nil, "values")
- if value then
- self:FixAll(ruleMap[key])
- end
- ApplyStates(self.bar)
- end
-
- function StateHandler:GetCondition(info, key)
- return self:GetRuleField("values", ruleMap[key]) or false
- end
-
- function StateHandler:GetCustomDisabled()
- return self:GetRuleField("type") ~= "custom"
- end
-
- function StateHandler:SetCustomRule(info, value)
- self:SetRuleField("custom",value)
- ApplyStates(self.bar)
- end
-
- function StateHandler:GetCustomRule()
- return self:GetRuleField("custom") or ""
- end
-
- function StateHandler:ValidateCustomRule(info, value)
- local s = value:gsub("%s","") -- remove all spaces
- -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
- repeat
- if s == "" then
- return true
- end
- local c, r = s:match("(%b[])(.*)")
- if c == nil and s and #s > 0 then
- return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "")
- end
- s = r
- until c == nil
- return true
- end
-
- function StateHandler:GetKeybindDisabled()
- return self:GetRuleField("type") ~= "keybind"
- end
-
- function StateHandler:GetKeybind()
- return self:GetRuleField("keybind")
- end
-
- function StateHandler:SetKeybind(info, value)
- if value and #value == 0 then
- value = nil
- end
- self:SetRuleField("keybind",value)
- ApplyStates(self.bar)
- end
-
- local function CreateStateOptions(bar, name)
- local opts = {
- type = "group",
- name = name,
- childGroups = "tab",
- args = stateOptions
- }
-
- opts.handler = StateHandler:New(bar,opts)
-
- return opts
- end
-
- function module:GetBarOptions(bar)
- local private = { }
- local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
- local options = {
- name = L["Dynamic State"],
- type = "group",
- order = -1,
- childGroups = "tree",
- disabled = InCombatLockdown,
- args = {
- __desc__ = {
- name = L["States are evaluated in the order they are listed"],
- order = 1,
- type = "description",
- },
- __new__ = {
- name = L["New State..."],
- order = 2,
- type = "group",
- args = {
- name = {
- name = L["State Name"],
- desc = L["Set a name for the new state"],
- order = 1,
- type = "input",
- get = function() return private.newstatename or "" end,
- set = function(info,value) private.newstatename = value end,
- pattern = "^%w*$",
- usage = L["State names must be alphanumeric without spaces"],
- },
- create = {
- name = L["Create State"],
- order = 2,
- type = "execute",
- func = function ()
- local name = private.newstatename
- if states[name] then
- ReAction:UserError(format(L["State named '%s' already exists"],name))
- else
- -- TODO: select default state options and pass as final argument
- states[name] = { }
- optionMap[bar].args[name] = CreateStateOptions(bar,name)
- ReAction:ShowEditor(bar, moduleID, name)
- private.newstatename = ""
- end
- end,
- disabled = function()
- local name = private.newstatename or ""
- return #name == 0 or name:find("%W")
- end,
- }
- }
- }
- }
- }
- for name, config in pairs(states) do
- options.args[name] = CreateStateOptions(bar,name)
- end
- optionMap[bar] = options
- return options
- end
-end
-
--- Module API --
-
--- Pass in a property field-name, an implementation secure snippet, a static options table, and an
--- optional options handler method-table
---
--- The options table is static, i.e. not bar-specific and should only reference handler method
--- strings (either existing ones or those added via optHandler). The existing options are ordered
--- 90-99. Order #1 is reserved for the heading.
---
--- The contents of optHandler, if provided, will be added to the existing StateHandler options metatable.
--- See above, for existing API. In particular see the properties set up in the New method: self.bar,
--- self.states, and self:GetName(), and the generic property handlers self:GetProp() and self:SetProp().
---
-function module:RegisterStateProperty( field, snippetHandler, options, optHandler )
- RegisterProperty(field, snippetHandler)
- RegisterPropertyOptions(field, options, optHandler)
-end
-
-function module:UnregisterStateProperty( field )
- UnregisterProperty(field)
- UnregisterPropertyOptions(field)
-end
-
-
--- Export methods to Bar class --
-
-ReAction.Bar.GetStateProperty = GetProperty
-ReAction.Bar.SetStateProperty = SetProperty
diff -r b2b105747466 -r 920d17851a93 modules/Totem.lua
--- a/modules/Totem.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
---[[
- ReAction Totem button module
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-
--- button
-local Button = ReAction.Button.MultiCast
-
--- module declaration
-local moduleID = "Totem"
-local module = ReAction:NewModule( moduleID,
- "AceEvent-3.0"
- -- mixins go here
-)
-
--- handlers
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- buttons = { }
- }
- }
- )
-
- self.buttons = { }
-
- ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-
- self:RegisterEvent("UPDATE_MULTI_CAST_ACTIONBAR","PLAYER_ENTERING_WORLD")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Totem Bar"],
- {
- type = moduleID ,
- defaultButtonSize = 36,
- defaultBarRows = 1,
- defaultBarCols = 6,
- defaultBarSpacing = 3
- })
-
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Totem Bar"])
-end
-
-function module:OnDestroyBar(event, bar, name)
- local btns = self.buttons[bar]
- if btns then
- for _,b in pairs(btns) do
- if b then
- b:Destroy()
- end
- end
- self.buttons[bar] = nil
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if bar.config.type == moduleID then
- local btns = self.buttons[bar]
- if btns == nil then
- btns = { }
- self.buttons[bar] = btns
- end
- local profile = self.db.profile
- if profile.buttons[name] == nil then
- profile.buttons[name] = {}
- end
- local btnCfg = profile.buttons[name]
-
- local r, c = bar:GetButtonGrid()
- local n = min(r*c,6)
- Button.SetupBarHeader(bar)
- for i = 1, n do
- if btnCfg[i] == nil then
- btnCfg[i] = {}
- end
- if not btns[i] then
- local success, r = pcall(Button.New,Button,i,btnCfg,bar)
- if success then
- btns[i] = r
- if r then
- bar:AddButton(i,r)
- end
- else
- geterrorhandler()(r)
- n = i - 1
- bar:ClipNButtons(n)
- break
- end
- end
- if btns[i] then
- btns[i]:Refresh()
- end
- end
- for i = n+1, #btns do
- if btns[i] then
- bar:RemoveButton(btns[i])
- btns[i] = btns[i]:Destroy()
- if btnCfg[i] then
- btnCfg[i] = nil
- end
- end
- end
- end
-
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.buttons[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldName, newName)
- local b = self.db.profile.buttons
- b[newname], b[oldname] = b[oldname], nil
-end
-
-function module:RefreshAll()
- for bar in pairs(self.buttons) do
- self:OnRefreshBar(nil,bar,bar:GetName())
- end
-end
-
-function module:UPDATE_MULTI_CAST_ACTIONBAR()
- if not InCombatLockdown() then
- for bar in pairs(self.buttons) do
- self:OnRefreshBar("OnRefreshBar", bar, bar:GetName())
- end
- end
-end
-
-function module:PLAYER_ENTERING_WORLD()
- for bar in pairs(self.buttons) do
- self:OnRefreshBar("OnRefreshBar", bar, bar:GetName())
- end
-end
-
-
diff -r b2b105747466 -r 920d17851a93 modules/VehicleExit.lua
--- a/modules/VehicleExit.lua Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
---[[
- ReAction Vehicle Exit button module
-
- The button module implements a single button which you can use
- to exit a vehicle that doesn't have controls (replacement for
- MainMenuBarLeaveVehicleButton).
-
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-
--- module declaration
-local moduleID = "VehicleExit"
-local module = ReAction:NewModule( moduleID )
-
--- Button class
-local Button = ReAction.Button.VehicleExit
-
--- module methods
-function module:OnInitialize()
- self.db = ReAction.db:RegisterNamespace( moduleID,
- {
- profile = {
- buttons = { }
- }
- }
- )
- self.registered = { }
- self.buttons = { }
-
- ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
-
- ReAction.RegisterCallback(self, "OnCreateBar")
- ReAction.RegisterCallback(self, "OnDestroyBar")
- ReAction.RegisterCallback(self, "OnRefreshBar")
- ReAction.RegisterCallback(self, "OnEraseBar")
- ReAction.RegisterCallback(self, "OnRenameBar")
-end
-
-function module:OnEnable()
- ReAction:RegisterBarType(L["Exit Vehicle Floater"],
- {
- type = moduleID ,
- defaultButtonSize = 36,
- defaultBarRows = 1,
- defaultBarCols = 1,
- defaultBarSpacing = 3
- })
-end
-
-function module:OnDisable()
- ReAction:UnregisterBarType(L["Exit Vehicle Floater"])
-end
-
-function module:OnCreateBar(event, bar, name)
- if bar.config.type == moduleID then
- self:OnRefreshBar(event, bar, name)
- end
-end
-
-function module:OnRefreshBar(event, bar, name)
- if bar.config.type == moduleID then
- local profile = self.db.profile
- if profile.buttons[name] == nil then
- profile.buttons[name] = {}
- end
- local btnCfg = profile.buttons[name]
-
- if profile.buttons[name] == nil then
- profile.buttons[name] = { }
- end
- if self.buttons[bar] == nil then
- local success, r = pcall(Button.New, Button, 1, profile.buttons[name], bar)
- if success and r then
- self.buttons[bar] = r
- bar:AddButton(1,r)
- end
- else
- self.buttons[bar]:Refresh()
- end
- bar:ClipNButtons(1)
- self:UpdateRegistration(bar)
- end
-end
-
-function module:OnDestroyBar(event, bar, name)
- if self.buttons[bar] then
- self.buttons[bar]:Destroy()
- self.buttons[bar] = nil
- end
-end
-
-function module:OnEraseBar(event, bar, name)
- self.db.profile.buttons[name] = nil
-end
-
-function module:OnRenameBar(event, bar, oldname, newname)
- local b = self.db.profile.buttons
- b[newname], b[oldname] = b[oldname], nil
-end
-
-
-function module:UpdateRegistration(bar)
- -- auto show/hide when on a vehicle
- local config = self.db.profile.buttons[bar:GetName()]
- local f = bar:GetFrame()
- if config.withControls then
- if bar.vehicleExitStateRegistered then
- UnregisterStateDriver(f, "unitexists")
- bar.vehicleExitStateRegistered = false
- end
- bar:RegisterUnitWatch("vehicle",true)
- else
- bar:RegisterUnitWatch("vehicle",false)
- if not bar.vehicleExitStateRegistered then
- f:SetAttribute("unit","vehicle")
- RegisterStateDriver(f, "unitexists", "[target=vehicle,exists,novehicleui] show; hide") -- spoof onstate-unitexists
- bar.vehicleExitStateRegistered = true
- end
- end
-end
-
----- Options ----
-local Handler = { }
-local meta = { __index = Handler }
-
-function Handler:New(bar)
- return setmetatable(
- {
- bar = bar
- }, meta)
-end
-
-function Handler:GetConfig()
- return module.db.profile.buttons[self.bar:GetName()]
-end
-
-function Handler:GetPassengerOnly()
- return not self:GetConfig().withControls
-end
-
-function Handler:SetPassengerOnly(info, value)
- self:GetConfig().withControls = not value
- module:UpdateRegistration(self.bar)
-end
-
-
-function module:GetBarOptions(bar)
- if bar.config.type == moduleID then
- return {
- type = "group",
- name = L["Exit Vehicle"],
- handler = Handler:New(bar),
- args = {
- passengerOnly = {
- name = L["Show only when passenger"],
- desc = L["Only show the button when riding as a passenger in a vehicle (no vehicle controls)"],
- order = 2,
- width = "double",
- type = "toggle",
- get = "GetPassengerOnly",
- set = "SetPassengerOnly",
- },
- }
- }
- end
-end
-
-
diff -r b2b105747466 -r 920d17851a93 modules/modules.xml
--- a/modules/modules.xml Thu Nov 18 13:11:08 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file