changeset 17:639282f3a0e0

More cleanup of main.lua, ReBound-1.0.lua
author Flick <flickerstreak@gmail.com>
date Fri, 23 Mar 2007 19:28:30 +0000
parents 832aab6fed49
children a805e4464237
files Buttons.lua ReAction.toc libs/ReBound-1.0/ReBound-1.0.lua main.lua
diffstat 4 files changed, 256 insertions(+), 168 deletions(-) [+]
line wrap: on
line diff
--- a/Buttons.lua	Thu Mar 22 21:08:43 2007 +0000
+++ b/Buttons.lua	Fri Mar 23 19:28:30 2007 +0000
@@ -4,7 +4,7 @@
 --
 
 local AceOO = AceLibrary("AceOO-2.0")
-local ReBound = AceLibrary("ReBound-1.0"):new("REACTION")
+local ReBound = AceLibrary("ReBound-1.0"):new("ReAction")
 
 local Action = AceOO.Class(
   ReAction, 
--- a/ReAction.toc	Thu Mar 22 21:08:43 2007 +0000
+++ b/ReAction.toc	Fri Mar 23 19:28:30 2007 +0000
@@ -42,8 +42,7 @@
 Defaults.lua
 Options.lua
 
+main.lua
+
 KeybindDialog.xml
 
-main.lua
-
-
--- a/libs/ReBound-1.0/ReBound-1.0.lua	Thu Mar 22 21:08:43 2007 +0000
+++ b/libs/ReBound-1.0/ReBound-1.0.lua	Fri Mar 23 19:28:30 2007 +0000
@@ -1,27 +1,50 @@
 --[[
 Name: ReBound-1.0
-Revision: $Rev: 2 $
+Revision: $Rev: 3 $
 Author: Flick
 Website: 
 Documentation: 
 SVN: 
 Description: A library to assist with click-binding
 License: MIT
-Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2, AceOO-2.0
+Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2, AceOO-2.0, AceConsole-2.0
 ]]
 
 
-local version_major, version_minor = "ReBound-1.0", "$Rev: 2 $"
+local version_major, version_minor = "ReBound-1.0", "$Rev: 3 $"
 
 if not AceLibrary then error(version_major .. " requires AceLibrary.") end
 if not AceLibrary:IsNewVersion(version_major, version_minor) then return end
-if not AceLibrary:HasInstance("AceEvent-2.0") then error(version_major .. " requires AceEvent-2.0.") end
-if not AceLibrary:HasInstance("AceLocale-2.2") then error(version_major .. " requires AceLocale-2.2.") end
-if not AceLibrary:HasInstance("AceOO-2.0") then error(version_major .. " requires AceOO-2.0.") end
+for _, lib in pairs({ "AceEvent-2.0", "AceLocale-2.2", "AceOO-2.0", "AceConsole-2.0" }) do
+  if not AceLibrary:HasInstance(lib) then error(version_major .. " requires "..lib) end
+end
 
 local L = AceLibrary("AceLocale-2.2"):new("ReBound")
 
+-- localization
+L:RegisterTranslations( "enUS", function()
+  return {
+    ["none"] = true,
+    ["Click"] = true,
+    ["Right-click"] = true,
+    ["Shift-click"] = true,
+    ["Shift-right-click"] = true,
+    ["Right Click"] = true,
+    ["to select for binding"] = true,
+    ["to select for alternate (right-click) binding"] = true,
+    ["to clear binding"] = true,
+    ["to clear alternate (right-click) binding"] = true,
+    ["Press a key to assign binding"] = true,
+    ["is now unbound"] = true,
+  }
+end )
+
+
+
+local kbValidate = AceLibrary("AceConsole-2.0").keybindingValidateFunc
+
 local colorGreen = "|cff00ff00"
+local colorOrange = "|cffffcc00"
 local colorOff = "|r"
 
 local mouseButtonConvert = {
@@ -32,20 +55,42 @@
   Button5 = "BUTTON5"
 }
 
---local BINDING_PENDING = { }  -- a constant
-
--- localization
-L:RegisterTranslations( "enUS", function()
-  return {
-    ["none"] = true,
-    ["Right-click"] = true,
-    ["Right Click"] = true,
-    ["Click to select for binding"] = true,
-    ["Shift-click to clear binding"] = true,
-    ["Press a key to assign binding"] = true,
-    ["is now unbound"] = true,
-  }
-end )
+-- TODO: localize
+local keybindAbbreviations = {
+  [KEY_BACKSPACE]      = "BkSp",
+  [KEY_BUTTON3]        = "M-3",
+  [KEY_BUTTON4]        = "M-4",
+  [KEY_BUTTON5]        = "M-5",
+  [KEY_DOWN]           = "Down",
+  [KEY_ESCAPE]         = "Esc",
+  [KEY_INSERT]         = "Ins",
+  [KEY_LEFT]           = "Left",
+  [KEY_MOUSEWHEELDOWN] = "M-Down",
+  [KEY_MOUSEWHEELUP]   = "M-Up",
+  [KEY_NUMLOCK]        = "NumLk",
+  [KEY_NUMPAD0]        = "Np0",
+  [KEY_NUMPAD1]        = "Np1",
+  [KEY_NUMPAD2]        = "Np2",
+  [KEY_NUMPAD3]        = "Np3",
+  [KEY_NUMPAD4]        = "Np4",
+  [KEY_NUMPAD5]        = "Np5",
+  [KEY_NUMPAD6]        = "Np6",
+  [KEY_NUMPAD7]        = "Np7",
+  [KEY_NUMPAD8]        = "Np8",
+  [KEY_NUMPAD9]        = "Np9",
+  [KEY_NUMPADDECIMAL]  = "Np.",
+  [KEY_NUMPADDIVIDE]   = "Np/",
+  [KEY_NUMPADMINUS]    = "Np-",
+  [KEY_NUMPADMULTIPLY] = "Np*",
+  [KEY_NUMPADPLUS]     = "Np+",
+  [KEY_PAGEDOWN]       = "PgDn",
+  [KEY_PAGEUP]         = "PgUp",
+  [KEY_PRINTSCREEN]    = "PrScr",
+  [KEY_RIGHT]          = "Right",
+  [KEY_SCROLLLOCK]     = "ScrLk",
+  [KEY_SPACE]          = "Sp",
+  [KEY_UP]             = "Up",
+}
 
 
 local ReBound = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
@@ -71,16 +116,12 @@
   Calls to new() which share ids will return an existing object with that id, similar
   to AceLocale-2.2.
 ]]
