changeset 10:f3a7bfebc283

Version 0.33
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:37:38 +0000
parents 650f75d08952
children 88df7235ad8b
files Bindings.xml Buttons.lua Defaults.lua KeybindDialog.xml Options.lua README.html ReAction.toc classes/ReAction.lua classes/ReAction_ActionDisplay.lua classes/ReAction_PetActionDisplay.lua classes/ReBar.lua libs/ReBound-1.0/ReBound-1.0.lua locale-enUS.lua main.lua
diffstat 14 files changed, 872 insertions(+), 194 deletions(-) [+]
line wrap: on
line diff
--- a/Bindings.xml	Tue Mar 20 21:35:57 2007 +0000
+++ b/Bindings.xml	Tue Mar 20 21:37:38 2007 +0000
@@ -2,7 +2,7 @@
   <Binding name="REACTION_TOGGLELOCK" header="REACTION">
     ReActionAddOn:ToggleLocked()
   </Binding>
-  <Binding name="REBOUND_TOGGLEBINDINGMODE">
-    ReBound:ToggleEnabled()
+  <Binding name="REACTION_TOGGLEKEYBIND">
+    ReActionAddOn:ToggleKeybindMode()
   </Binding>
 </Bindings>
--- a/Buttons.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/Buttons.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -4,6 +4,7 @@
 --
 
 local AceOO = AceLibrary("AceOO-2.0")
+local ReBound = AceLibrary("ReBound-1.0")
 
 local Action = AceOO.Class(
   ReAction, 
@@ -20,7 +21,7 @@
 )
 
 
-ReAction:AddButtonType( "Action",    Action,    120 )
+ReAction:AddButtonType( "Action",     Action,    120 )
 ReAction:AddButtonType( "Pet Action", PetAction, 10  )
 
 
@@ -34,8 +35,10 @@
   ids = { },
   selfcast = nil,
   keyBindLoc = "TOPRIGHT",
+  keyBindRightLoc = "RIGHT",
   stackCountLoc = "BOTTOMRIGHT",
   showKeyBind = true,
+  showKeyBindRight = false,
   showStackCount = true,
   showMacroText = true,
   showBorder = true,
@@ -123,6 +126,7 @@
           end
         end,
         validate = { "default", "none", "alt", "ctrl", "shift", "right-click" },
+        order = 101
       },
 
       opacity = {
@@ -206,6 +210,23 @@
           },
 
         },
+        order = 102,
+      },
+
+      displaysep = {
+        type = "header",
+        name = "   ",
+        desc = "   ",
+        order = 103,
+      },
+
+      showkeybind = {
+        type = "toggle",
+        name = "Show Hotkey",
+        desc = "Toggle show/hide hot key labels",
+        get  = function() return config.showKeyBind end,
+        set  = function() config.showKeyBind = not config.showKeyBind ; refresh() end,
+        order = 104,
       },
 
       keyloc = {
@@ -214,24 +235,39 @@
         desc = "Sets hotkey location",
         get  = function() return config.keyBindLoc end,
         set  = function(loc) config.keyBindLoc = loc ; refresh() end,
+        hidden = function() return not config.showKeyBind end,
         validate = labelPlacementOptions,
+        order = 105,
       },
       
