flickerstreak@7: -- main.lua flickerstreak@1: -- flickerstreak@1: -- Top-level file for the ReAction Action Bar add-on flickerstreak@1: -- flickerstreak@7: -- implemented in terms of the Ace 2 development framework library: http://www.wowace.com flickerstreak@1: -- flickerstreak@1: flickerstreak@20: flickerstreak@7: -- Ace Library local object initialization flickerstreak@7: local L = AceLibrary("AceLocale-2.2"):new("ReAction") flickerstreak@7: local dewdrop = AceLibrary("Dewdrop-2.0") flickerstreak@7: local tablet = AceLibrary("Tablet-2.0") flickerstreak@17: local ReBound = AceLibrary("ReBound-1.0"):new("ReAction") flickerstreak@1: flickerstreak@7: -- private functions flickerstreak@2: local function tcopy(t) flickerstreak@2: local r = { } flickerstreak@2: for k, v in pairs(t) do flickerstreak@2: r[k] = (type(v) == "table" and tcopy(v) or v) flickerstreak@2: end flickerstreak@2: return r flickerstreak@2: end flickerstreak@2: flickerstreak@7: -- private constants flickerstreak@7: local EMPTY_BAR_SLOT = -1 flickerstreak@7: flickerstreak@7: -- key binding label constants flickerstreak@17: BINDING_HEADER_REACTION = L["ReAction"] flickerstreak@17: BINDING_NAME_REACTION_TOGGLELOCK = L["Toggle ReAction Bar Lock"] flickerstreak@17: BINDING_NAME_REACTION_TOGGLEKEYBIND = L["ReAction Keybinding Mode"] flickerstreak@7: flickerstreak@10: -- UI panel strings flickerstreak@17: REACTION_KEYBIND_TITLE = L["ReAction Keybinding"] flickerstreak@17: REACTION_KEYBIND_SUBTITLE = L["Click Buttons to Set Keybindings"] flickerstreak@17: REACTION_KEYBIND_DONE = L["Save"] flickerstreak@17: REACTION_KEYBIND_REVERT = L["Revert"] flickerstreak@7: flickerstreak@10: flickerstreak@10: flickerstreak@10: ------------------------------ flickerstreak@10: -- AceAddon setup flickerstreak@10: ------------------------------ flickerstreak@7: local main = AceLibrary("AceAddon-2.0"):new( flickerstreak@7: "AceConsole-2.0", flickerstreak@7: "AceEvent-2.0", flickerstreak@7: "AceDB-2.0", flickerstreak@7: "FuBarPlugin-2.0" flickerstreak@7: ) flickerstreak@1: flickerstreak@10: function main:OnInitialize() flickerstreak@10: self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" ) flickerstreak@10: self:RegisterDB("ReActionDB","ReActionDBPC") flickerstreak@10: self:RegisterDefaults("profile", ReAction_DefaultProfile) flickerstreak@10: self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown") flickerstreak@10: self:DisableDefaultKeybindings() flickerstreak@1: flickerstreak@12: -- create update function for keybinding frame flickerstreak@17: ReActionKeybindDialog:SetScript("OnHide", function(frame) main:HideKeybindDialog(frame) end) flickerstreak@12: flickerstreak@10: -- initial non-persistent state flickerstreak@10: self.locked = true flickerstreak@17: self.keybindMode = false flickerstreak@10: self.bars = { } flickerstreak@10: end flickerstreak@7: flickerstreak@17: -- OnEnable is called at PLAYER_LOGIN or when the addon is enabled. flickerstreak@12: function main:OnEnable( ) flickerstreak@17: self:HideDefaultBars() flickerstreak@17: self:SetupProfile( ) flickerstreak@10: end flickerstreak@7: flickerstreak@10: function main:OnDisable() flickerstreak@10: self:Lock() flickerstreak@10: end flickerstreak@10: flickerstreak@10: -- OnProfileEnable() is only called when switching profiles, NOT for the initial profile at load time. flickerstreak@10: function main:OnProfileEnable( oldName, oldData ) flickerstreak@12: self:UnregisterEvent("REBOUND_BIND") flickerstreak@12: self:UnregisterEvent("REBOUND_UNBIND") flickerstreak@12: ReBound:ClearRegisteredBindings() flickerstreak@17: self:SetupProfile() flickerstreak@10: end flickerstreak@10: flickerstreak@17: function main:SetupProfile( ) flickerstreak@17: local profile = self.db.profile flickerstreak@17: if profile.firstRunDone ~= true then flickerstreak@17: profile.bars = tcopy(ReAction_DefaultBlizzardBars) flickerstreak@17: end flickerstreak@17: self:DestroyAllBars() flickerstreak@17: self:UpgradeProfile() flickerstreak@17: self:HideArt() flickerstreak@17: self:SetupBars() flickerstreak@17: self:SetupKeybindings() flickerstreak@17: if profile.firstRunDone ~= true then flickerstreak@17: self:Unlock() flickerstreak@17: profile.firstRunDone = true flickerstreak@17: end flickerstreak@17: end flickerstreak@17: flickerstreak@17: -- Set a global variable for Bindings.xml (I use 'setglobal' for clarity, it's not strictly necessary) flickerstreak@17: setglobal("ReActionAddOn", main) flickerstreak@17: flickerstreak@17: flickerstreak@17: flickerstreak@17: flickerstreak@17: ------------------------------------------------------------ flickerstreak@17: -- Profile conversion functions (from old profiles) flickerstreak@17: -- flickerstreak@17: -- NOTE: these will be REMOVED when alpha testing is over. flickerstreak@17: ------------------------------------------------------------ flickerstreak@17: function main:UpgradeBindingConfig() flickerstreak@17: if #self.db.profile.bindings == 0 then flickerstreak@10: for _, bar in pairs(self.bars) do flickerstreak@10: for _, button in pairs(bar.buttons) do flickerstreak@10: local key = ReBound:GetBinding(button:GetActionFrame(),"LeftButton") flickerstreak@10: if key and #key > 0 and not self.db.profile.bindings[key] then flickerstreak@10: self:REBOUND_BIND(key,button:GetActionFrame():GetName(),"LeftButton") flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: flickerstreak@17: function main:UpgradeProfile() flickerstreak@17: end flickerstreak@10: flickerstreak@10: flickerstreak@10: flickerstreak@10: -------------------------------------------- flickerstreak@7: -- FuBar plugin setup flickerstreak@10: -- Even if FuBar isn't installed, the plugin flickerstreak@10: -- provides a nice minimap-button interface. flickerstreak@10: --------------------------------------------- flickerstreak@7: main.hasIcon = "Interface\\Icons\\INV_Qiraj_JewelEncased" flickerstreak@7: main.hasNoColor = true flickerstreak@7: main.hideMenuTitle = true flickerstreak@7: main.defaultPosition = "LEFT" flickerstreak@7: main.defaultMinimapPosition = 240 -- degrees flickerstreak@7: main.OnMenuRequest = tcopy(ReActionGlobalMenuOptions) -- use a copy, or bar menus will have FuBar inserted items flickerstreak@7: main.independentProfile = true flickerstreak@7: flickerstreak@7: -- set the handler for the global bar menu options flickerstreak@7: -- have to do this after tcopy() above, otherwise it will try to copy the handler object (bad idea) flickerstreak@7: ReActionGlobalMenuOptions.handler = main flickerstreak@7: flickerstreak@7: function main:OnTooltipUpdate() flickerstreak@7: local c = tablet:AddCategory("columns", 2) flickerstreak@7: c:AddLine("text", L["Bar lock"], "text2", self.locked and ("|cffff0000"..L["Locked"].."|r") or ("|cffffcc00"..L["Unlocked"].."|r")) flickerstreak@7: c:AddLine("text", L["Button lock"], "text2", LOCK_ACTIONBAR == "1" and ("|cffcc0000"..L["Locked"].."|r") or ("|cff00cc00"..L["Unlocked"].."|r")) flickerstreak@10: c:AddLine("text", L["Kebinding mode"], "text2", self:GetKeybindMode() and ("|cff33ff33"..L["On"].."|r") or ("|cffffcc00"..L["Off"].."|r")) flickerstreak@7: tablet:SetHint(L["|cffffcc00Shift-Click for bar lock|n|cff33ff33Alt-Click|r for keybindings|nRight-click for menu"]) flickerstreak@7: end flickerstreak@7: flickerstreak@7: function main:OnClick(button) flickerstreak@7: if IsShiftKeyDown() then flickerstreak@7: self:ToggleLocked() flickerstreak@7: self:UpdateDisplay() flickerstreak@7: elseif IsAltKeyDown() then flickerstreak@10: self:ToggleKeybindMode() flickerstreak@7: self:UpdateDisplay() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@10: flickerstreak@10: flickerstreak@10: ------------------------------ flickerstreak@10: -- Key binding functions flickerstreak@10: ------------------------------ flickerstreak@10: function main:DisableDefaultKeybindings() flickerstreak@17: -- change the labels on all actionbar keybindings in the default interface. flickerstreak@10: local label = "|cff999999("..L["Use ReAction"]..")|r" flickerstreak@10: for i = 1, 12 do flickerstreak@10: setglobal("BINDING_NAME_ACTIONBUTTON"..i,label) flickerstreak@10: for j = 1, 4 do flickerstreak@10: setglobal("BINDING_NAME_MULTIACTIONBAR"..j.."BUTTON"..i,label) flickerstreak@10: end flickerstreak@10: end flickerstreak@10: for i = 1, 6 do flickerstreak@10: setglobal("BINDING_NAME_ACTIONPAGE"..i,label) flickerstreak@10: end flickerstreak@10: for i = 1, 10 do flickerstreak@10: setglobal("BINDING_NAME_BONUSACTIONBUTTON"..i,label) flickerstreak@17: -- setglobal("BINDING_NAME_SHAPESHIFTBUTTON"..i,label) flickerstreak@10: end flickerstreak@10: BINDING_HEADER_ACTIONBAR = "|cff999999"..L["Action Bar Functions Disabled"].."|r" flickerstreak@10: BINDING_HEADER_MULTIACTIONBAR = "|cff999999"..L["Multi-Action Bar Functions Disabled"].."|r" flickerstreak@10: BINDING_NAME_NEXTACTIONPAGE = label flickerstreak@10: BINDING_NAME_PREVIOUSACTIONPAGE = label flickerstreak@10: end flickerstreak@10: flickerstreak@12: function main:SetupKeybindings() flickerstreak@10: if self.db.profile.firstRunDone ~= true then flickerstreak@10: self:StealKeyBindings() flickerstreak@10: else flickerstreak@17: self:UpgradeBindingConfig() flickerstreak@17: local needsSave = false flickerstreak@10: for key, binding in pairs(self.db.profile.bindings) do flickerstreak@12: local target = getglobal(binding.target) flickerstreak@12: if target then flickerstreak@17: if ReBound:GetBinding(target,binding.button) ~= key then flickerstreak@17: ReBound:SetBinding(key,target,binding.button,true) flickerstreak@17: needsSave = true flickerstreak@17: end flickerstreak@12: end flickerstreak@10: end flickerstreak@17: if needsSave then flickerstreak@17: ReBound:SaveBindings() flickerstreak@17: end flickerstreak@10: end flickerstreak@10: self:RegisterEvent("REBOUND_BIND") flickerstreak@10: self:RegisterEvent("REBOUND_UNBIND") flickerstreak@10: end flickerstreak@10: flickerstreak@10: function main:StealKeyBindings() flickerstreak@10: -- steal the keybindings of the main action bar and assign them to rebar 1, buttons 1-12 flickerstreak@17: local bar = self.bars[1] flickerstreak@17: if bar and bar ~= EMPTY_BAR_SLOT then flickerstreak@17: for i = 1, 12 do flickerstreak@17: local key = GetBindingKey("ACTIONBUTTON"..i) flickerstreak@17: if key and #key > 0 then flickerstreak@17: local button = bar.buttons[i] flickerstreak@17: if button then flickerstreak@17: ReBound:SetBinding(key, button:GetActionFrame(),nil,true) flickerstreak@17: end flickerstreak@17: end flickerstreak@17: end flickerstreak@17: local key = GetBindingKey("NEXTACTIONPAGE") flickerstreak@10: if key and #key > 0 then flickerstreak@17: ReBound:SetBinding(key, bar.upArrow,nil,true) flickerstreak@10: end flickerstreak@17: key = GetBindingKey("PREVIOUSACTIONPAGE") flickerstreak@17: if key and #key > 0 then flickerstreak@17: ReBound:SetBinding(key, bar.downArrow,nil,true) flickerstreak@17: end flickerstreak@17: ReBound:SaveBindings() flickerstreak@10: end flickerstreak@10: end flickerstreak@10: flickerstreak@12: function main:REBOUND_BIND(id, key, target, button) flickerstreak@17: if id == "ReAction" and key and target then flickerstreak@10: self.db.profile.bindings[key] = { target = target, button = button } flickerstreak@10: end flickerstreak@10: end flickerstreak@10: flickerstreak@12: function main:REBOUND_UNBIND(id, key) flickerstreak@17: if id == "ReAction" and key then flickerstreak@10: self.db.profile.bindings[key] = nil flickerstreak@10: end flickerstreak@10: end flickerstreak@10: flickerstreak@10: function main:ToggleKeybindMode() flickerstreak@10: self:SetKeybindMode(not self:GetKeybindMode()) flickerstreak@10: end flickerstreak@10: flickerstreak@10: function main:GetKeybindMode() flickerstreak@10: return self.keybindMode flickerstreak@10: end flickerstreak@10: flickerstreak@10: function main:SetKeybindMode(enabled) flickerstreak@17: if InCombatLockdown() then flickerstreak@17: UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT) flickerstreak@17: else flickerstreak@10: self.keybindMode = enabled flickerstreak@10: for _, bar in pairs(self.bars) do flickerstreak@17: if bar and bar ~= EMPTY_BAR_SLOT then flickerstreak@17: for __, button in pairs(bar.buttons) do flickerstreak@17: if button then flickerstreak@17: button:TempShow(enabled) flickerstreak@17: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: if enabled then flickerstreak@17: ReBound:ShowRegisteredFrames() flickerstreak@10: ReActionKeybindDialog:Show() flickerstreak@10: else flickerstreak@17: ReBound:HideRegisteredFrames() flickerstreak@10: if ReActionKeybindDialog:IsShown() then flickerstreak@10: ReActionKeybindDialog:Hide() flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: end flickerstreak@10: flickerstreak@17: function main:HideKeybindDialog( frame ) flickerstreak@17: self:SetKeybindMode(false) flickerstreak@17: if frame.save then flickerstreak@17: ReBound:SaveBindings() flickerstreak@17: else flickerstreak@17: ReBound:RevertBindings() flickerstreak@17: end flickerstreak@17: frame.save = false flickerstreak@17: end flickerstreak@10: flickerstreak@10: flickerstreak@10: ---------------------------- flickerstreak@10: -- Bar lock/unlock functions flickerstreak@10: ---------------------------- flickerstreak@10: function main:CombatLockdown() flickerstreak@10: if not self:IsLocked() then flickerstreak@10: self:Lock() flickerstreak@10: UIErrorsFrame:AddMessage(L["ReAction bars locked when in combat"]) flickerstreak@10: end flickerstreak@10: ReActionKeybindDialog:Hide() flickerstreak@10: end flickerstreak@10: flickerstreak@7: function main:SetLocked( lock ) flickerstreak@2: if lock ~= self.locked then flickerstreak@2: if not lock and InCombatLockdown() then flickerstreak@10: UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT) flickerstreak@2: else flickerstreak@2: self.locked = lock and true or false -- force data integrity flickerstreak@2: for _, bar in pairs(self.bars) do flickerstreak@7: if bar ~= EMPTY_BAR_SLOT then flickerstreak@7: if self.locked then flickerstreak@7: bar:HideControls() flickerstreak@7: -- close any dewdrop menu owned by the bar flickerstreak@7: if bar:GetControlFrame() == dewdrop:GetOpenedParent() then flickerstreak@7: dewdrop:Close() flickerstreak@7: end flickerstreak@7: else flickerstreak@7: bar:ShowControls() flickerstreak@7: end flickerstreak@7: end flickerstreak@2: end flickerstreak@2: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:IsLocked() flickerstreak@1: return self.locked flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:Lock() flickerstreak@1: self:SetLocked(true) flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:Unlock() flickerstreak@1: self:SetLocked(false) flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:ToggleLocked() flickerstreak@17: self:SetLocked( not(self.locked) ) flickerstreak@1: end flickerstreak@1: flickerstreak@1: flickerstreak@1: flickerstreak@10: -------------------------------------------------------- flickerstreak@10: -- Functions to hide the default Blizzard main bar parts flickerstreak@10: -------------------------------------------------------- flickerstreak@7: function main:HideArt() flickerstreak@1: if self.db.profile.hideArt then flickerstreak@17: -- the pet bar is a child of MainMenuBar, but can't be hidden because it will flickerstreak@17: -- break automatic pet bar show/hide. Need to reparent it. flickerstreak@7: PetActionBarFrame:SetParent(UIParent) flickerstreak@17: flickerstreak@7: -- these two are the pet bar background flickerstreak@7: -- unfortunately UIParent_ManageFramePositions() shows and hides these too flickerstreak@7: -- so they get reparented to MainMenuBar flickerstreak@7: SlidingActionBarTexture0:SetParent(MainMenuBar) flickerstreak@7: SlidingActionBarTexture1:SetParent(MainMenuBar) flickerstreak@17: flickerstreak@17: MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons. flickerstreak@1: else flickerstreak@7: SlidingActionBarTexture0:SetParent(PetActionBarFrame) flickerstreak@7: SlidingActionBarTexture1:SetParent(PetActionBarFrame) flickerstreak@17: PetActionBarFrame:SetParent(MainMenuBar) flickerstreak@1: MainMenuBar:Show() flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:IsArtHidden() flickerstreak@1: return self.db.profile.hideArt flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:SetHideArt( hide ) flickerstreak@2: if InCombatLockdown() then flickerstreak@2: UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) flickerstreak@2: else flickerstreak@2: self.db.profile.hideArt = hide and true or false -- force data integrity flickerstreak@2: self:HideArt() flickerstreak@2: end flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:ToggleHideArt() flickerstreak@1: self:SetHideArt( not self:IsArtHidden() ) flickerstreak@1: end flickerstreak@1: flickerstreak@1: -- Hide default Blizzard bars flickerstreak@1: local blizzDefaultBars = { flickerstreak@1: ActionButton1, flickerstreak@1: ActionButton2, flickerstreak@1: ActionButton3, flickerstreak@1: ActionButton4, flickerstreak@1: ActionButton5, flickerstreak@1: ActionButton6, flickerstreak@1: ActionButton7, flickerstreak@1: ActionButton8, flickerstreak@1: ActionButton9, flickerstreak@1: ActionButton10, flickerstreak@1: ActionButton11, flickerstreak@1: ActionButton12, flickerstreak@7: PetActionButton1, flickerstreak@7: PetActionButton2, flickerstreak@7: PetActionButton3, flickerstreak@7: PetActionButton4, flickerstreak@7: PetActionButton5, flickerstreak@7: PetActionButton6, flickerstreak@7: PetActionButton7, flickerstreak@7: PetActionButton8, flickerstreak@7: PetActionButton9, flickerstreak@7: PetActionButton10, flickerstreak@7: -- NOT the PetActionBarFrame, though - we need that to auto-hide/show our pet action bars flickerstreak@7: MainMenuBarPageNumber, flickerstreak@7: ActionBarUpButton, flickerstreak@7: ActionBarDownButton, flickerstreak@1: BonusActionBarFrame, flickerstreak@7: ShapeshiftBarFrame, flickerstreak@1: MultiBarLeft, flickerstreak@1: MultiBarRight, flickerstreak@1: MultiBarBottomLeft, flickerstreak@7: MultiBarBottomRight, flickerstreak@1: } flickerstreak@1: flickerstreak@7: local function disableUIOptions() flickerstreak@7: -- disable the buttons to hide/show the blizzard multiaction bars flickerstreak@7: -- see UIOptionsFrame.lua and .xml flickerstreak@7: -- This is called every time the options panel is shown, after it is set up flickerstreak@7: for _, idx in pairs( { 33, 34, 35, 36, 37, 40 } ) do flickerstreak@7: local f = getglobal("UIOptionsFrameCheckButton"..idx) flickerstreak@7: f.disabled = true flickerstreak@7: OptionsFrame_DisableCheckBox(f) flickerstreak@7: f:SetChecked(false) flickerstreak@7: end flickerstreak@7: end flickerstreak@1: flickerstreak@7: function main:HideDefaultBars() flickerstreak@7: for _, f in pairs(blizzDefaultBars) do flickerstreak@7: f:Hide() flickerstreak@7: f:ClearAllPoints() flickerstreak@7: f:SetParent(ReAction.recycler) flickerstreak@7: f:SetPoint("TOPLEFT") flickerstreak@7: end flickerstreak@7: flickerstreak@7: MainMenuBar:SetFrameStrata("LOW") -- otherwise it appears on top of bars, if it isn't hidden flickerstreak@7: hooksecurefunc("UIOptionsFrame_Load",disableUIOptions) flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@10: flickerstreak@10: flickerstreak@10: --------------------------------------- flickerstreak@10: -- Bar setup and manipulation functions flickerstreak@10: --------------------------------------- flickerstreak@7: -- Reset bars to blizzard defaults flickerstreak@7: function main:ResetBars() flickerstreak@2: if InCombatLockdown() then flickerstreak@2: UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) flickerstreak@2: else flickerstreak@7: self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars) flickerstreak@17: self:OnProfileEnable() -- treat it like a profile switch flickerstreak@2: end flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:DestroyAllBars() flickerstreak@7: -- destroy any existing bars flickerstreak@7: for id = 1, table.maxn(self.bars) do flickerstreak@7: self:DestroyBar(id) flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function main:SetupBars() flickerstreak@1: -- set up the bars from the profile flickerstreak@2: -- note the use of table.maxn rather than # or ipairs: flickerstreak@2: -- our array of bars can in fact contain holes flickerstreak@2: for id = 1, table.maxn(self.db.profile.bars) do flickerstreak@2: local config = self.db.profile.bars[id] flickerstreak@2: if config then flickerstreak@17: self.bars[id] = self:CreateBar(config, id) flickerstreak@2: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: -- anchor the bars, have to do this in a second pass because flickerstreak@1: -- they might be anchored to each other in a non-ordered way flickerstreak@2: for _, bar in pairs(self.bars) do flickerstreak@7: if bar ~= EMPTY_BAR_SLOT then flickerstreak@7: bar:ApplyAnchor() flickerstreak@2: end flickerstreak@2: end flickerstreak@1: end flickerstreak@1: flickerstreak@7: function main:CreateBar( config, id ) flickerstreak@17: local buttonType = config.btnConfig and config.btnConfig.type and getglobal(config.btnConfig.type) flickerstreak@17: local subtype = buttonType and buttonType:GetButtonType(config.btnConfig.subtype) flickerstreak@17: flickerstreak@17: if not subtype then flickerstreak@17: self:Print(L["Tried to create a button of unknown type"]) flickerstreak@17: return flickerstreak@17: end flickerstreak@17: flickerstreak@7: local bar = ReBar:new(config, id) flickerstreak@1: flickerstreak@17: -- initialize dewdrop menu flickerstreak@17: dewdrop:Register(bar:GetControlFrame(), flickerstreak@17: 'children', flickerstreak@17: function() flickerstreak@17: dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions) flickerstreak@17: dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(bar,self)) flickerstreak@17: dewdrop:FeedAceOptionsTable(subtype:GenerateOptionsTable(config.btnConfig, function() return bar:GetButtonList() end)) flickerstreak@17: end, flickerstreak@17: 'cursorX', true, flickerstreak@17: 'cursorY', true flickerstreak@17: ) flickerstreak@7: flickerstreak@17: -- register page up/down buttons with ReBound for keybinding flickerstreak@17: ReBound:Register(bar.upArrow) flickerstreak@17: ReBound:Register(bar.downArrow) flickerstreak@7: flickerstreak@17: if not self.locked then flickerstreak@17: bar:ShowControls() flickerstreak@17: end flickerstreak@7: flickerstreak@17: return bar flickerstreak@7: end flickerstreak@7: flickerstreak@7: function main:DestroyBar( id ) flickerstreak@7: local bar = self.bars[id] flickerstreak@7: if bar and bar ~= EMPTY_BAR_SLOT then flickerstreak@7: local cf = bar:GetControlFrame() flickerstreak@7: if cf == dewdrop:GetOpenedParent() then flickerstreak@7: dewdrop:Close() flickerstreak@7: dewdrop:Unregister(cf) flickerstreak@7: end flickerstreak@7: bar:Destroy() flickerstreak@7: -- we can't do tremove because each bar ID is encoded into the flickerstreak@7: -- frame names as they're created. Need a blank entry in the table. flickerstreak@7: -- The nice thing is that table.insert in NewBar() will automatically flickerstreak@7: -- find the lowest numbered nil slot. flickerstreak@7: self.bars[id] = EMPTY_BAR_SLOT flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@10: -- flickerstreak@10: -- this function is a wrapper for CreateBar() which looks up the bar type flickerstreak@10: -- and constructs a new configuration object of the right type. flickerstreak@7: function main:NewBar( type ) flickerstreak@7: if InCombatLockdown() then flickerstreak@7: UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) flickerstreak@17: return flickerstreak@17: end flickerstreak@17: flickerstreak@17: local t = ReAction:GetButtonType(type) flickerstreak@17: if t then flickerstreak@17: local c = tcopy(ReAction_DefaultBarConfig["ReAction"][type]) flickerstreak@17: local id = nil flickerstreak@17: for i = 1, table.maxn(self.bars) + 1 do -- there may be holes, so #self.bars won't work flickerstreak@17: if self.bars[i] == nil or self.bars[i] == EMPTY_BAR_SLOT then flickerstreak@17: id = i flickerstreak@17: break flickerstreak@7: end flickerstreak@7: end flickerstreak@17: self.bars[id] = self:CreateBar(c, id) flickerstreak@17: self.db.profile.bars[id] = c flickerstreak@17: self.bars[id]:ApplyAnchor() flickerstreak@17: self:Unlock() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@10: -- flickerstreak@10: -- This function is a wrapper for DestroyBar() which does in-combat flickerstreak@10: -- checking and updates the config. flickerstreak@7: function main:DeleteBar(id) flickerstreak@2: if InCombatLockdown() then flickerstreak@2: UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) flickerstreak@2: else flickerstreak@2: if self.bars[id] then flickerstreak@7: self:DestroyBar(id) flickerstreak@2: self.db.profile.bars[id] = nil flickerstreak@2: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@10: flickerstreak@10: