diff main.lua @ 7:f920db5fc6b1

version 0.3
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:25:29 +0000
parents dfd829db3ad0
children c05fd3e18b4f
line wrap: on
line diff
--- a/main.lua	Tue Mar 20 21:20:20 2007 +0000
+++ b/main.lua	Tue Mar 20 21:25:29 2007 +0000
@@ -1,23 +1,16 @@
--- ReAction.lua
+-- main.lua
 -- 
 -- Top-level file for the ReAction Action Bar add-on
 --
--- ReAction is implemented in terms of the Ace 2 library: http://www.wowace.com
+-- implemented in terms of the Ace 2 development framework library: http://www.wowace.com
 --
 
--- key binding label constants
-BINDING_HEADER_REACTION                 = "ReAction"
-BINDING_NAME_REACTION_TOGGLELOCK        = "Lock/Unlock ReAction Bars"
-BINDING_NAME_REBINDER_TOGGLEBINDINGMODE = "Toggle ReAction keybinding mode"
+-- Ace Library local object initialization
+local L       = AceLibrary("AceLocale-2.2"):new("ReAction")
+local dewdrop = AceLibrary("Dewdrop-2.0")
+local tablet  = AceLibrary("Tablet-2.0")
 
--- ReAction addon setup via Ace 2
-ReAction = AceLibrary("AceAddon-2.0"):new(
-  "AceConsole-2.0",
-  "AceEvent-2.0",
-  "AceDB-2.0",
-  "FuBarPlugin-2.0"
-)
-
+-- private functions
 local function tcopy(t)
   local r = { }
   for k, v in pairs(t) do
@@ -26,109 +19,180 @@
   return r
 end
 
--- FuBar plugin setup
-ReAction.hasIcon = false
-ReAction.hasNoColor = true
-ReAction.hideMenuTitle = true
-ReAction.defaultPosition = "RIGHT"
-ReAction.defaultMinimapPosition = 240 -- degrees
-ReAction.OnMenuRequest = tcopy(ReActionGlobalMenuOptions)
+-- private constants
+local EMPTY_BAR_SLOT = -1
+
+-- key binding label constants
+BINDING_HEADER_REACTION                = L["ReAction"]
+BINDING_NAME_REACTION_TOGGLELOCK       = L["Toggle ReAction Bar Lock"]
+BINDING_NAME_REBOUND_TOGGLEBINDINGMODE = L["Toggle ReBound Keybinding Mode"]
+
+
+-- main object
+local main = AceLibrary("AceAddon-2.0"):new(
+  "AceConsole-2.0",
+  "AceEvent-2.0",
+  "AceDB-2.0",
+  "FuBarPlugin-2.0"
+)
 
 -- initial non-persistent state
-ReAction.locked = true
+main.locked = true
 
--- localization
--- local L = AceLibrary("AceLocale-2.0"):new("ReAction")
+-- set a global variable for Bindings.xml
+ReActionAddOn = main
+
+
+-- FuBar plugin setup
+-- Even if FuBar isn't installed, this gives us a nice minimap-button interface.
+main.hasIcon = "Interface\\Icons\\INV_Qiraj_JewelEncased"
+main.hasNoColor = true
+main.hideMenuTitle = true
+main.defaultPosition = "LEFT"
+main.defaultMinimapPosition = 240 -- degrees
+main.OnMenuRequest = tcopy(ReActionGlobalMenuOptions) -- use a copy, or bar menus will have FuBar inserted items
+main.independentProfile = true
+
+-- set the handler for the global bar menu options
+-- have to do this after tcopy() above, otherwise it will try to copy the handler object (bad idea)
+ReActionGlobalMenuOptions.handler = main
+
 
 
 
 -- Event handling
-function ReAction:OnInitialize()
-  self:RegisterChatCommand( {"/reaction", "/rxn"}, ReActionConsoleOptions, "REACTION" )
-
+function main:OnInitialize()
+  self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" )
   self:RegisterDB("ReActionDB","ReActionDBPC")
-  self:RegisterDefaults("profile", ReActionProfileDefaults)
+  self:RegisterDefaults("profile", ReAction_DefaultProfile)
   self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
   self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
+  self:RegisterEvent("EVENT_REBOUND_KEYBINDING_MODE")
 end
 
-function ReAction:OnEnable()
+function main:OnEnable()
+  -- this gets called at startup and when the profile is changed
   if self.db.profile.firstRunDone ~= true then
     -- Do some "first-run" setup
+    self:StealKeyBindings()
     self.db.profile.firstRunDone = true
-  elseif self.db.profile.disabled == true then
-    -- print some kind of a warning
+    self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
   end
+  self:DestroyAllBars()
   self:SetupBars()
 end
 
-function ReAction:OnDisable()
+function main:OnDisable()
   self:Lock()
 end
 