-      stackloc = {
-        type = "text",
-        name = "Stack Count Location",
-        desc = "Sets stack count location",
-        get  = function() return config.stackCountLoc end,
-        set  = function(loc) config.stackCountLoc = loc ; refresh() end,
-        validate = labelPlacementOptions,
+      showKeyBindRight = {
+        type = "toggle",
+        name = "Show Right-click Hotkey",
+        desc = "Toggle show/hide right-click hot key labels",
+        get  = function() return config.showKeyBindRight end,
+        set  = function() config.showKeyBindRight = not config.showKeyBindRight ; refresh() end,
+        order = 106,
       },
 
-      showkeybind = {
+      rightkeyloc = {
+        type = "text",
+        name = "Right-click Hotkey Location",
+        desc = "Sets right-click hotkey location",
+        get  = function() return config.keyBindRightLoc end,
+        set  = function(loc) config.keyBindRightLoc = loc ; refresh() end,
+        hidden = function() return not config.showKeyBindRight end,
+        validate = labelPlacementOptions,
+        order = 107,
+      },
+      
+      colorhotkeys = {
         type = "toggle",
-        name = "Show Hotkey",
-        desc = "Toggle show/hide hot key labels",
-        get  = function() return config.showKeyBind end,
-        set  = function() config.showKeyBind = not config.showKeyBind ; refresh() end,
+        name = "Colorize Hotkeys",
+        desc = "Toggles coloring hotkeys based on the modifier key. Out-of-range coloring is always enabled.",
+        get  = function() return config.keyBindColorCode end,
+        set  = function() config.keyBindColorCode = not config.keyBindColorCode ; refresh() end,
+        hidden = function() return not config.showKeyBind and not config.showKeyBindRight end,
+        order = 109,
       },
 
       showstackcount = {
@@ -240,6 +276,18 @@
         desc = "Toggle show/hide stack count labels",
         get  = function() return config.showStackCount end,
         set  = function() config.showStackCount = not config.showStackCount ; refresh() end,
+        order = 110,
+      },
+
+      stackloc = {
+        type = "text",
+        name = "Stack Count Location",
+        desc = "Sets stack count location",
+        get  = function() return config.stackCountLoc end,
+        set  = function(loc) config.stackCountLoc = loc ; refresh() end,
+        hidden = function() return not config.showStackCount end,
+        validate = labelPlacementOptions,
+        order = 111,
       },
 
       showmacrotext = {
@@ -248,6 +296,7 @@
         desc = "Toggle show/hide macro name labels",
         get  = function() return config.showMacroText end,
         set  = function() config.showMacroText = not config.showMacroText ; refresh() end,
+        order = 112,
       },
 
       hidecooldown = {
@@ -256,6 +305,7 @@
         desc = "Hides all cooldown displays on buttons. Toggling this on does not hide currently running cooldowns.",
         get  = function() return config.hideCooldown end,
         set  = function() config.hideCooldown = not config.hideCooldown ; refresh() end,
+        order = 114,
       },
 
       hideglobalcooldown = {
@@ -264,14 +314,8 @@
         desc = "Disables the global cooldown from being displayed on buttons.",
         get  = function() return config.hideGlobalCooldown end,
         set  = function() config.hideGlobalCooldown = not config.hideGlobalCooldown ; refresh() end,
-      },
-
-      colorhotkeys = {
-        type = "toggle",
-        name = "Colorize Hotkeys",
-        desc = "Toggles coloring hotkeys based on the modifier key. Out-of-range coloring is always enabled.",
-        get  = function() return config.keyBindColorCode end,
-        set  = function() config.keyBindColorCode = not config.keyBindColorCode ; refresh() end,
+        hidden = function() return not config.hideCooldown end,
+        order = 115,
       },
 
       --[[
@@ -355,11 +399,7 @@
   
   self:SetupDisplay("ReActionButton"..id)
   self:SetupAction()
-
-  -- register button with ReBound for keybinding
-  if ReBound then
-    ReBound:AddKeybindTarget(self:GetActionFrame())
-  end
+  ReBound:Register(self:GetActionFrame())
 end
 
 function PetAction.prototype:init( id )
@@ -367,10 +407,6 @@
   
   self:SetupDisplay("ReActionPetButton"..id)
   self:SetupAction()
-
-  -- register button with ReBound for keybinding
-  if ReBound then
-    ReBound:AddKeybindTarget(self:GetActionFrame())
-  end
+  ReBound:Register(self:GetActionFrame())
 end
 
--- a/Defaults.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/Defaults.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -14,8 +14,8 @@
 -- default saved variables
 ReAction_DefaultProfile = {
   hideArt = false,
-
-  bars = { }
+  bars = { },
+  bindings = { }
 }
 
 ReAction_DefaultBarConfig = {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/KeybindDialog.xml	Tue Mar 20 21:37:38 2007 +0000
@@ -0,0 +1,117 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
+
+
+  <Frame name="ReActionKeybindDialog" frameStrata="DIALOG" movable="true" hidden="true" enableMouse="true">
+    <Size>
+      <AbsDimension x="270" y="95"/>
+    </Size>
+    <Anchors>
+      <Anchor point="CENTER"/>
+    </Anchors>
+    <TitleRegion>
+      <Size>
+        <AbsDimension x="200" y="30"/>
+      </Size>
+      <Anchors>
+        <Anchor point="TOP">
+          <Offset>
+            <AbsDimension x="0" y="-10"/>
+          </Offset>
+        </Anchor>
+      </Anchors>
+    </TitleRegion>
+    <Backdrop  bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
+			<BackgroundInsets>
+				<AbsInset left="4" right="4" top="4" bottom="4"/>
+			</BackgroundInsets>
+      <TileSize>
+        <AbsValue val="16"/>
+      </TileSize>
+      <EdgeSize>
+        <AbsValue val="16"/>
+      </EdgeSize>
+    </Backdrop>
+    <Layers>
+      <Layer level="ARTWORK">
+        <FontString inherits="GameFontNormalLarge" text="REACTION_KEYBIND_TITLE" justifyH="CENTER">
+          <Size>
+            <AbsDimension x="200" y="30"/>
+          </Size>
+          <Anchors>
+            <Anchor point="TOP">
+              <Offset>
+                <AbsDimension x="0" y="-10"/>
+              </Offset>
+            </Anchor>
+          </Anchors>
+        </FontString>
+        <FontString inherits="GameFontNormalSmall" text="REACTION_KEYBIND_SUBTITLE" justifyH="CENTER">
+          <Size>
+            <AbsDimension x="240" y="70"/>
+          </Size>
+          <Anchors>
+            <Anchor point="TOP">
+              <Offset>
+                <AbsDimension x="0" y="-10"/>
+              </Offset>
+            </Anchor>
+          </Anchors>
+        </FontString>
+      </Layer>
+    </Layers>
+    <Frames>
+      <Button inherits="GameMenuButtonTemplate" text="REACTION_KEYBIND_DONE">
+        <Size>
+          <AbsDimension x="112" y="28"/>
+        </Size>
+        <Anchors>
+          <Anchor point="BOTTOMLEFT" relativePoint="BOTTOM">
+            <Offset>
+              <AbsDimension x="10" y="10"/>
+            </Offset>
+          </Anchor>
+        </Anchors>
+        <Scripts>
+          <OnClick>
+            this:GetParent().save = true
+            this:GetParent():Hide()
+          </OnClick>
+        </Scripts>
+      </Button>
+      <Button inherits="GameMenuButtonTemplate" text="REACTION_KEYBIND_REVERT">
+        <Size>
+          <AbsDimension x="112" y="28"/>
+        </Size>
+        <Anchors>
+          <Anchor point="BOTTOMRIGHT" relativePoint="BOTTOM">
+            <Offset>
+              <AbsDimension x="-10" y="10"/>
+            </Offset>
+          </Anchor>
+        </Anchors>
+        <Scripts>
+          <OnClick>
+            this:GetParent():Hide()
+          </OnClick>
+        </Scripts>
+      </Button>
+    </Frames>
+    <Scripts>
+      <OnLoad>
+        table.insert(UISpecialFrames, this:GetName())
+      </OnLoad>
+      <OnHide>
+        ReActionAddOn:SetKeybindMode(false)
+        if this.save then
+          this.save = false
+          SaveBindings(GetCurrentBindingSet())
+        else
+          LoadBindings(GetCurrentBindingSet())
+        end
+      </OnHide>
+    </Scripts>
+  </Frame>
+
+</Ui>
--- a/Options.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/Options.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -32,11 +32,12 @@
       func = "Unlock",
     },
 
-    bindings = {
-      type = "execute",
-      name = "bindings",
-      desc = "Launches keybinding setup mode",
-      func = function() ReBound:Enable() end,
+    keybind = {
+      type = "toggle",
+      name = "keybind",
+      desc = "keybind setup mode",
+      get  = "GetKeybindMode",
+      set  = "SetKeybindMode",
     },
 
     hideart = {
@@ -71,16 +72,6 @@
       desc = "Resets to single bar in the default position",
       func = "ResetBars",
     },
-    
-    --[[
-    resync = {
-      type = "execute",
-      name = "resync",
-      desc = "Re-orders action IDs sequentially amongst bars",
-      func = "ResyncActionIDs",
-      disabled = true -- not yet implemented
-    },
-    ]]
   }
 }
 
@@ -117,11 +108,12 @@
       order = 3,
     },
 
-    bindings = {
-      type = "execute",
+    keybind = {
+      type = "toggle",
       name = "Set Key Bindings",
-      desc = "Launches keybinding setup mode",
-      func = function() ReBound:Enable() end,
+      desc = "keybind setup mode",
+      get  = "GetKeybindMode",
+      set  = "SetKeybindMode",
       order = 4,
     },
 
@@ -134,16 +126,6 @@
       order = 6,
     },
     
-    --[[
-    resync = {
-      type = "execute",
-      name = "Re-sync Action IDs",
-      desc = "Re-orders action IDs sequentially amongst bars",
-      func = "ResyncActionIDs",
-      disabled = true, -- not yet implemented
-    },
-    ]]
-
   }
 }
 