+ReBound.instances = { }
 local super_new = ReBound.new
 function ReBound:new( id )
-  self.instances = self.instances or { }
-  if self.instances[id] then
-    return self.instances[id]
-  else
-    local i = super_new(self,id)
-    self.instances[id] = i
-    return i
-  end
+  local instances = self.instances
+  instances[id] = instances[id] or super_new(self,id)
+  return instances[id]
 end
 
 
@@ -91,7 +132,7 @@
     id : the ID that will be provided in events. This can be absolutely 
          anything, but a string is recommended.
 ]]
-local super_init = ReBound.prototype.init
+local super_init = ReBound.super.prototype.init
 function ReBound.prototype:init( id )
   super_init(self)
 
@@ -109,6 +150,7 @@
   key: A string representation of a key, suitable for passing to SetBinding.
   target: The frame with an OnClick handler to which the click-binding should be attached
   [button]: The mouse button to emulate. Default is "LeftButton".
+  [silent]: boolean - whether to suppress messages about keys being unbound.
 
   Returns:
   nothing.
@@ -119,6 +161,8 @@
 function ReBound.prototype:SetBinding( key, target, button )
   if not key then error("ReBound:SetBinding() requires a key argument.") end
   if not target then error("ReBound:SetBinding() requires a binding target argument") end
+  if key and not kbValidate(key) then error("ReBound:SetBinding(): invalid key code "..tostring(key)) end
+
   button = button or "LeftButton"
 
   -- prevent setting a binding that's already set