-function ReAction:OnProfileEnable()
-  -- handle profile switching
-  self:Lock()
-  self:SetupBars()
+function main:OnProfileEnable()
+  -- for profile switching
+  self:OnEnable()
 end
 
-function ReAction:CombatLockdown()
+function main:CombatLockdown()
   if not self:IsLocked() then
     self:Lock()
-    UIErrorsFrame:AddMessage("ReAction bars locked when in combat")
+    ReBound:Disable()
+    UIErrorsFrame:AddMessage(L["ReAction bars locked when in combat"])
   end
 end
 
+function main:EVENT_REBOUND_KEYBINDING_MODE(enabled)
+  for _, bar in pairs(self.bars) do
+    for __, button in pairs(bar.buttons) do
+      button:TempShow(enabled)
+    end
+  end
+end
 
--- lock/unlock ReAction
-function ReAction:SetLocked( lock )
+
+-- FuBar plugin methods
+function main:OnTooltipUpdate()
+	local c = tablet:AddCategory("columns", 2)
+	c:AddLine("text", L["Bar lock"], "text2", self.locked and ("|cffff0000"..L["Locked"].."|r") or ("|cffffcc00"..L["Unlocked"].."|r"))
+  c:AddLine("text", L["Button lock"], "text2", LOCK_ACTIONBAR == "1" and ("|cffcc0000"..L["Locked"].."|r") or ("|cff00cc00"..L["Unlocked"].."|r"))
+  c:AddLine("text", L["Kebinding mode"], "text2", ReBound:IsEnabled() and ("|cff33ff33"..L["On"].."|r") or ("|cffffcc00"..L["Off"].."|r"))
+	tablet:SetHint(L["|cffffcc00Shift-Click for bar lock|n|cff33ff33Alt-Click|r for keybindings|nRight-click for menu"])
+end
+
+function main:OnClick(button)
+	if IsShiftKeyDown() then
+	  self:ToggleLocked()
+    self:UpdateDisplay()
+	elseif IsAltKeyDown() then
+    ReBound:ToggleEnabled()
+    self:UpdateDisplay()
+  end
+end
+
+
+-- lock/unlock bars
+function main:SetLocked( lock )
   if lock ~= self.locked then
-    if not lock then
-      self:Print("Buttons disabled while unlocked")
-    end
     if not lock and InCombatLockdown() then
       UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
     else
       self.locked = lock and true or false -- force data integrity
       for _, bar in pairs(self.bars) do
-        if self.locked then bar:HideControls() else bar:ShowControls() end
+        if bar ~= EMPTY_BAR_SLOT then
+          if self.locked then 
+            bar:HideControls()
+            -- close any dewdrop menu owned by the bar
+            if bar:GetControlFrame() == dewdrop:GetOpenedParent() then
+              dewdrop:Close()
+            end
+          else
+            bar:ShowControls() 
+          end
+        end
       end
     end
   end
 end
 
-function ReAction:IsLocked()
+function main:IsLocked()
   return self.locked
 end
 
-function ReAction:Lock()
+function main:Lock()
   self:SetLocked(true)
 end
 
-function ReAction:Unlock()
+function main:Unlock()
   self:SetLocked(false)
 end
 
-function ReAction:ToggleLocked()
-  ReAction:SetLocked( not(self.locked) )
+function main:ToggleLocked()
+  main:SetLocked( not(self.locked) )
 end
 
 
 
 -- Hide the default Blizzard main bar artwork
-function ReAction:HideArt()
+function main:HideArt()
   if self.db.profile.hideArt then
+    -- the pet bar is a child of MainMenuBar, and can't be hidden. Need to reparent it
+    PetActionBarFrame:SetParent(UIParent)
     MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons.
+    -- these two are the pet bar background
+    -- unfortunately UIParent_ManageFramePositions() shows and hides these too
+    -- so they get reparented to MainMenuBar
+    SlidingActionBarTexture0:SetParent(MainMenuBar)
+    SlidingActionBarTexture1:SetParent(MainMenuBar)
   else
+    SlidingActionBarTexture0:SetParent(PetActionBarFrame)
+    SlidingActionBarTexture1:SetParent(PetActionBarFrame)
     MainMenuBar:Show()
   end
 end
 
-function ReAction:IsArtHidden()
+function main:IsArtHidden()
   return self.db.profile.hideArt
 end
 
-function ReAction:SetHideArt( hide )
+function main:SetHideArt( hide )
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
   else
@@ -137,27 +201,12 @@
   end
 end
 
-function ReAction:ToggleHideArt()
+function main:ToggleHideArt()
   self:SetHideArt( not self:IsArtHidden() )
 end
 
 
 