--- a/README.html	Tue Mar 20 21:35:57 2007 +0000
+++ b/README.html	Tue Mar 20 21:37:38 2007 +0000
@@ -2,14 +2,21 @@
 <head>
 <title>ReAction: README</title>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<style type="text/css">
+<!--
+body {  background-color: #FFFFCC; list-style-type: none}
+p {  margin-top: 0px; margin-bottom: 18px}
+ul {  line-height: 110%}
+-->
+</style>
 </head>
 
 <body bgcolor="#FFFFFF" text="#000000">
 <h1 align="center">ReAction</h1>
 <h3 align="center">AddOn for World of Warcraft</h3>
-<p><font size="2">Current Version: 0.32 (alpha)<br>
-  Released: 03 Feb 2007</font><font size="2"><br>
-  WoW Version Compatibility/TOC: 2.0.6 / TOC 20003</font></p>
+<p><font size="2">Current Version: 0.33 (alpha)<br>
+  Released: 02 Mar 2007</font><font size="2"><br>
+  WoW Version Compatibility/TOC: 2.0.8 / TOC 20003</font></p>
 <h2>The Basics</h2>
 <p>ReAction is a replacement for the default Blizzard action bars. It allows you 
   redefine your action button layout any way you like.</p>
@@ -23,7 +30,8 @@
     Automatically anchor bars to each other or the screen edges by holding shift 
     down as you drag.</li>
   <li>Context menus provide independent configuration options for each bar.</li>
-  <li>Point and click keybinding interface.</li>
+  <li>Point and click keybinding interface. You can bind keys to left-click or 
+    right-click independently.</li>
   <li>Supports multiple 'pages' per bar, configured independently. Automatic stance, 
     form, and stealth switching among pages is supported, including Shadowform.</li>
   <li>Pet action bar is fully supported and configurable.</li>
@@ -80,18 +88,30 @@
   mode by alt-clicking the ReAction Control Button (or choosing 'keybinding mode' 
   from the right-click menu). <b>ReAction button keybindings are not available 
   from the standard keybindings menu!</b> You <i>must</i> use the ReAction keybinding 
-  interface.</p>
+  interface. They're even greyed out in the keybinding menu to remind you.</p>
 <p>Like configuration mode, normal button operation is disabled while in keybinding 
   mode (though again, any hotkeys you have assigned will work).</p>
 <p>With the keybinding interface out, you can mouseover any ReAction button to 
   see what its current keybinding is. You can set the keybinding on a button by 
-  pressing the key, then clicking the button. To clear a keybinding from a ReAction 
-  button, right-click the button. If you've set up bars with multiple pages, you 
+  clicking the button, then pressing the key. To clear a keybinding from a ReAction 
+  button, shift-click the button. Tooltips will remind you of this interface. 
+  You can also right-click/shift-right-click to set/clear a right-click hotkey, 
+  which will simulate right-clicking the button (useful for complex macros, typically 
+  to save screen real estate). If you've set up bars with multiple pages, you 
   can also bind a key to the page up/down buttons on a per-bar basis. Just make 
   sure the buttons are showing (they can be hidden later) and assign the keybinding 
   like any other ReAction button.</p>
 <p>Keybindings are saved on a per-character basis. Keybinding mode is not available 
-  if you are in combat, and is automatically cancelled if you enter combat.</p>
+  if you are in combat, and is automatically cancelled if you enter combat. When 
+  you first log in with ReAction, it steals the keybindings from the default main 
+  action bar (buttons 1-12) and assigns them to the corresponding buttons on the 
+  default ReAction bar.</p>
+<p><b>Remember to click the 'Save' button to save your keybindings! </b>If you 
+  do not, they will automatically revert to the previous bindings when exiting 
+  keybinding mode. This can be useful for &quot;trying out&quot; certain layouts 
+  briefly, but can also be a serious gotcha &#151; if you just hit 'Escape,' or 
+  alt-click the ReAction Control Button, or enter combat while in keybinding mode, 
+  your bindings will revert to their previous state.</p>
 <h3>Playing with ReAction</h3>
 <p>Once you get your keybindings and configuration set up, you're ready to go. 
   The buttons behave just like regular Blizzard buttons. However, at any time 
@@ -114,8 +134,9 @@
     during combat. This workaround can be disabled via a configuration option, 
     but then you can't drag and drop actions onto slots during combat. Pick your 
     poison, it's a limitation of Blizzard's protection scheme.</li>
-  <li>If you hide the default main menu bar, there is no substitute for the XP 
-    bar, bag bar, or micro menu bar (although the hotkeys for them still work)</li>
+  <li>If you hide the default main menu bar, there is no substitute provided for 
+    the XP bar, bag bar, or micro menu bar (although the hotkeys for them still 
+    work). Other addons can provide these features until ReAction supports them.</li>
 </ul>
 <h2>Known Issues</h2>
 <ul>
@@ -127,16 +148,12 @@
     you will probably need to move your actions around.</li>
   <li>Action IDs may not always be laid out in sequence, meaning that similar 
     layouts on different machines may put the actions in a different order.</li>
-  <li>Keybindings are only saved per character, which causes problems when switching 
-    profiles.</li>
   <li>There seems to be a big performance hit when first dragging a bar after 
-    entering configuration mode, and when first enabling keybinding mode.</li>
+    entering configuration mode, and when first enabling keybinding mode. More 
+    investigation is necessary.</li>
 </ul>
 <h2>Future Plans</h2>
 <ul>
-  <li>Use override bindings for the keybindings, and automatically switch with 
-    profiles. Also &quot;steal&quot; bindings from the default UI on first run 
-    so that they're populated with something reasonable.</li>
   <li>Add support for bag bar, shapeshift bar, and micro menu bar. May also add 
     XP bar to default unit frames for those who don't want to use a unit frame 
     addon to get the XP bar back.</li>
@@ -156,6 +173,23 @@
   <li>Localization</li>
 </ul>
 <h2>Version History</h2>
+<p>Version 0.33:</p>
+<ul>
+  <li>Rewrote the keybinding interface (again). I think I finally like this version. 
+    Keybindings are now saved and loaded with the profile, and honor the &quot;character-specific 
+    keybindings&quot; setting in the Blizzard Keybinding pane. The default keybindings 
+    for action bars are now greyed out in Blizzard's interface to remind you to 
+    use ReAction to set bindings for action bars.</li>
+  <li>Moved the Action ID label on the buttons to the center of the button.</li>
+  <li>Added support for binding right-clicks to hotkeys on the main action buttons 
+    only (no pet buttons). There is also an option (off by default) to display 
+    and specify the location for right-click binding labels.</li>
+  <li>Tweaked the ordering of the bar menus. Some options will automatically show/hide 
+    when they are relevant.</li>
+  <li>Converted the core of the keybinding code to an Ace2-style library: ReBound-1.0</li>
+  <li>Did a little bit of code cleanup in main.lua</li>
+  <li>Converted to MIT license</li>
+</ul>
 <p>Version 0.32:</p>
 <ul>
   <li>Fixed a bug with displaying cooldowns generating slews of errors</li>
@@ -207,26 +241,28 @@
 <h2>Credits</h2>
 <p>Huge credit to the <a href="http://www.wowace.com">Ace 2</a> development team, 
   whose framework provides a level of functionality that I consider critical to 
-  the success of this addon.</p>
-<p>Similarly, enormous credit goes to <a href="http://ckknight.wowinterface.com">ckknight</a>, 
+  the success of this addon. Similarly, enormous credit goes to <a href="http://ckknight.wowinterface.com">ckknight</a>, 
   whose Dewdrop menuing system and FuBar plugin system are ridiculously easy to 
   use.</p>
 <p>Finally, thanks to my alpha testers and stalwart adventuring companions: Deor, 
   Nogrim, Sorabel, and Yngvi.</p>
-<h2>Copyright</h2>
-<p>ReAction &copy; 2007 by Ryan Findley.</p>
-<p>You are free to distribute this AddOn package without notice to the author, 
-  as long as the package is unmodified, this readme.html file accompanies the 
-  distribution, and no claim of authorship of the contents of the package is made. 
-  Derived works are expressly permitted but must be clearly labeled as not the 
-  work of the original author and packaged separately, with credit given to the 
-  original author. Inclusion of this package within a compilation is expressly 
-  permitted.</p>
-<p>The author expressly disclaims any warranty of any kind for the material contained 
-  in this package. USE AT YOUR OWN RISK.</p>
-<p>All files in this package under the 'libs/' directory are libraries made available 
-  by <a href="http://www.wowace.com">WoWAce</a>, and are not the work of this 
-  author.</p>
+<h2>Copyright &amp; License</h2>
+<p>ReAction is distributed under the MIT license.</p>
+<p>ReAction Copyright &copy; 2007 Ryan Findley.</p>
+<p>Permission is hereby granted, free of charge, to any person obtaining a copy 
+  of this software and associated documentation files (the &quot;Software&quot;), 
+  to deal in the Software without restriction, including without limitation the 
+  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
+  sell copies of the Software, and to permit persons to whom the Software is furnished 
+  to do so, subject to the following conditions:</p>
+<p>The above copyright notice and this permission notice shall be included in 
+  all copies or substantial portions of the Software.</p>
+<p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 
+  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
 <p>World of Warcraft is a registered trademark of Blizzard Entertainment, Inc.</p>
 </body>
 </html>
--- a/ReAction.toc	Tue Mar 20 21:35:57 2007 +0000
+++ b/ReAction.toc	Tue Mar 20 21:37:38 2007 +0000
@@ -4,7 +4,7 @@
 ## DefaultState: enabled
 ## LoadOnDemand: 0
 ## Author: Flick
-## Version: 0.32
+## Version: 0.33
 ## X-Description: An action bar and button layout tool
 ## X-Category: Action Bars
 ## SavedVariables: ReActionDB
@@ -22,13 +22,12 @@
 libs\Dewdrop-2.0\Dewdrop-2.0.lua
 libs\Tablet-2.0\Tablet-2.0.lua
 libs\FuBarPlugin-2.0\FuBarPlugin-2.0.lua
+libs\ReBound-1.0\ReBound-1.0.lua
 
 locale-enUS.lua
 
 classes\ReAnchor.xml
 classes\ReAnchor.lua
-classes\ReBound.xml
-classes\ReBound.lua
 classes\ReBar.xml
 classes\ReBar.lua
 
@@ -44,3 +43,6 @@
 Options.lua
 
 main.lua
+
+KeybindDialog.xml
+
--- a/classes/ReAction.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/classes/ReAction.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -7,8 +7,6 @@
 -- ReAction implements the ReBar.IButton interface. It is designed to be used with ReBar
 -- for grouping and laying out buttons.
 --
--- ReAction supports the ReBound keybinding interface (only).
---
 -- Each instance of a ReAction-derived object is associated with a single action
 -- button frame, which may or may not have a one-to-one mapping with actionID.
 --
@@ -77,7 +75,7 @@
   GetActionFrame     = "function", -- f = GetActionFrame(), return a frame derived from SecureActionButtonTemplate (note: this is inherited unimplemented from ReBar.IButton)
   GetBaseButtonSize  = "function", -- sz = GetBaseButtonSize(), return size in pixels of the nominal button (square)
   DisplayID          = "function", -- DisplayID(show), true/false to show/hide the action ID (or equivalent)
-  DisplayHotkey      = "function", -- DisplayHotkey(keyText), set the hotkey display text
+  DisplayHotkey      = "function", -- DisplayHotkey(keyText, button), set the hotkey display text. 2nd argument specifies which button the hotkey is for, default is "LeftButton".
 }
 
 
