changeset 47:e12b736c23c3

Added Layout Editor
author Flick <flickerstreak@gmail.com>
date Fri, 11 Apr 2008 22:21:28 +0000
parents aa0b7fd68462
children 7b7d178dec52
files ReAction.lua locale/enUS.lua modules/ReAction_ConfigUI/ReAction_ConfigUI.lua
diffstat 3 files changed, 418 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/ReAction.lua	Thu Apr 10 23:27:58 2008 +0000
+++ b/ReAction.lua	Fri Apr 11 22:21:28 2008 +0000
@@ -116,15 +116,12 @@
   SlashHandler = function(option)
     if option == "config" then
       ReAction:ShowConfig()
-    elseif option == "unlock" then
-      ReAction:SetConfigMode(true)
-    elseif option == "lock" then
-      ReAction:SetConfigMode(false)
+    elseif option == "layout" then
+      ReAction:ShowLayout()
     else
       ReAction:Print(("%3.1f.%d"):format(ReAction.version,ReAction.revision))
       ReAction:Print("/reaction config")
-      ReAction:Print("/reaction unlock")
-      ReAction:Print("/reaction lock")
+      ReAction:Print("/reaction layout")
     end
   end
 end
@@ -289,15 +286,16 @@
   local bar, name = SelectBar(x)
   if bar and name and newname then
     if self.bars[newname] then
-      error(L["ReAction: name already in use"])
+      UIErrorsFrame:AddMessage(("%s ('%s')"):format(L["ReAction: name already in use"],newname))
+    else
+      self.bars[newname] = self.bars[name]
+      self.bars[name] = nil
+      bar:SetName(newname or "")
+      local cfg = self.db.profile.bars
+      cfg[newname], cfg[name] = cfg[name], nil
+      self:CallMethodOnAllModules("RenameBarConfig", name, newname)
+      self.callbacks:Fire("OnRenameBar", name, newname)
     end
-    self.bars[newname] = self.bars[name]
-    self.bars[name] = nil
-    bar:SetName(newname or "")
-    local cfg = self.db.profile.bars
-    cfg[newname], cfg[name] = cfg[name], nil
-    self:CallMethodOnAllModules("RenameBarConfig", name, newname)
-    self.callbacks:Fire("OnRenameBar", name, newname)
   end
 end
 
@@ -344,3 +342,6 @@
   self:CallModuleMethod("ConfigUI","OpenConfig")
 end
 
+function ReAction:ShowLayout()
+  self:CallModuleMethod("ConfigUI","LaunchLayoutEditor")
+end
--- a/locale/enUS.lua	Thu Apr 10 23:27:58 2008 +0000
+++ b/locale/enUS.lua	Fri Apr 11 22:21:28 2008 +0000
@@ -1,51 +1,78 @@
 local L = LibStub("AceLocale-3.0"):NewLocale("ReAction","enUS",true)
 if not L then return end
 