@@ -131,7 +175,7 @@
 
   -- clear the old binding for the key. This isn't strictly necessary, but it allows us to collect
   -- notification of the unbinding in one place (ClearBinding).
-  self:ClearBinding( key )
+  self:ClearBinding( key, nil, nil, silent )
 
   -- clear the old binding for the target and button (silently)
   self:ClearBinding( nil, target, button, true )
@@ -214,6 +258,33 @@
 
 
 --[[
+  Gets the localized, abbreviated key cap text for the primary binding on a target. 
+  Abbreviations are more aggressive than the standard Blizzard abbreviation
+  (which just shortens modifier keys)
+
+  Arguments:
+  target: target frame to query
+  [abbrev]: boolean flag to abbreviate the result
+  [button]: mouse button to emulate ("LeftButton", "RightButton")
+
+  Returns:
+  abbreviated, localized key label
+]]
+function ReBound.prototype:GetBindingText( target, abbrev, button )
+  local key = self:GetBinding(target,button)
+  local txt = key and GetBindingText(key, "KEY_", abbrev and 1) or ""
+
+  if txt and abbrev then
+    -- further abbreviate some key names
+    txt = string.gsub(txt, "[^%-]+$", keybindAbbreviations)
+    -- the above does not handle "num pad -"
+    txt = string.gsub(txt, KEY_NUMPADMINUS, keybindAbbreviations)
+  end
+  return txt
+end
+
+
+--[[
   Publishes permanent binding notification events.
 ]]
 local function PublishBindings(self)
@@ -308,7 +379,7 @@
 --[[
   Shows all the registered click binding frames.
 ]]
-function ReBound.prototype:ShowFrames()
+function ReBound.prototype:ShowRegisteredFrames()
   if InCombatLockdown() then
     -- can't set bindings while in combat, so don't bother showing them
     UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT)
@@ -323,7 +394,7 @@
 --[[
   Hides all the registered click binding frames.
 ]]
-function ReBound.prototype:HideFrames()
+function ReBound.prototype:HideRegisteredFrames()
   -- because these frames aren't protected, there's no restriction 
   -- on hiding them while in combat.
   for _, f in pairs(self.frames) do
@@ -345,8 +416,11 @@
     GameTooltip:AddDoubleLine(L["Right-click"]..":", colorGreen.."("..binding2..")"..colorOff)
   end
   -- line 3: instructions
-  GameTooltip:AddLine(L["Click to select for binding"])
-  GameTooltip:AddLine(L["Shift-click to clear binding"])
+  GameTooltip:AddLine(colorGreen..L["Click"]..colorOff.." "..L["to select for binding"])
+  GameTooltip:AddLine(colorGreen..L["Shift-click"]..colorOff.." "..L["to clear binding"])
+  GameTooltip:AddLine("")
+  GameTooltip:AddLine(colorOrange..L["Right-click"]..colorOff.." "..L["to select for alternate (right-click) binding"])
+  GameTooltip:AddLine(colorOrange..L["Shift-right-click"]..colorOff.." "..L["to clear alternate (right-click) binding"])
   GameTooltip:Show()
 end
 
--- a/main.lua	Thu Mar 22 21:08:43 2007 +0000
+++ b/main.lua	Fri Mar 23 19:28:30 2007 +0000
@@ -9,7 +9,7 @@
 local L       = AceLibrary("AceLocale-2.2"):new("ReAction")
 local dewdrop = AceLibrary("Dewdrop-2.0")
 local tablet  = AceLibrary("Tablet-2.0")
-local ReBound = AceLibrary("ReBound-1.0"):new("REACTION")
+local ReBound = AceLibrary("ReBound-1.0"):new("ReAction")
 
 -- private functions
 local function tcopy(t)
@@ -24,15 +24,15 @@
 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_REACTION_TOGGLEKEYBIND    = L["ReAction Keybinding Mode"]
+BINDING_HEADER_REACTION             = L["ReAction"]
+BINDING_NAME_REACTION_TOGGLELOCK    = L["Toggle ReAction Bar Lock"]
+BINDING_NAME_REACTION_TOGGLEKEYBIND = L["ReAction Keybinding Mode"]
 
 -- UI panel strings