@@ -292,14 +290,14 @@
 -- Event handlers
 
 function ReAction.prototype:UPDATE_BINDINGS()
-  self:DisplayHotkey(self:GetKeyBindingText(nil, true))
+  self:DisplayHotkey(self:GetKeyBindingText("LeftButton", true),"LeftButton")
+  self:DisplayHotkey(self:GetKeyBindingText("RightButton",true),"RightButton")
 end
 
 
 -- Internal functions
 
 function ReAction.prototype:Recycle()
-  --self:SetKeyBinding(nil) -- TODO: only if we're using override bindings
   self:UnregisterAllEvents()
   
   -- tuck the frame away
@@ -329,13 +327,10 @@
 function ReAction.prototype:SetKeyBinding( k, mouseBtn )
   if k == nil or kbValidate(k) then
     local current = self:GetKeyBinding(mouseBtn)
-  	-- !!!TODO: do we need this?
-  	-- ClearOverrideBindings(self:GetActionFrame())
     if current then
       SetBinding(current,nil)
     end
     if k then
-      -- TODO: use OverrideBinding and store the keybinding in the profile.
       SetBindingClick(k, self:GetActionFrame():GetName(), mouseBtn or "LeftButton")
     end
   end
--- a/classes/ReAction_ActionDisplay.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/classes/ReAction_ActionDisplay.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -107,6 +107,13 @@
   -- find where it does) but for some reason we have to here.
   self.frames.cooldown:SetFrameLevel(self.frames.cooldown:GetFrameLevel() + 1)
 