+for _, string in pairs({
 -- bindings.lua
-L["ReAction"] = true
-L["Toggle ReAction Bar Lock"] = true
-L["ReAction Keybinding Mode"] = true
+"ReAction",
+"Toggle ReAction Bar Lock",
+"ReAction Keybinding Mode",
 
 -- ReAction.lua
-L["Bar "] = true
-L["ReAction: name already in use"] = true
-L["ReAction config mode disabled during combat."] = true
+"Bar ",
+"ReAction: name already in use",
+"ReAction config mode disabled during combat.",
 
 -- Bar.lua
-L["Drag to add/remove buttons"] = true
-L["Drag to resize buttons"] = true
-L["Right-click-drag"] = true
-L["to change spacing"] = true
-L["Size:"] = true
-L["Spacing:"] = true
-L["Drag to move"] = true
-L["Shift-drag for sticky mode"] = true
-L["Right-click for options"] = true
-L["Configure..."] = true
-L["Open the configuration dialogue for this bar"] = true
-L["Delete Bar"] = true
-L["Remove the bar from the current profile"] = true
+"Drag to add/remove buttons",
+"Drag to resize buttons",
+"Right-click-drag",
+"to change spacing",
+"Size:",
+"Spacing:",
+"Drag to move",
+"Shift-drag for sticky mode",
+"Right-click for options",
+"Configure...",
+"Open the configuration dialogue for this bar",
+"Delete Bar",
+"Remove the bar from the current profile",
 
 -- modules/ReAction_HideBlizzard
-L["Hide Blizzard Action Bars"] = true
-L["Hide the default main bar and extra action bars"] = true
+"Hide Blizzard Action Bars",
+"Hide the default main bar and extra action bars",
 
 -- modules/ReAction_Action
-L["New Action Bar"] = true
-L["Create a new bar of standard action buttons"] = true
+"New Action Bar",
+"Create a new bar of standard action buttons",
 
 -- modules/ReAction_ConfigUI
-L["Customizable replacement for Blizzard's Action Bars"] = true
-L["Global Settings"] = true
-L["Global configuration settings"] = true
-L["Unlock Bars"] = true
-L["Unlock bars for dragging and resizing with the mouse"] = true
-L["Module Settings"] = true
-L["Configuration settings for each module"] = true
-L["Bar Config"] = true
-L["Configuration settings for bars"] = true
---L["Rename Bar"] = true
---L["Set a name for the bar"] = true
+"Customizable replacement for Blizzard's Action Bars",
+"Global Settings",
+"Global configuration settings",
+"Unlock Bars",
+"Unlock bars for dragging and resizing with the mouse",
+"Module Settings",
+"Configuration settings for each module",
+"Layout Editor...",
+"Show the ReAction Layout Editor to edit your bars",
+"Close on Launch",
+"Close the Interface Options window when launching the ReAction Layout Editor",
+"Layout",
+"Global Config",
+"Opens ReAction global configuration settings panel",
+"Close the Layout Editor when opening the ReAction global Interface Options",
+"New Bar...",
+"Choose a name, type, and initial grid for your new action bar:",
+"Bar Name",
+"Enter a name for your new action bar",
+"Button Type",
+"Create Bar",
+"General",
+"Rename Bar",
+"Delete Bar",
+"Button Grid",
+"Rows",
+"Columns",
+"Size",
+"Spacing",
+"Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality.",
+
+
+--"Rename Bar",
+--"Set a name for the bar",
 
 -- modules/ReAction_State
-L["Dynamic Behavior"] = true
+"Dynamic Behavior",
+}) do
+  L[string] = true
+end
--- a/modules/ReAction_ConfigUI/ReAction_ConfigUI.lua	Thu Apr 10 23:27:58 2008 +0000
+++ b/modules/ReAction_ConfigUI/ReAction_ConfigUI.lua	Fri Apr 11 22:21:28 2008 +0000
@@ -7,16 +7,33 @@
 -- local imports
 local ReAction = ReAction
 local L = ReAction.L
+local AceConfigReg = LibStub("AceConfigRegistry-3.0")
+local AceConfigDialog = LibStub("AceConfigDialog-3.0")
 
 -- module declaration
 local moduleID = "ConfigUI"
-local module = ReAction:NewModule( moduleID )
+local module = ReAction:NewModule( moduleID,
+  "AceEvent-3.0"
+)
 
 -- module methods
 function module:OnInitialize()
+  self.db = ReAction.db:RegisterNamespace( moduleID,
+    { 
+      profile = {
+        closeOnLaunch = true,
+        editorCloseOnLaunch = true,
+      }
+    }
+  )
+
   ReAction.RegisterCallback(self,"OnOptionsRegistered")
   ReAction.RegisterCallback(self,"OnOptionsRefreshed")
+  ReAction.RegisterCallback(self,"OnCreateBar")
+  ReAction.RegisterCallback(self,"OnEraseBar")
+  ReAction.RegisterCallback(self,"OnRenameBar")
   self:InitializeOptions()
+  self:RegisterEvent("PLAYER_REGEN_DISABLED")
 end
 
 function module:OnOptionsRegistered(evt, context, module, opts)
@@ -25,6 +42,8 @@
     for k, v in pairs(opts) do
       c.args[k] = v
     end
+  elseif c == "bar" then
+    
   end
 end
 
@@ -32,32 +51,192 @@
   -- TODO: refresh options frame (just OpenConfig again?)
 end
 
-function module:OpenConfig(bar)
-  InterfaceOptionsFrame_OpenToFrame("ReAction")
-  if bar then
-    -- TODO: select the correct bar pane
+function module:OnCreateBar(evt, 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
+  local i = 1
+  repeat
+    key = ("bar%s"):format(i)
+    i = i+1
+  until self.layoutOpts.args[key] == nil
+  self.barOptMap[name] = key
+  self.layoutOpts.args[key] = {
+    type = "group",
+    name = name,
+    childGroups = "tab",
+    args = {
+      general = {
+        type = "group",
+        name = L["General"],
+        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 = -1
+          },
+
+        }
+      },
+    },
+
+  }
+end
+
+function module:OnEraseBar(evt, name)
+  local key = self.barOptMap[name]
+  self.barOptMap[name] = nil
+  if key then
+    self.layoutOpts.args[key] = nil
+    self:RefreshLayoutEditor()
   end
 end
 