-REACTION_KEYBIND_TITLE        = L["ReAction Keybinding"]
-REACTION_KEYBIND_SUBTITLE     = L["Click Buttons to Set Keybindings"]
-REACTION_KEYBIND_DONE         = L["Save"]
-REACTION_KEYBIND_REVERT       = L["Revert"]
+REACTION_KEYBIND_TITLE    = L["ReAction Keybinding"]
+REACTION_KEYBIND_SUBTITLE = L["Click Buttons to Set Keybindings"]
+REACTION_KEYBIND_DONE     = L["Save"]
+REACTION_KEYBIND_REVERT   = L["Revert"]
 
 
 
@@ -51,38 +51,21 @@
   self:RegisterDB("ReActionDB","ReActionDBPC")
   self:RegisterDefaults("profile", ReAction_DefaultProfile)
   self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
-  self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
   self:DisableDefaultKeybindings()
 
   -- create update function for keybinding frame
-  ReActionKeybindDialog:SetScript("OnHide", function(frame)
-    main:SetKeybindMode(false)
-    if frame.save then
-      ReBound:SaveBindings()
-    else
-      ReBound:RevertBindings()
-    end
-    frame.save = false
-  end )
+  ReActionKeybindDialog:SetScript("OnHide", function(frame) main:HideKeybindDialog(frame) end)
 
   -- initial non-persistent state
   self.locked = true
+  self.keybindMode = false
   self.bars   = { }
 end
 
--- OnEnable is called at startup and when the profile is changed (via OnProfileEnable)
+-- OnEnable is called at PLAYER_LOGIN or when the addon is enabled.
 function main:OnEnable( )
-  if self.db.profile.firstRunDone ~= true then
-    self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
-  end
-  self:DestroyAllBars()
-  self:SetupBars()
-  self:UpgradeProfile()
-  self:SetupKeybindings()
-  if self.db.profile.firstRunDone ~= true then
-    self:Unlock()
-  end
-  self.db.profile.firstRunDone = true
+  self:HideDefaultBars()
+  self:SetupProfile( )
 end
 
 function main:OnDisable()
@@ -94,11 +77,38 @@
   self:UnregisterEvent("REBOUND_BIND")
   self:UnregisterEvent("REBOUND_UNBIND")
   ReBound:ClearRegisteredBindings()
-  self:OnEnable()
+  self:SetupProfile()
 end
 