+  -- create a right-click hotkey label
+  local hkr = b:CreateFontString(nil,"ARTWORK","NumberFontNormalSmallGray")
+  hkr:SetWidth(36)
+  hkr:SetHeight(10)
+  hkr:Hide()
+  self.frames.hotkeyright = hkr
+
   b:EnableMouse()
   b:RegisterForDrag("LeftButton", "RightButton")
   b:RegisterForClicks("AnyUp")
@@ -150,7 +157,7 @@
     if not f then
       -- create the actionID label
       f = self.frames.button:CreateFontString(nil,"ARTWORK","NumberFontNormalSmall")
-      f:SetPoint("BOTTOMLEFT")
+      f:SetPoint("CENTER")
       f:SetTextColor( tcolor(actionIDColor) )
       self.frames.actionID = f
     end
@@ -161,8 +168,13 @@
   end
 end
 
-function RAAD:DisplayHotkey(txt)
-  self.frames.hotkey:SetText(string.upper(txt or ""))
+function RAAD:DisplayHotkey(txt,button)
+  button = button or "LeftButton"
+  if button == "LeftButton" then
+    self.frames.hotkey:SetText(string.upper(txt or ""))
+  elseif button == "RightButton" then
+    self.frames.hotkeyright:SetText(string.upper(txt or ""))
+  end
   self:UpdateUsable()
 end
 
@@ -171,6 +183,7 @@
   f.icon:SetVertexColor(          self:GetIconColor(isUsable, notEnoughMana, outOfRange) )
   f.button:GetNormalTexture():SetVertexColor( self:GetBorderColor(isUsable, notEnoughMana, outOfRange) )
   f.hotkey:SetTextColor(          self:GetHotkeyColor(isUsable, notEnoughMana, outOfRange, f.hotkey:GetText()) )
+  f.hotkeyright:SetTextColor(     self:GetHotkeyColor(isUsable, notEnoughMana, outOfRange, f.hotkeyright:GetText()) )
 
   local o 
   if isUsable then
@@ -349,6 +362,10 @@
     placeLabel(f.hotkey, self.config.keyBindLoc)
   end
 
+  if self.config.keyBindRightLoc then
+    placeLabel(f.hotkeyright, self.config.keyBindRightLoc)
+  end
+
   if self.config.stackCountLoc then
     placeLabel(f.count, self.config.stackCountLoc)
   end
@@ -359,6 +376,12 @@
     f.hotkey:Hide()
   end
     
+  if self.config.showKeyBindRight then
+    f.hotkeyright:Show()
+  else
+    f.hotkeyright:Hide()
+  end
+    
   if self.config.showStackCount then
     f.count:Show()
   else
@@ -377,6 +400,7 @@
   local f = self.frames
   -- for now, just a static style
   f.hotkey:SetFontObject(NumberFontNormal)
+  f.hotkeyright:SetFontObject(NumberFontNormalSmall)
   f.count:SetFontObject(NumberFontNormalYellow)
   f.border:SetVertexColor( tcolor(equippedActionBorderColor) )
 end
--- a/classes/ReAction_PetActionDisplay.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/classes/ReAction_PetActionDisplay.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -169,8 +169,11 @@
   end
 end
 
-function RAPAD:DisplayHotkey(txt)
-  self.frames.hotkey:SetText(string.upper(txt or ""))
+function RAPAD:DisplayHotkey(txt,button)
+  if button == nil or button == "LeftButton" then
+    -- only left-button hotkeys supported
+    self.frames.hotkey:SetText(string.upper(txt or ""))
+  end
 end
 
 function RAPAD:DisplayInUse( inUse )
--- a/classes/ReBar.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/classes/ReBar.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -81,6 +81,7 @@
 end
 
 local AceOO = AceLibrary("AceOO-2.0")
+local ReBound = AceLibrary("ReBound-1.0")
 
 -- ReBar is an Ace 2 class prototype object.
 ReBar = AceOO.Class("AceEvent-2.0", ReAnchor, ReAnchor.IAnchorable)
@@ -183,10 +184,8 @@
   end
 
   -- register page up/down buttons with ReBound for keybinding
-  if ReBound then
-    ReBound:AddKeybindTarget(self.upArrow)
-    ReBound:AddKeybindTarget(self.downArrow)
-  end
+  ReBound:Register(self.upArrow)
+  ReBound:Register(self.downArrow)
 
   -- add bar to anchorTargets list
   table.insert(ReBar.anchorTargets, self)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ReBound-1.0/ReBound-1.0.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -0,0 +1,344 @@