+function module:OnRenameBar(evt, oldname, newname)
+  local key = self.barOptMap[oldname]
+  self.barOptMap[oldname], self.barOptMap[newname] = nil, key
+  if key then
+    self.layoutOpts.args[key].name = newname
+    self:RefreshLayoutEditor()
+  end
+end
+
+function module:PLAYER_REGEN_DISABLED()
+  if self.editor then
+    self.editor:Hide()
+  end
+end
+
+function module:UserError(msg)
+  -- any user errors should be flashed to the UIErrorsFrame
+  UIErrorsFrame:AddMessage(msg)
+end
+
+function module:OpenConfig()
+  InterfaceOptionsFrame_OpenToFrame("ReAction")
+end
+
+function module:LaunchLayoutEditor(bar)
+  if InCombatLockdown() then
+    self:UserError(L["ReAction config mode disabled during combat."])
+  else
+    if not self.editor then
+      -- use a local container to work around AceConfigDialog closing
+      -- both the layout editor and the global options when interface options is closed
+      local ed = LibStub("AceGUI-3.0"):Create("Frame")
+      ed.frame:SetClampedToScreen(true)
+      local old_OnUpdate = ed.frame:GetScript("OnUpdate")
+      ed.frame:SetScript("OnUpdate", function(dt)
+          if old_OnUpdate then
+            old_OnUpdate(dt)
+          end
+          if ed.closePending then
+            InterfaceOptionsFrame:Hide()
+            ed.closePending = false
+          end
+          if ed.selfClosePending then
+            ed:Hide()
+            AceConfigReg:NotifyChange("ReAction")
+            ed.selfClosePending = false
+          end
+        end )
+      ed:SetCallback("OnClose", 
+        function() 
+          ReAction:SetConfigMode(false)
+        end )
+      self.editor = ed
+      AceConfigDialog:SetDefaultSize("ReAction-Layout", 600, 450)
+    end
+
+    AceConfigDialog:Open("ReAction-Layout", self.editor)
+    ReAction:SetConfigMode(true)
+  end
+end
+
+function module:RefreshLayoutEditor()
+  AceConfigReg:NotifyChange("ReAction-Layout")
+  if self.editor and self.editor.frame:IsShown() then
+    AceConfigDialog:Open("ReAction-Layout", self.editor)
+  end
+end
+
+function module:GetBarTypes()
+  local opts = self.optBarTypes or { }
+  self.optBarTypes = opts
+
+  -- TODO: get these from module registration somehow
+  opts[1] = "foo"
+  
+  return opts
+end
+
+function module:CreateBar()
+  local name = self.tmpBarName
+  local type = self.tmpBarType
+
+  self.tmpBarName = nil
+  self.tmpBarType = nil
+
+  -- TODO: get from module registration
+  -- TODO: use rows/cols info
+  ReAction:CreateBar(name)
+end
+
 function module:InitializeOptions()
-  self.configOptions = {
+  -- general config options
+  local opts = {
     type = "group",
+    name = "ReAction",
     childGroups = "tab",
     args = {
+      _desc = {
+        type = "description",
+        name = L["Customizable replacement for Blizzard's Action Bars"],
+        order = 1,
+      },
+      _launchLayout = {
+        type = "execute",
+        handler = self,
+        name = L["Layout Editor..."],
+        desc = L["Show the ReAction Layout Editor to edit your bars"],
+        func = function()
+            self:LaunchLayoutEditor()
+            -- you can't close a dialog in response to an options click, because the end of the 
+            -- handler for all the button events calls lib:Open()
+            -- So, schedule a close on the next OnUpdate
+            if self.db.profile.closeOnLaunch then
+              self.editor.closePending = true
+            end
+          end,
+        order = 2,
+      },
+      _closeThis = {
+        type = "toggle",
+        name = L["Close on Launch"],
+        desc = L["Close the Interface Options window when launching the ReAction Layout Editor"],
+        get  = function() return self.db.profile.closeOnLaunch end,
+        set  = function(info, val) self.db.profile.closeOnLaunch = val end,
+        order = 3,
+      },
       global = {
         type = "group",
         name = L["Global Settings"],
         desc = L["Global configuration settings"],
         args = { },
-        order = 1,
+        order = 3,
       },
-      bar = {
-        type = "group",
-        name = L["Bar Config"],
-        desc = L["Configuration settings for bars"],
-        args = { },
-        order = 2,
-      },
+      _profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db),
       module = {
         type = "group",
         childGroups = "select",
@@ -69,8 +248,18 @@
     },
     plugins = { }
   }
+  self.configOptions = opts
+  opts.args._profile.order = -2
+  AceConfigReg:RegisterOptionsTable("ReAction",opts)
+  self.frame = AceConfigDialog:AddToBlizOptions("ReAction", "ReAction")
+  self.frame.obj:SetCallback("default", 
+    function() 
+      ReAction.db:ResetProfile()
+      module:OpenConfig()
+    end )
 
-  for c, tbl in pairs(self.configOptions.args) do
+  -- import options from registered modules
+  for c, tbl in pairs(opts.args) do
     for _, m in pairs(ReAction:GetOptions(c)) do
       for k, v in pairs(m) do
         tbl.args[k] = v
@@ -78,13 +267,6 @@
     end
   end
 
-  self.configOptions.args.desc = {
-    type = "description",
-    name = L["Customizable replacement for Blizzard's Action Bars"],
-  }
-  self.configOptions.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db)
-  self.configOptions.args.profile.order = -2
-
   ReAction:RegisterOptions("module",self, {
     configUI = {
       type = "group",
@@ -103,8 +285,142 @@
     },
   })
 