-function main:UpgradeProfile()
-  if self.db.profile.firstRunDone ~= true and #self.db.profile.bindings == 0 then
+function main:SetupProfile( )
+  local profile = self.db.profile
+  if profile.firstRunDone ~= true then
+    profile.bars = tcopy(ReAction_DefaultBlizzardBars)
+  end
+  self:DestroyAllBars()
+  self:UpgradeProfile()
+  self:HideArt()
+  self:SetupBars()
+  self:SetupKeybindings()
+  if profile.firstRunDone ~= true then
+    self:Unlock()
+    profile.firstRunDone = true
+  end
+end
+
+-- Set a global variable for Bindings.xml (I use 'setglobal' for clarity, it's not strictly necessary)
+setglobal("ReActionAddOn", main)
+
+
+
+
+------------------------------------------------------------
+-- Profile conversion functions (from old profiles)
+--
+-- NOTE: these will be REMOVED when alpha testing is over.
+------------------------------------------------------------
+function main:UpgradeBindingConfig()
+  if #self.db.profile.bindings == 0 then
     for _, bar in pairs(self.bars) do
       for _, button in pairs(bar.buttons) do
         local key = ReBound:GetBinding(button:GetActionFrame(),"LeftButton")
@@ -110,6 +120,8 @@
   end
 end
 
+function main:UpgradeProfile()
+end
 
 
 
@@ -155,8 +167,7 @@
 -- Key binding functions
 ------------------------------
 function main:DisableDefaultKeybindings()
-  -- change the labels on all actionbar keybindings in the default
-  -- interface.
+  -- change the labels on all actionbar keybindings in the default interface.
   local label = "|cff999999("..L["Use ReAction"]..")|r"
   for i = 1, 12 do
     setglobal("BINDING_NAME_ACTIONBUTTON"..i,label)
@@ -169,7 +180,7 @@
   end
   for i = 1, 10 do
     setglobal("BINDING_NAME_BONUSACTIONBUTTON"..i,label)
-    setglobal("BINDING_NAME_SHAPESHIFTBUTTON"..i,label)
+--    setglobal("BINDING_NAME_SHAPESHIFTBUTTON"..i,label)
   end
   BINDING_HEADER_ACTIONBAR = "|cff999999"..L["Action Bar Functions Disabled"].."|r"
   BINDING_HEADER_MULTIACTIONBAR = "|cff999999"..L["Multi-Action Bar Functions Disabled"].."|r"
@@ -181,38 +192,58 @@
   if self.db.profile.firstRunDone ~= true then
     self:StealKeyBindings()
   else
+    self:UpgradeBindingConfig()
+    local needsSave = false
     for key, binding in pairs(self.db.profile.bindings) do
       local target = getglobal(binding.target) 
       if target then
-        ReBound:SetBinding(key, target, binding.button)
+        if ReBound:GetBinding(target,binding.button) ~= key then
+          ReBound:SetBinding(key,target,binding.button,true)
+          needsSave = true
+        end
       end
     end
+    if needsSave then
+      ReBound:SaveBindings()
+    end
   end
-  ReBound:SaveBindings()
   self:RegisterEvent("REBOUND_BIND")
   self:RegisterEvent("REBOUND_UNBIND")
 end
 
 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
-    local key = GetBindingKey("ACTIONBUTTON"..i)
+  local bar = self.bars[1]
+  if bar and bar ~= EMPTY_BAR_SLOT then
+    for i = 1, 12 do
+      local key = GetBindingKey("ACTIONBUTTON"..i)
+      if key and #key > 0 then
+        local button = bar.buttons[i]
+        if button then
+          ReBound:SetBinding(key, button:GetActionFrame(),nil,true)
+        end
+      end
+    end
+    local key = GetBindingKey("NEXTACTIONPAGE")
     if key and #key > 0 then
-      ReBound:ClearBinding(key,nil,nil,true) -- suppress notification printouts
-      ReBound:SetBinding(key, self.bars[1].buttons[i]:GetActionFrame(), "LeftButton")
+      ReBound:SetBinding(key, bar.upArrow,nil,true)
     end
+    key = GetBindingKey("PREVIOUSACTIONPAGE")
+    if key and #key > 0 then
+      ReBound:SetBinding(key, bar.downArrow,nil,true)
+    end
+    ReBound:SaveBindings()
   end
-  ReBound:SaveBindings()
 end
 
 function main:REBOUND_BIND(id, key, target, button)
-  if id == "REACTION" and key and target then
+  if id == "ReAction" and key and target then
     self.db.profile.bindings[key] = { target = target, button = button }
   end
 end
 
 function main:REBOUND_UNBIND(id, key)
-  if id == "REACTION" and key then
+  if id == "ReAction" and key then
     self.db.profile.bindings[key] = nil
   end
 end
@@ -226,30 +257,40 @@
 end
 
 function main:SetKeybindMode(enabled)
-  if not InCombatLockdown() then
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT)
+  else
     self.keybindMode = enabled
     for _, bar in pairs(self.bars) do
-      for __, button in pairs(bar.buttons) do
-        if button and button ~= EMPTY_BAR_SLOT then
-          button:TempShow(enabled)
+      if bar and bar ~= EMPTY_BAR_SLOT then
+        for __, button in pairs(bar.buttons) do
+          if button then
+            button:TempShow(enabled)
+          end
         end
       end
     end
     if enabled then
-      ReBound:ShowFrames()
+      ReBound:ShowRegisteredFrames()
       ReActionKeybindDialog:Show()
     else
-      ReBound:HideFrames()
+      ReBound:HideRegisteredFrames()
       if ReActionKeybindDialog:IsShown() then
         ReActionKeybindDialog:Hide()
       end
     end