+--[[
+Name: ReBound-1.0
+Revision: $Rev: 1 $
+Author: Flick
+Website: 
+Documentation: 
+SVN: 
+Description: Library for point-and-click key binding interfaces
+License: MIT
+Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2
+]]
+
+
+local version_major, version_minor = "ReBound-1.0", "$Rev: 1 $"
+
+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
+
+local L = AceLibrary("AceLocale-2.2"):new("ReBound")
+
+local colorGreen = "|cff00ff00"
+local colorOff = "|r"
+
+local mouseButtonConvert = {
+  MiddleButton = "BUTTON3",
+  Button4 = "BUTTON4",
+  Button5 = "BUTTON5"
+}
+
+-- localization
+L:RegisterTranslations( "enUS", function()
+  return {
+    ["none"] = 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 )
+
+
+
+
+local ReBound = { }
+
+
+--[[
+  Arguments:
+  key: A string representation of a key, suitable for passing to SetBinding.
+  target: The frame with an OnClick handler to attach a click-binding to
+  [button]: The mouse button to emulate. Default is "LeftButton".
+
+  Returns:
+  nothing.
+
+  Notes:
+  This does not save the bindings.
+]]
+function ReBound:SetBinding( key, target, button )
+  if not key then self:error("ReBound:SetBinding() requires a key argument.") end
+  if not target then self:error("ReBound:SetBinding() requires a binding target argument") end
+  button = button or "LeftButton"
+
+  -- prevent setting a binding that's already set
+  local current = { self:GetBinding(target,button) }
+  for _, b in pairs(current) do
+    if b == key then
+      return
+    end
+  end
+
+  -- 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 )
+
+  -- clear the old binding for the target and button (silently)
+  self:ClearBinding( nil, target, button, true )
+
+  -- set the new binding
+  SetBindingClick(key, target:GetName(), button)
+
+  -- notify listeners, e.g. for storing the setting
+  self.event:TriggerEvent("REBOUND_BIND", key, target:GetName(), button)
+end
+
+
+--[[
+  Arguments:
+  [key]: A string representation of a key, suitable for passing to SetBinding. This can be nil if target is specified.
+  [target]: The frame with a click keybinding to search for a key. 
+  [button]: The mouse button to emulate. Default is "LeftButton". Only used with [target].
+  [silent]: if true, omits printout.
+
+  Returns:
+  nothing.
+
+  Notes:
+  If key is provided, then the binding for that key is cleared. If key is not provided and target is provided, then
+  all the bindings attached to the click-binding for that target are cleared.
+
+  This does NOT save the bindings. Call SaveBindings() to commit the bindings to disk.
+]]
+function ReBound:ClearBinding( key, target, button, silent ) 
+  if not target and not key then self:error("ReBound:ClearBinding() requires a key or click-binding target argument") end
+  button = button or "LeftButton"
+
+  local keys = key and { key } or { self:GetBinding(target,button) }
+  for _, k in ipairs(keys) do
+    -- Print a notification message
+    if k and not silent then
+      local action = GetBindingAction(k)
+      if action then
+        local name = GetBindingText(action,"BINDING_NAME_")
+        local keyTxt = GetBindingText(k,"KEY_")
+        -- make click-bindings look prettier
+        local f, b = name:match("CLICK (.+)\:(.+)")
+        if f then
+          name = f
+          if b ~= "LeftButton" then
+            if b == "RightButton" then b = "Right Click" end
+            name = f .."-"..b
+          end
+        end
+        if name and #name > 0 then
+          UIErrorsFrame:AddMessage(name.." ("..colorGreen..keyTxt..colorOff..") "..L["is now unbound"].."!")
+        end
+      end
+    end
+    SetBinding(k,nil)
+    self.event:TriggerEvent("REBOUND_UNBIND", k)
+  end
+end
+
+
+--[[
+  Gets the keys bound to clicking a frame.
+
+  Arguments:
+  target: target frame to query
+  [button]: mouse button to emulate ("LeftButton", "RightButton")
+
+  Returns:
+  key1, key2, key3, etc, as strings.
+]]
+function ReBound:GetBinding( target, button )
+  if not target then self:error("ReBound:GetBinding() requires a target frame argument") end
+  button = button or "LeftButton"
+  return GetBindingKey("CLICK "..target:GetName()..":"..button)
+end
+
+
+--[[
+  Registers a target frame by creating a click-binding frame and putting that frame in the list of 
+  registered frames, which can then be all shown/hidden as one unit.
+
+  Arguments:
+  target = the frame whose OnClick handler should be the target of keybinding
+
+  Returns:
+  A clickbinder frame.
+]]
+function ReBound:Register( target )
+  local f = self:CreateClickBindingFrame(target)
+  self.frames[target] = f
+  return f
+end
+
+
+--[[ 
+  Unregisters a target frame by removing it from the internal list. Does nothing to the clickbinding frame.
+
+  Arguments:
+  target = the frame whose OnClick handler should no longer be the target of keybinding
+
+  Returns:
+  nothing.
+]]
+function ReBound:Unregister( target )
+  self.frames[target] = nil
+end
+
+
+--[[
+  Shows all the registered click binding frames.
+]]
+function ReBound:ShowAll()
+  if InCombatLockdown() then
+    -- can't set bindings while in combat, so don't bother showing them
+    UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT)
+  else
+    for _, f in pairs(self.frames) do
+      f:Show()
+    end
+  end
+end
+
+
+--[[
+  Hides all the registered click binding frames.
+]]
+function ReBound:HideAll()
+  for _, f in pairs(self.frames) do
+    f:Hide()
+  end
+end
+
+-- click binding frame implementation functions
+local function ShowTooltip1( self )
+  local target = self:GetParent()
+
+  GameTooltip:ClearLines()
+  GameTooltip:SetOwner(self,"ANCHOR_TOPRIGHT")
+  -- line 1: button name and current binding
+  GameTooltip:AddDoubleLine(target:GetName(), colorGreen.."("..(self.ReBound:GetBinding(target,"LeftButton") or L["none"])..")"..colorOff)
+  -- line 2: current right-click binding (if any)
+  local binding2 = self.ReBound:GetBinding(target,"RightButton")
+  if binding2 then
+    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:Show()
+end
+
+local function ShowTooltip2( self )
+  if GameTooltip:IsOwned(self) then
+    local target = self:GetParent()
+    GameTooltip:ClearLines()
+    GameTooltip:SetOwner(self)
+    local clickSuffix = self.selectedButton == "RightButton" and (" ("..L["Right-click"]..")") or ""
+    -- line 1: button name and binding to be set
+    GameTooltip:AddDoubleLine(target:GetName()..clickSuffix, colorGreen.."("..(self.ReBound:GetBinding(target,self.selectedButton) or L["none"])..")"..colorOff)
+    -- line 2: instructions
+    GameTooltip:AddLine(colorGreen..L["Press a key to assign binding"]..colorOff)
+    GameTooltip:Show()
+  end
+end
+
+local function OnClick( self, button )
+  if button == "LeftButton" or button == "RightButton" then
+    if IsShiftKeyDown() then
+      self.ReBound:ClearBinding( nil, self:GetParent(), button )
+      self.selectedButton = nil
+      self:EnableKeyboard(false)
+      ShowTooltip1(self)
+    else
+      self.selectedButton = button
+      self:EnableKeyboard(true)
+      ShowTooltip2(self)
+    end
+  elseif self.selectedButton then
+    self.ReBound:SetBinding( mouseButtonConvert[button], self:GetParent(), self.selectedButton )
+    self.selectedButton = nil
+    self:EnableKeyboard(false)
+    ShowTooltip1(self)
+  end
+end
+
+local function OnEnter( self )
+  -- clear current binding button
+  self.selectedButton = nil
+  -- show tooltip 1
+  ShowTooltip1(self)
+end
+
+local function OnLeave( self )
+  -- disable keyboard input, if it was enabled
+  self:EnableKeyboard(false)
+  -- hide tooltip
+  if GameTooltip:IsOwned(self) then
+    GameTooltip:Hide()
+  end
+end
+
+local function OnKeyDown( self, key )
+  if key == nil or key == "UNKNOWN" or key == "SHIFT" or key == "CTRL" or key == "ALT" then 
+    return
+  end
+  if IsShiftKeyDown()   then key = "SHIFT-"..key end
+  if IsControlKeyDown() then key = "CTRL-"..key end
+  if IsAltKeyDown()     then key = "ALT-"..key end
+
+  if key ~= "ESCAPE" then
+    self.ReBound:SetBinding( key, self:GetParent(), self.selectedButton )
+  end
+
+  self:EnableKeyboard(false)
+  self.selectedButton = nil
+  ShowTooltip1(self)
+end
+
+--[[
+  Creates a click-binding frame attached to the target frame, which can be used for point-and-click keybind assignments. The
+  frame is initially hidden by default. It is not registered with ReBound for automatic show/hide: use Register() for that.
+
+  Arguments:
+  target - the frame whose OnClick handler should be the target of keybinding
+
+  Returns:
+  A clickbinder frame.
+]]
+function ReBound:CreateClickBindingFrame( target )
+  local f = CreateFrame("Button", nil, target)
+  f.ReBound = self
+  f:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
+  f:SetToplevel(1)
+  f:SetFrameStrata("DIALOG")
+  f:RegisterForClicks("AnyUp")
+  f:SetScript("OnClick",   OnClick)
+  f:SetScript("OnEnter",   OnEnter)
+  f:SetScript("OnLeave",   OnLeave)
+  f:SetScript("OnKeyDown", OnKeyDown)
+  f:SetAllPoints(target)
+  f:Hide()
+  return f
+end
+
+
+
+-- library setup
+
+local function activate( self, oldLib, oldDeactivate )
+  -- set initial values
+  self.mode = oldLib and oldLib.mode or "char"
+  self.frames = { }
+
+  self.event = AceLibrary("AceOO-2.0").Class("AceEvent-2.0"):new()
+  self.event:RegisterEvent("PLAYER_REGEN_DISABLED", function() self:HideAll() end)
+
+  if oldDeactivate then
+    oldDeactivate(oldLib)
+  end
+end
+
+local function deactivate( self )
+  self.event:UnregisterEvent("PLAYER_REGEN_DISABLED")
+end
+
+AceLibrary:Register(ReBound, version_major, version_minor, activate, deactivate)
+ReBound = nil
--- a/locale-enUS.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/locale-enUS.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -7,7 +7,7 @@
   -- main.lua
   ["ReAction"] = true,
   ["Toggle ReAction Bar Lock"] = true,