-  LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("ReAction",self.configOptions)
-  self.frame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ReAction", "ReAction")
-  self.frame.obj:SetCallback("default", function() ReAction.db:ResetProfile() end)
+  -- layout editor options
+  local layoutOpts = {
+    type = "group",
+    name = ("ReAction - %s"):format(L["Layout"]),
+    handler = self,
+    childGroups = "tree",
+    args = {
+      desc = {
+        type = "description",
+        name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."],
+        order = 1
+      },
+      launchConfig = {
+        type = "execute",
+        name = L["Global Config"],
+        desc = L["Opens ReAction global configuration settings panel"],
+        func = function()
+            self:OpenConfig()
+            -- you can't close a dialog in response to an options click, because the end of the 
+            -- handler for all the button events calls lib:Open()
+            -- So, schedule a close on the next appropriate event
+            if self.db.profile.editorCloseOnLaunch then
+              self.editor.selfClosePending = true
+            end
+          end,
+        order = 2
+      },
+      closThis = {
+        type = "toggle",
+        name = L["Close on Launch"],
+        desc = L["Close the Layout Editor when opening the ReAction global Interface Options"],
+        get  = function() return self.db.profile.editorCloseOnLaunch end,
+        set  = function(info, val) self.db.profile.editorCloseOnLaunch = val end,
+        order = 3,
+      },
+      new = {
+        type = "group",
+        name = L["New Bar..."],
+        order = 4,
+        args = { 
+          desc = {
+            type = "description",
+            name = L["Choose a name, type, and initial grid for your new action bar:"],
+            order = 1,
+          },
+          name = {
+            type = "input",
+            name = L["Bar Name"],
+            desc = L["Enter a name for your new action bar"],
+            get  = function() return self.tmpBarName or "" end,
+            set  = function(info, val) self.tmpBarName = val end,
+            order = 2,
+          },
+          type = {
+            type = "select",
+            name = L["Button Type"],
+            get  = function() return self.tmpBarType or "" end,
+            set  = function(info, val) self.tmpBarType = val end,
+            values = "GetBarTypes",
+            order = 3,
+          },
+          grid = {
+            type = "group",
+            name = L["Button Grid"],
+            inline = true,
+            args = {
+              hdr = {
+                type = "header",
+                name = L["Button Grid"],
+                order = 1,
+              },
+              rows = {
+                type = "range",
+                name = L["Rows"],
+                get  = function() return self.tmpBarRows or 1 end,
+                set  = function(info, val) self.tmpBarRows = val end,
+                width = "half",
+                min = 1,
+                max = 32,
+                step = 1,
+                order = 2,
+              },
+              cols = {
+                type = "range",
+                name = L["Columns"],
+                get  = function() return self.tmpBarCols or 12 end,
+                set  = function(info, val) self.tmpBarCols = val end,
+                width = "half",
+                min = 1, 
+                max = 32,
+                step = 1,
+                order = 3,
+              },
+              sz = {
+                type = "range",
+                name = L["Size"],
+                get  = function() return self.tmpBarSize or 36 end,
+                set  = function(info, val) self.tmpBarSize = val end,
+                width = "half",
+                min = 10,
+                max = 72,
+                step = 1,
+                order = 4,
+              },
+              spacing = {
+                type = "range",
+                name = L["Spacing"],
+                get  = function() return self.tmpBarSpacing or 3 end,
+                set  = function(info, val) self.tmpBarSpacing = val end,
+                width = "half",
+                min = 0,
+                max = 24,
+                step = 1,
+                order = 5,
+              }
+            },
+            order = 4
+          },
+          spacer = {
+            type = "header",
+            name = "",
+            width = "full",
+            order = -2
+          },
+          go = {
+            type = "execute",
+            name = L["Create Bar"],
+            func = "CreateBar",
+            order = -1,
+          }
+        }
+      }
+    }
+  }
+  self.layoutOpts = layoutOpts
+  self.barOptMap = { }
+  AceConfigReg:RegisterOptionsTable("ReAction-Layout",layoutOpts)
 end