--- Keybinding color coding
-function ReAction:SetKeyColorCoding( cc )
-  self.db.profile.keyColorCode = cc
-end
-
-function ReAction:IsKeyColorCodeEnabled()
-  return self.db.profile.keyColorCode
-end
-
-function ReAction:ToggleKeyColorCoding()
-  self:SetKeyColorCoding(not self.db.profile.keyColorCode)
-end
-
-
-
 -- Hide default Blizzard bars
 local blizzDefaultBars = {
   ActionButton1,
@@ -172,143 +221,216 @@
   ActionButton10,
   ActionButton11,
   ActionButton12,
+  PetActionButton1,
+  PetActionButton2,
+  PetActionButton3,
+  PetActionButton4,
+  PetActionButton5,
+  PetActionButton6,
+  PetActionButton7,
+  PetActionButton8,
+  PetActionButton9,
+  PetActionButton10,
+  -- NOT the PetActionBarFrame, though - we need that to auto-hide/show our pet action bars
+  MainMenuBarPageNumber,
+  ActionBarUpButton,
+  ActionBarDownButton,
   BonusActionBarFrame,
+  ShapeshiftBarFrame,
   MultiBarLeft,
   MultiBarRight,
   MultiBarBottomLeft,
-  MultiBarBottomRight
+  MultiBarBottomRight,
 }
 
-function ReAction:HideDefaultBars()
-  for _, f in pairs(blizzDefaultBars) do
-    f:UnregisterAllEvents()
-    f:Hide()
-    f:SetParent(ReActionButtonRecycler) -- I mean it!
-    f:ClearAllPoints()                  -- no, I really mean it!
+function main:StealKeyBindings()
+  -- steal the keybindings of the main action bar and assign them to rebar 1, buttons 1-12
+  for i = 1, 12 do
+    -- TODO: when we convert to override bindings
   end
 end
 
+local function disableUIOptions()
+  -- disable the buttons to hide/show the blizzard multiaction bars
+  -- see UIOptionsFrame.lua and .xml
+  -- This is called every time the options panel is shown, after it is set up
+  for _, idx in pairs( { 33, 34, 35, 36, 37, 40 } ) do
+    local f = getglobal("UIOptionsFrameCheckButton"..idx)
+    f.disabled = true
+    OptionsFrame_DisableCheckBox(f)
+    f:SetChecked(false)
+  end
+end
 
--- Reset bars to defaults
-function ReAction:ResetBars()
+function main:HideDefaultBars()
+  for _, f in pairs(blizzDefaultBars) do
+    f:Hide()
+    f:ClearAllPoints()
+    f:SetParent(ReAction.recycler)
+    f:SetPoint("TOPLEFT")
+  end
+
+  MainMenuBar:SetFrameStrata("LOW") -- otherwise it appears on top of bars, if it isn't hidden
+  hooksecurefunc("UIOptionsFrame_Load",disableUIOptions)
+end
+
+
+-- Reset bars to blizzard defaults
+function main:ResetBars()
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
   else
-    self.db.profile.bars = ReActionProfileDefaults.bars
+    self:DestroyAllBars()
+    self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
     self:SetupBars()
   end
 end
 
 
 -- re-sync action IDs
-function ReAction:ResyncActionIDs()
+function main:ResyncActionIDs()
   -- TODO
 end
 
 
 
 -- Bar manipulation
-ReAction.bars    = { }
+main.bars    = { }
 
-function ReAction:SetupBars()
+function main:DestroyAllBars()
+  -- destroy any existing bars
+  for id = 1, table.maxn(self.bars) do
+    self:DestroyBar(id)
+  end
+end
+
+
+function main:SetupBars()
   -- hide the default Blizzard art, if configued
   self:HideArt()
-  -- hide the default Blizzard bars
-  self:HideDefaultBars()
 
   -- set up the bars from the profile
   -- note the use of table.maxn rather than # or ipairs: 
   -- our array of bars can in fact contain holes
   for id = 1, table.maxn(self.db.profile.bars) do
     local config = self.db.profile.bars[id]
-    if self.bars[id] then 
-      self.bars[id]:Destroy() -- remove old version of bar if switching profiles 
-    end
     if config then
-      self.bars[id] = ReBar:new(config, id)
-    end
-  end
-  
-  -- remove excess bars
-  for id = table.maxn(self.db.profile.bars) + 1, table.maxn(self.bars) do
-    if self.bars[id] then
-      self.bars[id]:Destroy()
-      self.bars[id] = nil
+      self:CreateBar(config, id)
     end
   end
   
   -- anchor the bars, have to do this in a second pass because
   -- they might be anchored to each other in a non-ordered way
   for _, bar in pairs(self.bars) do