-  ["Toggle ReBound Keybinding Mode"] = true,
+  ["ReAction Keybinding Mode"] = true,
   ["/reaction"] = true,
   ["/rxn"] = true,
   ["ReAction bars locked when in combat"] = true,
@@ -20,6 +20,13 @@
   ["Kebinding mode"] = true,
   ["Tried to create a button of unknown type"] = true,
   ["|cffffcc00Shift-Click for bar lock|n|cff33ff33Alt-Click|r for keybindings|nRight-click for menu"] = true,
+  ["ReAction Keybinding"] = true,
+  ["Click Buttons to Set Keybindings"] = true,
+  ["Save"] = true,
+  ["Revert"] = true,
+  ["Use ReAction"] = true,
+  ["Action Bar Functions Disabled"] = true,
+  ["Multi-Action Bar Functions Disabled"] = true,
 
 }
 end )
--- a/main.lua	Tue Mar 20 21:35:57 2007 +0000
+++ b/main.lua	Tue Mar 20 21:37:38 2007 +0000
@@ -9,6 +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")
 
 -- private functions
 local function tcopy(t)
@@ -25,10 +26,19 @@
 -- 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"]
+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"]
 
--- main object
+
+
+------------------------------
+-- AceAddon setup
+------------------------------
 local main = AceLibrary("AceAddon-2.0"):new(
   "AceConsole-2.0",
   "AceEvent-2.0",
@@ -36,15 +46,65 @@
   "FuBarPlugin-2.0"
 )
 
--- initial non-persistent state
-main.locked = true
+function main:OnInitialize()
+  self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" )
+  self:RegisterDB("ReActionDB","ReActionDBPC")
+  self:RegisterDefaults("profile", ReAction_DefaultProfile)
+  self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
+  self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
+  self:DisableDefaultKeybindings()
 
--- set a global variable for Bindings.xml
-ReActionAddOn = main
+  -- initial non-persistent state
+  self.locked = true
+  self.bars   = { }
+end
 
+-- OnEnable is called at startup (startup = true, oldConfig = nil),
+-- and when the profile is changed (startup = false, oldConfig ~= nil )
+function main:OnEnable( startup, oldConfig )
+  if self.db.profile.firstRunDone ~= true then
+    self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
+  end
+  self:DestroyAllBars()
+  self:SetupBars()
+  self:UpgradeProfile()
+  self:SetupKeybindings( oldConfig and oldConfig.bindings )
+  if self.db.profile.firstRunDone ~= true then
+    self:Unlock()
+  end
+  self.db.profile.firstRunDone = true
+end
 
+function main:OnDisable()
+  self:Lock()
+end
+
+-- OnProfileEnable() is only called when switching profiles, NOT for the initial profile at load time.
+function main:OnProfileEnable( oldName, oldData )
+  self:OnEnable(false, oldData)
+end
+
+function main:UpgradeProfile()
+  if self.db.profile.firstRunDone ~= true and #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")
+        if key and #key > 0 and not self.db.profile.bindings[key] then
+          self:REBOUND_BIND(key,button:GetActionFrame():GetName(),"LeftButton")
+        end
+      end
+    end
+  end
+end
+
+
+
+
+--------------------------------------------
 -- FuBar plugin setup
--- Even if FuBar isn't installed, this gives us a nice minimap-button interface.
+-- Even if FuBar isn't installed, the plugin 
+-- provides a nice  minimap-button interface.
+---------------------------------------------
 main.hasIcon = "Interface\\Icons\\INV_Qiraj_JewelEncased"
 main.hasNoColor = true
 main.hideMenuTitle = true