-  else
-    UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT)
   end
 end
 
-
+function main:HideKeybindDialog( frame )
+  self:SetKeybindMode(false)
+  if frame.save then
+    ReBound:SaveBindings()
+  else
+    ReBound:RevertBindings()
+  end
+  frame.save = false
+end
 
 
 ----------------------------
@@ -299,7 +340,7 @@
 end
 
 function main:ToggleLocked()
-  main:SetLocked( not(self.locked) )
+  self:SetLocked( not(self.locked) )
 end
 
 
@@ -309,17 +350,21 @@
 --------------------------------------------------------
 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
+    -- the pet bar is a child of MainMenuBar, but can't be hidden because it will
+    -- break automatic pet bar show/hide. 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)
+
+    MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons.
   else
     SlidingActionBarTexture0:SetParent(PetActionBarFrame)
     SlidingActionBarTexture1:SetParent(PetActionBarFrame)
+    PetActionBarFrame:SetParent(MainMenuBar)
     MainMenuBar:Show()
   end
 end
@@ -412,9 +457,8 @@
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
   else
-    self:DestroyAllBars()
     self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
-    self:SetupBars()
+    self:OnProfileEnable() -- treat it like a profile switch
   end
 end
 
@@ -426,16 +470,13 @@
 end
 
 function main:SetupBars()
-  -- hide the default Blizzard art, if configued
-  self:HideArt()
-
   -- 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 config then
-      self:CreateBar(config, id)
+      self.bars[id] = self:CreateBar(config, id)
     end
   end
   
@@ -449,48 +490,37 @@
 end
 
 function main:CreateBar( config, id )
+  local buttonType = config.btnConfig and config.btnConfig.type and getglobal(config.btnConfig.type)
+  local subtype = buttonType and buttonType:GetButtonType(config.btnConfig.subtype)
+
+  if not subtype then
+    self:Print(L["Tried to create a button of unknown type"])
+    return
+  end
+
   local bar = ReBar:new(config, id)
-  local buttonType = ReAction:GetButtonType(config.btnConfig.subtype)
 
-  if buttonType then
-    self.bars[id] = bar
-    self.db.profile.bars[id] = config
+  -- initialize dewdrop menu
+  dewdrop:Register(bar:GetControlFrame(), 
+    'children', 
+    function()
+      dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
+      dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(bar,self))
+      dewdrop:FeedAceOptionsTable(subtype:GenerateOptionsTable(config.btnConfig, function() return bar:GetButtonList() end))
+    end,
+    'cursorX', true, 
+    'cursorY', true
+  )
 
-    -- 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
-    )
+  -- register page up/down buttons with ReBound for keybinding
+  ReBound:Register(bar.upArrow)
+  ReBound:Register(bar.downArrow)
 
-    bar:GetControlFrame():SetScript("OnClick", 
-      function(btn)
-        if btn == "RightButton" then
-          dewdrop:Open(cf)
-        end
-      end
-    )
+  if not self.locked then
+    bar:ShowControls()
+  end
 
-    -- register page up/down buttons with ReBound for keybinding
-    ReBound:Register(bar.upArrow)
-    ReBound:Register(bar.downArrow)
-
-    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
+  return bar
 end
 
 function main:DestroyBar( id )
@@ -516,21 +546,23 @@
 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
+    return
+  end
+
+  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
-      local bar = self:CreateBar(c, id)
-      bar:ApplyAnchor()
-      self:Unlock()
     end
+    self.bars[id] = self:CreateBar(c, id)
+    self.db.profile.bars[id] = c
+    self.bars[id]:ApplyAnchor()
+    self:Unlock()
   end
 end
 
@@ -550,24 +582,3 @@
 
 
 
-
------------------
--- General utility
------------------
-function main:ToggleIds()
-  if self.showIds then
-    ReAction:HideAllIds()
-  else
-    ReAction:ShowAllIds()
-  end
-  self.showIds = not self.showIds
-end
-
-function main:AreIdsVisible()
-  return self.showIds
-end
-
--- set a global variable for Bindings.xml
-ReActionAddOn = main
-
-