-    bar:ApplyAnchor()
-  end
-end
-
-
-function ReAction:NewBar()
-  if InCombatLockdown() then
-    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-  else
-    local c = tcopy(ReActionBarConfigDefaults)
-    local bar = ReBar:new(c, #self.bars+1)
-    table.insert(self.bars, bar)
-    table.insert(self.db.profile.bars, c) 
-    if not self.locked then
-      bar:ShowControls()
+    if bar ~= EMPTY_BAR_SLOT then
+      bar:ApplyAnchor()
     end
   end
 end
 
+function main:CreateBar( config, id )
+  local bar = ReBar:new(config, id)
+  local buttonType = ReAction:GetButtonType(config.btnConfig.subtype)
 
-function ReAction:DeleteBar(id)
+  if buttonType then
+    self.bars[id] = bar
+    self.db.profile.bars[id] = config
+
+    -- initialize dewdrop menu
+    local cf = bar:GetControlFrame()
+    dewdrop:Register(cf, 
+      'children', 
+      function()
+        dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
+        dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(bar,self))
+        dewdrop:FeedAceOptionsTable(buttonType:GenerateOptionsTable(config.btnConfig, function() return bar:GetButtonList() end))
+      end,
+      'cursorX', true, 
+      'cursorY', true
+    )
+
+    bar:GetControlFrame():SetScript("OnClick", 
+      function(btn)
+        if btn == "RightButton" then
+          dewdrop:Open(cf)
+        end
+      end
+    )
+
+    if not self.locked then
+      bar:ShowControls()
+    end
+    return bar
+  else
+    if bar then
+      bar:Destroy()
+    end
+    error(L["Tried to create a button of unknown type"])
+  end
+end
+
+function main:DestroyBar( id )
+  local bar = self.bars[id]
+  if bar and bar ~= EMPTY_BAR_SLOT then 
+    local cf = bar:GetControlFrame()
+    if cf == dewdrop:GetOpenedParent() then
+      dewdrop:Close()
+      dewdrop:Unregister(cf)
+    end
+    bar:Destroy()
+    -- we can't do tremove because each bar ID is encoded into the
+    -- frame names as they're created. Need a blank entry in the table.
+    -- The nice thing is that table.insert in NewBar() will automatically
+    -- find the lowest numbered nil slot.
+    self.bars[id] = EMPTY_BAR_SLOT
+  end
+end
+
+function main:NewBar( type )
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+  else
+    local t = ReAction:GetButtonType(type)
+    if t then
+      local c = tcopy(ReAction_DefaultBarConfig["ReAction"][type])
+      local id = nil
+      for i = 1, table.maxn(self.bars) + 1 do  -- there may be holes, so #self.bars won't work
+        if self.bars[i] == nil or self.bars[i] == EMPTY_BAR_SLOT then
+          id = i
+          break
+        end
+      end
+      local bar = self:CreateBar(c, id)
+      bar:ApplyAnchor()
+      self:Unlock()
+    end
+  end
+end
+
+
+function main:DeleteBar(id)
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
   else
     if self.bars[id] then
-      -- we can't do tremove because each bar ID is encoded into the
-      -- frame names as they're created. Need a nil entry in the table.
-      -- The nice thing is that table.insert in NewBar() will automatically
-      -- find the first nil slot.
-      self.bars[id]:Destroy()
-      self.bars[id] = nil
+      self:DestroyBar(id)
       self.db.profile.bars[id] = nil
     end
   end
 end
 
-function ReAction:ToggleActionID()
-  if self.showActionIDs then
-    ReActionButton:HideAllActionIDs()
+function main:ToggleIds()
+  if self.showIds then
+    ReAction:HideAllIds()
   else
-    ReActionButton:ShowAllActionIDs()
+    ReAction:ShowAllIds()
   end
-  self.showActionIDs = not self.showActionIDs
+  self.showIds = not self.showIds
 end
 
-function ReAction:IsActionIDVisible()
-  return self.showActionIDs
+function main:AreIdsVisible()
+  return self.showIds
 end
 
 
 
--- FuBar plugin methods
-local tablet = AceLibrary("Tablet-2.0")
-
-function ReAction:OnTooltipUpdate()
-	local c = tablet:AddCategory("columns", 2)
-	c:AddLine("text", "Bar lock", "text2", self.locked and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
-  c:AddLine("text", "Button lock", "text2", LOCK_ACTIONBAR == "1" and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
-  c:AddLine("text", "Kebinding mode", "text2", ReBinder:IsEnabled() and "|cff33ff33On|r" or "|cffffcc00Off|r")
-	tablet:SetHint("|cffffcc00Shift-Click|r for bar lock|n"..
-                 "|cff33ff33Alt-Click|r for keybindings|n"..
-                 "Right-click for menu")
-end
-
-function ReAction:OnClick(button)
-	if IsShiftKeyDown() then
-	  self:ToggleLocked()
-    self:UpdateDisplay()
-	elseif IsAltKeyDown() then
-    ReBinder:ToggleEnabled()
-  end
-end