@@ -57,65 +117,11 @@
 -- have to do this after tcopy() above, otherwise it will try to copy the handler object (bad idea)
 ReActionGlobalMenuOptions.handler = main
 
-
-
-
--- Event handling
-function main:OnInitialize()
-  self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" )
-  self:RegisterDB("ReActionDB","ReActionDBPC")
-  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 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
-    self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
-  end
-  self:DestroyAllBars()
-  self:SetupBars()
-end
-
-function main:OnDisable()
-  self:Lock()
-end
-
-function main:OnProfileEnable()
-  -- for profile switching
-  self:OnEnable()
-end
-
-function main:CombatLockdown()
-  if not self:IsLocked() then
-    self:Lock()
-    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
-      if button and button ~= EMPTY_BAR_SLOT then
-        button:TempShow(enabled)
-      end
-    end
-  end
-end
-
-
--- 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"))
+  c:AddLine("text", L["Kebinding mode"], "text2", self:GetKeybindMode() 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
 
@@ -124,17 +130,134 @@
 	  self:ToggleLocked()
     self:UpdateDisplay()
 	elseif IsAltKeyDown() then
-    ReBound:ToggleEnabled()
+    self:ToggleKeybindMode()
     self:UpdateDisplay()
   end
 end
 
 
--- lock/unlock bars
+
+
+------------------------------
+-- Key binding functions
+------------------------------
+function main:DisableDefaultKeybindings()
+  -- 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)
+    for j = 1, 4 do
+      setglobal("BINDING_NAME_MULTIACTIONBAR"..j.."BUTTON"..i,label)
+    end
+  end
+  for i = 1, 6 do
+    setglobal("BINDING_NAME_ACTIONPAGE"..i,label)
+  end
+  for i = 1, 10 do
+    setglobal("BINDING_NAME_BONUSACTIONBUTTON"..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"
+  BINDING_NAME_NEXTACTIONPAGE = label
+  BINDING_NAME_PREVIOUSACTIONPAGE = label
+end
+
+function main:SetupKeybindings( previous )
+  if previous then
+    self:UnregisterEvent("REBOUND_BIND")
+    self:UnregisterEvent("REBOUND_UNBIND")
+    for key, binding in pairs(previous) do
+      ReBound:ClearBinding(key, getglobal(binding.target), binding.button, true)
+    end
+  end
+  if self.db.profile.firstRunDone ~= true then
+    self:StealKeyBindings()
+  else
+    for key, binding in pairs(self.db.profile.bindings) do
+      ReBound:SetBinding(key, getglobal(binding.target), binding.button)
+    end
+  end
+  SaveBindings(GetCurrentBindingSet())
+  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)
+    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")
+    end
+  end
+  SaveBindings(GetCurrentBindingSet())
+end
+
+function main:REBOUND_BIND(key, target, button)
+  if key and target then
+    self.db.profile.bindings[key] = { target = target, button = button }
+  end
+end
+
+function main:REBOUND_UNBIND(key)
+  if key then
+    self.db.profile.bindings[key] = nil
+  end
+end
+
+function main:ToggleKeybindMode()
+  self:SetKeybindMode(not self:GetKeybindMode())
+end
+
+function main:GetKeybindMode()
+  return self.keybindMode
+end
+
+function main:SetKeybindMode(enabled)
+  if not InCombatLockdown() then
+    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)
+        end
+      end
+    end
+    if enabled then
+      ReBound:ShowAll()
+      ReActionKeybindDialog:Show()
+    else
+      ReBound:HideAll()
+      if ReActionKeybindDialog:IsShown() then
+        ReActionKeybindDialog:Hide()
+      end
+    end
+  else
+    UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT)
+  end
+end
+
+
+
+
+----------------------------
+-- Bar lock/unlock functions
+----------------------------
+function main:CombatLockdown()
+  if not self:IsLocked() then
+    self:Lock()
+    UIErrorsFrame:AddMessage(L["ReAction bars locked when in combat"])
+  end
+  ReActionKeybindDialog:Hide()
+end
+
 function main:SetLocked( lock )
   if lock ~= self.locked then
     if not lock and InCombatLockdown() then
-      UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+      UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT)
     else
       self.locked = lock and true or false -- force data integrity
       for _, bar in pairs(self.bars) do
@@ -172,7 +295,9 @@
 
 
 
--- Hide the default Blizzard main bar artwork
+--------------------------------------------------------
+-- Functions to hide the default Blizzard main bar parts
+--------------------------------------------------------
 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
@@ -207,8 +332,6 @@
   self:SetHideArt( not self:IsArtHidden() )
 end
 
-
-
 -- Hide default Blizzard bars
 local blizzDefaultBars = {
   ActionButton1,
@@ -245,13 +368,6 @@
   MultiBarBottomRight,
 }
 
-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
@@ -277,6 +393,11 @@
 end
 
 
+
+
+---------------------------------------
+-- Bar setup and manipulation functions
+---------------------------------------
 -- Reset bars to blizzard defaults
 function main:ResetBars()
   if InCombatLockdown() then
@@ -288,17 +409,6 @@
   end
 end
 
-
--- re-sync action IDs
-function main:ResyncActionIDs()
-  -- TODO
-end
-
-
-
--- Bar manipulation
-main.bars    = { }
-
 function main:DestroyAllBars()
   -- destroy any existing bars
   for id = 1, table.maxn(self.bars) do
@@ -306,7 +416,6 @@
   end
 end
 
-
 function main:SetupBars()
   -- hide the default Blizzard art, if configued
   self:HideArt()
@@ -388,6 +497,9 @@
   end
 end
 
+-- 
+-- this function is a wrapper for CreateBar() which looks up the bar type
+-- and constructs a new configuration object of the right type.
 function main:NewBar( type )
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
@@ -409,7 +521,9 @@
   end
 end
 
-
+--
+-- This function is a wrapper for DestroyBar() which does in-combat 
+-- checking and updates the config.
 function main:DeleteBar(id)
   if InCombatLockdown() then
     UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
@@ -421,6 +535,12 @@
   end
 end
 
+
+
+
+-----------------
+-- General utility
+-----------------
 function main:ToggleIds()
   if self.showIds then
     ReAction:HideAllIds()
@@ -434,5 +554,7 @@
   return self.showIds
 end
 
+-- set a global variable for Bindings.xml
+ReActionAddOn = main