changeset 16:cdd387d39137

filename refactor
author Nenue
date Fri, 29 Jul 2016 21:18:15 -0400
parents 32d64e42ec9b
children 500f9b2bd9ac
files SkeletonKey/ActionTypes.lua SkeletonKey/BindingsUI.lua SkeletonKey/Cache.lua SkeletonKey/DynamicTypes.lua SkeletonKey/KeyBinds.xml SkeletonKey/KeySlot.lua SkeletonKey/SkeletonKey.lua SkeletonKey/SkeletonKey.toc SkeletonKey/SkeletonKey.xml
diffstat 9 files changed, 684 insertions(+), 652 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SkeletonKey/ActionTypes.lua	Fri Jul 29 21:18:15 2016 -0400
@@ -0,0 +1,79 @@
+-- SkeletonKey
+-- ActionTypes.lua
+-- Created: 7/29/2016 9:14 PM
+-- %file-revision%
+--
+local kb, print, wrap = LibStub('LibKraken').register(KeyBinder)
+
+local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544
+
+local PETACTION_SCRIPT = {
+  [PET_ACTION_MOVE_TO] = {SLASH_PET_MOVE_TO1, 'pet_move_to'},
+  [PET_ACTION_ATTACK] = {SLASH_PET_ATTACK1, 'pet_attack'},
+  [PET_ACTION_FOLLOW] = {SLASH_PET_FOLLOW1, 'pet_follow'},
+  [PET_ACTION_WAIT] = {SLASH_PET_STAY1, 'pet_stay'},
+  [PET_MODE_AGGRESSIVE] = {SLASH_PET_AGGRESSIVE1, 'pet_aggressive'},
+  [PET_MODE_DEFENSIVE] = {SLASH_PET_DEFENSIVE1, 'pet_defensive'},
+  [PET_MODE_PASSIVE] = {SLASH_PET_PASSIVE1, 'pet_passive'},
+  [PET_MODE_ASSIST] = {SLASH_PET_ASSIST1, 'pet_assist'},
+}
+
+--- Caps Lock derivatives
+local ACTION_HANDLERS = {}
+ACTION_HANDLERS['mount'] = function(id, name)
+  return "/script C_MountJournal.SummonByID("..id..")"
+end
+ACTION_HANDLERS['macro'] = "%s"
+ACTION_HANDLERS['equipset'] = "/script UseEquipmentSet(%d)"
+ACTION_HANDLERS['spell'] = "/cast %s"
+ACTION_HANDLERS['petaction'] = function(id, name)
+  return PETACTION_SCRIPT[name] or "/cast ".. name
+end
+
+ACTION_HANDLERS['battlepet'] = SLASH_SUMMON_BATTLE_PET1 .. " %s"
+ACTION_HANDLERS['item'] = "/use %s"
+local professionMappings = {
+  [5] = 3,
+  [7] = 4,
+  [9] = 5,
+  [10] = 6
+}
+
+
+--- Generates the command strings needed to assign different abilities
+kb.RegisterAction = function(actionType, id, name)
+  local macroText, macroName, command = '', '', ''
+
+  if actionType == 'spell' then
+    if kb.ProfessionCache[id] then
+      command = CLICK_KEYBINDER_KEY .. "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum
+    else
+      command = CLICK_KEYBINDER_KEY ..name
+    end
+  else
+
+    if type(ACTION_SCRIPT[actionType]) == 'function' then
+      macroName, macroText = ACTION_SCRIPT[actionType](id, name)
+    else
+      macroName = actionType .. ' ' .. name
+      macroText = ACTION_SCRIPT[actionType]:format(name)
+    end
+
+    local baseName, iterative = macroName, 1
+    while (macros[macroName] and macros[macroName][1] ~= macroText) do
+      print(' * cannot use|cFF00FF00', macroName, '|r"'.. (macros[macroName][1] or '') .. '"')
+      macroName = baseName .. '_' .. iterative
+      iterative = iterative + 1
+    end
+    if macroName ~= baseName then
+      print(' * Creating|cFF00FF00', macroName)
+    else
+      print(' * Re-using|cFF00FF00', macroName)
+    end
+    command = 'CLICK KeyBinderMacro:'.. macroName
+    macros[macroName] = {macroText, command }
+  end
+
+  print('RegisterAction', actionType, id, '->', command , macroText)
+  return macroName, macroText, command
+end
\ No newline at end of file
--- a/SkeletonKey/BindingsUI.lua	Fri Jul 29 03:27:15 2016 -0400
+++ b/SkeletonKey/BindingsUI.lua	Fri Jul 29 21:18:15 2016 -0400
@@ -2,7 +2,7 @@
 -- BindingsUI.lua
 -- Created: 7/28/2016 3:39 PM
 -- %file-revision%
---
+-- Code piecing the interface together
 
 local kb, print = LibStub("LibKraken").register(KeyBinder, 'KeySlot')
 local BINDS_PER_ROW = 2
@@ -38,17 +38,23 @@
 local fadeTime, fadeDelay = .30, 0.15
 local numButtons = BINDS_PER_ROW * 8
 local saveButton
-local KeyButton_OnKeyDown = function(self, key)
-  kb.StoreBinding(self, key)
+local KeyButton_OnKey = function(self, key)
+  kb.StoreBinding(self.saveTarget, key)
+  kb:SetScript('OnKeyUp', nil)
+  kb:SetScript('OnKeyDown', nil)
 end
+
 local KeyButton_OnClick = function(self, click)
   print(self:GetName(), 'OnMouseDown', click)
+  local cursorType = GetCursorInfo()
   if click == 'LeftButton' then
-    kb.DropToSlot(self)
+    if cursorType then
+      kb.DropToSlot(self)
+    else
+      kb.ActivateSlot(self)
+    end
   elseif click == 'RightButton' then
     kb.ReleaseSlot(self)
-  else
-    kb.StoreBinding(self, click:upper())
   end
 end
 
@@ -103,8 +109,6 @@
     if not self.active then
       -- only set this handler when the button is activated/mouseOver
       self.active = true
-      self:SetScript('OnKeyDown', KeyButton_OnKeyDown)
-
       kb.statustext:SetText(self.statusText .. ': '..self.actionName)
       kb.bindingstext:SetText(self.bindingText)
       kb.fadeStep = 0
@@ -261,6 +265,12 @@
 end
 
 
+kb.ActivateSlot = function(self)
+  kb.saveTarget = self
+  kb:SetScript('OnKeyUp', KeyButton_OnKey)
+  kb.bg:SetColorTexture(0,.5,0,1)
+end
+
 --- push current information into living UI
 kb.ui = function(force)
   for i, module in ipairs(kb.modules) do
--- a/SkeletonKey/Cache.lua	Fri Jul 29 03:27:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
--- KrakTool
--- Cache.lua
--- Created: 7/28/2016 3:28 PM
--- %file-revision%
--- Cached data regarding talent options, pet spells, etc.
-local kb, print = LibStub('LibKraken').register(KeyBinder, 'PlayerInfo')
-
-local PET_SPECIAL_SUBTEXT = 'Special Ability'
-local BINDING_TYPE_SPECIALIZATION = 3
-local BINDING_TYPE_CHARACTER = 2
-local BINDING_TYPE_GLOBAL = 1
-local professionMappings = {
-  [5] = 3,
-  [7] = 4,
-  [9] = 5,
-  [10] = 6
-}
-
-kb.TalentCache = {}
-kb.ProfessionCache = {}
-kb.PetCache = {}
-kb.specInfo = {}
-kb.UpdateSpecInfo = function()
-  kb.specInfo.id = GetSpecialization()
-  kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id)
-  kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id] = kb.InitProfile(kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id], {
-    specID = kb.specInfo.id})
-
-  kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name)
-  kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id]
-  kb.currentProfile = kb.loadedProfiles[kb.db.bindMode]
-  print('|cFF00FF00bindMode:|r', kb.db.bindMode)
-
-  kb.profileOrder = {kb.loadedProfiles[BINDING_TYPE_GLOBAL], kb.loadedProfiles[BINDING_TYPE_CHARACTER], kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION]}
-
-  print('|cFF00FF00current spec:|r', kb.specInfo.id, 'of', GetNumSpecializations())
-end
-
-kb.UpdateTalentInfo = function()
-  if kb.talentsPushed then
-    return
-  end
-
-
-  table.wipe(kb.TalentCache)
-
-  for row =1, MAX_TALENT_TIERS do
-    for col = 1, NUM_TALENT_COLUMNS do
-      local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1)
-      local talentInfo = kb.TalentCache[spellID] or {}
-      talentInfo.row = 1
-      talentInfo.col = col
-      talentInfo.name = talentName
-      talentInfo.talentID = talentID
-      talentInfo.selected = selected
-      talentInfo.available = available
-      talentInfo.spellID = spellID
-      kb.TalentCache[spellID] = talentInfo
-      kb.TalentCache[talentName] = talentInfo
-      print('Talent ', row, col, spellID, talentName)
-    end
-  end
-  kb.talentsPushed = true
-end
-
-kb.UpdateProfessionInfo = function()
-  table.wipe(kb.ProfessionCache)
-  local profs = {GetProfessions() }
-  local primaryNum = 0
-  for i, index in ipairs(profs) do
-    local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index)
-    print(i, index, profName, numSpells, spellOffset)
-    if not professionMappings[index] then
-      primaryNum = primaryNum + 1
-    end
-    local profNum = professionMappings[index] or primaryNum
-
-
-    kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {}
-
-    for j = 1, numSpells do
-      local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION)
-
-      local profInfo = {
-        spellName = spellName,
-        spellID = spellID,
-        icon = icon,
-        profOffset = i,
-        profIndex = index,
-        spellOffset = (spellOffset+j),
-        spellNum = j
-      }
-      KeyBinderKey:SetAttribute("*type-profession_"..i .. '_' ..j, "spell")
-      KeyBinderKey:SetAttribute("*spell-profession_"..i .. '_' ..j, spellName)
-
-      kb.ProfessionCache[i .. '_' .. j] = profInfo
-      kb.ProfessionCache[spellName] = profInfo
-      kb.ProfessionCache[spellID] = profInfo
-      print('  |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j)
-    end
-
-  end
-
-end
-
-
-
-kb.UpdatePetInfo = function()
-  kb.PetCache.spell = kb.PetCache.spell or {}
-  kb.PetCache.spellslot = kb.PetCache.spellslot or {}
-  kb.PetCache.action = kb.PetCache.action or {}
-  kb.PetCache.special = kb.PetCache.action or {}
-  local hasPetSpells, petType = HasPetSpells()
-  if PetHasSpellbook() then
-    print('PET SPELLBOOK')
-    local i = 1
-    local specialNum = 0
-    repeat
-
-      local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET)
-      local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET)
-      local isPassive = IsPassiveSpell(i, BOOKTYPE_PET)
-      if not isPassive then
-        if spellName then
-          kb.PetCache.spellslot[spellName] = {i, spellName, subText}
-          print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText)
-
-          if subText == PET_SPECIAL_SUBTEXT then
-            specialNum = specialNum + 1
-            kb.PetCache.special[spellName] = {i, specialNum, spellID, subText }
-            print('|cFF00FFFFspecial['..spellName..']|r', '=>', i, specialNum, spellID, subText)
-          end
-
-          if spellID then
-            kb.PetCache.spell[i] = {spellID, spellName, subText}
-            print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText)
-          end
-        end
-
-
-      end
-
-      i = i + 1
-    until spellType == nil
-  else
-    print('NO PET SPELLBOOK')
-    table.wipe(kb.PetCache.spell)
-    table.wipe(kb.PetCache.spellslot)
-  end
-
-  if PetHasActionBar() then
-    print('PET ACTION BAR')
-    for i = 1, 10 do
-
-
-      local name, subtext, texture, isToken, isActive = GetPetActionInfo(i)
-      if name then
-        kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive }
-
-
-      end
-      print('|cFFFFFF00action['..i..']|r', name, subtext, texture)
-    end
-  else
-    print('NO PET ACTION BAR')
-    table.wipe(kb.PetCache.action)
-  end
-
-  kb.UpdateCacheButtons(kb.petFrames)
-
-end
-
-kb.SystemBinds = {}
-kb.UpdateSystemBinds = function()
-  table.wipe(kb.SystemBinds)
-  local n = GetNumBindings()
-  for i=1, n do
-    local command, key1, key2 = GetBinding(i)
-    if key1 then
-      kb.SystemBinds[key1] = command
-    end
-    if key2 then
-      kb.SystemBinds[key2] = command
-    end
-  end
-
-end
-
-do
-  local garbage = {}
-  kb.UpdateCacheButtons = function(pending)
-    for i, button in ipairs(pending) do
-      if button.isDynamic then
-        print('flushing button', button:GetID())
-          kb.UpdateSlot(button, true)
-      end
-    end
-  end
-end
-
-
-kb.RemoveCacheButton = function(pending, button)
-  local found
-  for index, frame in ipairs(pending) do
-    if button == frame then
-      found = index
-      break
-    end
-  end
-  if found then
-    print('|cFFFF4400pruning', button:GetName(), 'from update queue')
-    tremove(pending, found)
-  end
-
-end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SkeletonKey/DynamicTypes.lua	Fri Jul 29 21:18:15 2016 -0400
@@ -0,0 +1,215 @@
+-- KrakTool
+-- DynamicTypes.lua
+-- Created: 7/28/2016 3:28 PM
+-- %file-revision%
+-- Logic related to dynamic handlers
+local kb, print = LibStub('LibKraken').register(KeyBinder, 'PlayerInfo')
+
+local PET_SPECIAL_SUBTEXT = 'Special Ability'
+local BINDING_TYPE_SPECIALIZATION = 3
+local BINDING_TYPE_CHARACTER = 2
+local BINDING_TYPE_GLOBAL = 1
+local professionMappings = {
+  [5] = 3,
+  [7] = 4,
+  [9] = 5,
+  [10] = 6
+}
+
+kb.TalentCache = {}
+kb.ProfessionCache = {}
+kb.PetCache = {}
+kb.specInfo = {}
+kb.UpdateSpecInfo = function()
+  kb.specInfo.id = GetSpecialization()
+  kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id)
+  kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id] = kb.InitProfile(kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id], {
+    specID = kb.specInfo.id})
+
+  kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name)
+  kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = kb.loadedProfiles[BINDING_TYPE_CHARACTER][kb.specInfo.id]
+  kb.currentProfile = kb.loadedProfiles[kb.db.bindMode]
+  print('|cFF00FF00bindMode:|r', kb.db.bindMode)
+
+  kb.profileOrder = {kb.loadedProfiles[BINDING_TYPE_GLOBAL], kb.loadedProfiles[BINDING_TYPE_CHARACTER], kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION]}
+
+  print('|cFF00FF00current spec:|r', kb.specInfo.id, 'of', GetNumSpecializations())
+end
+
+kb.UpdateTalentInfo = function()
+  if kb.talentsPushed then
+    return
+  end
+
+
+  table.wipe(kb.TalentCache)
+
+  for row =1, MAX_TALENT_TIERS do
+    for col = 1, NUM_TALENT_COLUMNS do
+      local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1)
+      local talentInfo = kb.TalentCache[spellID] or {}
+      talentInfo.row = 1
+      talentInfo.col = col
+      talentInfo.name = talentName
+      talentInfo.talentID = talentID
+      talentInfo.selected = selected
+      talentInfo.available = available
+      talentInfo.spellID = spellID
+      kb.TalentCache[spellID] = talentInfo
+      kb.TalentCache[talentName] = talentInfo
+      print('Talent ', row, col, spellID, talentName)
+    end
+  end
+  kb.talentsPushed = true
+end
+
+kb.UpdateProfessionInfo = function()
+  table.wipe(kb.ProfessionCache)
+  local profs = {GetProfessions() }
+  local primaryNum = 0
+  for i, index in ipairs(profs) do
+    local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index)
+    print(i, index, profName, numSpells, spellOffset)
+    if not professionMappings[index] then
+      primaryNum = primaryNum + 1
+    end
+    local profNum = professionMappings[index] or primaryNum
+
+
+    kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {}
+
+    for j = 1, numSpells do
+      local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION)
+
+      local profInfo = {
+        spellName = spellName,
+        spellID = spellID,
+        icon = icon,
+        profOffset = i,
+        profIndex = index,
+        spellOffset = (spellOffset+j),
+        spellNum = j
+      }
+      KeyBinderKey:SetAttribute("*type-profession_"..i .. '_' ..j, "spell")
+      KeyBinderKey:SetAttribute("*spell-profession_"..i .. '_' ..j, spellName)
+
+      kb.ProfessionCache[i .. '_' .. j] = profInfo
+      kb.ProfessionCache[spellName] = profInfo
+      kb.ProfessionCache[spellID] = profInfo
+      print('  |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j)
+    end
+
+  end
+
+end
+
+
+
+kb.UpdatePetInfo = function()
+  kb.PetCache.spell = kb.PetCache.spell or {}
+  kb.PetCache.spellslot = kb.PetCache.spellslot or {}
+  kb.PetCache.action = kb.PetCache.action or {}
+  kb.PetCache.special = kb.PetCache.action or {}
+  local hasPetSpells, petType = HasPetSpells()
+  if PetHasSpellbook() then
+    print('PET SPELLBOOK')
+    local i = 1
+    local specialNum = 0
+    repeat
+
+      local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET)
+      local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET)
+      local isPassive = IsPassiveSpell(i, BOOKTYPE_PET)
+      if not isPassive then
+        if spellName then
+          kb.PetCache.spellslot[spellName] = {i, spellName, subText}
+          print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText)
+
+          if subText == PET_SPECIAL_SUBTEXT then
+            specialNum = specialNum + 1
+            kb.PetCache.special[spellName] = {i, specialNum, spellID, subText }
+            print('|cFF00FFFFspecial['..spellName..']|r', '=>', i, specialNum, spellID, subText)
+          end
+
+          if spellID then
+            kb.PetCache.spell[i] = {spellID, spellName, subText}
+            print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText)
+          end
+        end
+
+
+      end
+
+      i = i + 1
+    until spellType == nil
+  else
+    print('NO PET SPELLBOOK')
+    table.wipe(kb.PetCache.spell)
+    table.wipe(kb.PetCache.spellslot)
+  end
+
+  if PetHasActionBar() then
+    print('PET ACTION BAR')
+    for i = 1, 10 do
+
+
+      local name, subtext, texture, isToken, isActive = GetPetActionInfo(i)
+      if name then
+        kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive }
+
+
+      end
+      print('|cFFFFFF00action['..i..']|r', name, subtext, texture)
+    end
+  else
+    print('NO PET ACTION BAR')
+    table.wipe(kb.PetCache.action)
+  end
+
+  kb.UpdateCacheButtons(kb.petFrames)
+
+end
+
+kb.SystemBinds = {}
+kb.UpdateSystemBinds = function()
+  table.wipe(kb.SystemBinds)
+  local n = GetNumBindings()
+  for i=1, n do
+    local command, key1, key2 = GetBinding(i)
+    if key1 then
+      kb.SystemBinds[key1] = command
+    end
+    if key2 then
+      kb.SystemBinds[key2] = command
+    end
+  end
+
+end
+
+do
+  local garbage = {}
+  kb.UpdateCacheButtons = function(pending)
+    for i, button in ipairs(pending) do
+      if button.isDynamic then
+        print('flushing button', button:GetID())
+          kb.UpdateSlot(button, true)
+      end
+    end
+  end
+end
+
+
+kb.RemoveCacheButton = function(pending, button)
+  local found
+  for index, frame in ipairs(pending) do
+    if button == frame then
+      found = index
+      break
+    end
+  end
+  if found then
+    print('|cFFFF4400pruning', button:GetName(), 'from update queue')
+    tremove(pending, found)
+  end
+
+end
\ No newline at end of file
--- a/SkeletonKey/KeyBinds.xml	Fri Jul 29 03:27:15 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-<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">
-  <Button name="KeyBinderMacro" inherits="SecureActionButtonTemplate">
-    <Attributes>
-      <Attribute name="*type*" value="macro" />
-    </Attributes>
-  </Button>
-  <Button name="KeyBinderKey" inherits="SecureActionButtonTemplate" />
-  <CheckButton name="KeyButton" virtual="true">
-    <Size x="32" y="32" />
-    <Layers>
-      <Layer level="BACKGROUND">
-        <Texture parentKey="border" setAllPoints="true">
-          <Color a="1" r=".25" g=".25" b=".25" />
-        </Texture>
-      </Layer>
-      <Layer level="BORDER">
-
-        <Texture parentKey="bg">
-          <Anchors>
-            <Anchor point="TOPLEFT" x="2" y="-2" />
-            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
-          </Anchors>
-          <Color a="0.5" r="0" g="0" b="0" />
-        </Texture>
-      </Layer>
-      <Layer level="ARTWORK">
-        <Texture setAllPoints="true" parentKey="icon">
-          <Anchors>
-            <Anchor point="TOPLEFT" x="2" y="-2" />
-            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
-          </Anchors>
-
-          <TexCoords left="0.1" right="0.9" top="0.1" bottom="0.9" />
-
-        </Texture>
-      </Layer>
-      <Layer level="OVERLAY">
-        <FontString inherits="NumberFontNormal" parentKey="header" wordwrap="false" justifyH="LEFT">
-
-          <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="-2" />
-            <Anchor point="RIGHT" x="128" y="0" />
-          </Anchors>
-        </FontString>
-        <FontString inherits="NumberFontNormal" parentKey="bind">
-          <Anchors>
-            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
-          </Anchors>
-        </FontString>
-        <FontString inherits="KTMacroButtonFont" parentKey="macro">
-          <Anchors>
-            <Anchor point="TOPLEFT" x="2" y="-2" />
-            <Anchor point="RIGHT" x="-2" y="0" />
-          </Anchors>
-        </FontString>
-        <FontString inherits="NumberFontNormal" parentKey="details" justifyH="LEFT">
-          <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" x="0" y="-2" relativeKey="$parent.header" />
-            <Anchor point="RIGHT" x="128" y="0" />
-          </Anchors>
-        </FontString>
-
-        <Texture parentKey="ignoreTexture" file="Interface\PaperDollInfoFrame\UI-GearManager-LeaveItem-Transparent" hidden="true">
-          <Anchors>
-            <Anchor point="TOPLEFT" x="0" y="0" />
-            <Anchor point="BOTTOMRIGHT" x="0" y="0" />
-          </Anchors>
-        </Texture>
-      </Layer>
-    </Layers>
-    <HighlightTexture file="Interface\BUTTONS\UI-Button-Outline" alphaMode="ADD">
-      <Anchors>
-        <Anchor point="TOPLEFT" x="-13" y="13" />
-        <Anchor point="BOTTOMRIGHT" x="13" y="-13" />
-      </Anchors>
-    </HighlightTexture>
-  </CheckButton>
-
-  <Frame name="KeyBinder" parent="UIParent" hidden="true" clampedToScreen="true" movable="true" enableMouse="true">
-    <Anchors>
-      <Anchor point="TOP" y="-25" x="0" />
-    </Anchors>
-    <Size x="600" y="200" />
-    <Scripts>
-      <OnLoad>
-        self:RegisterForDrag('LeftButton')
-      </OnLoad>
-      <OnShow>
-      </OnShow>
-      <OnDragStart>
-        self:StartMoving()
-      </OnDragStart>
-      <OnDragStop>
-        self:StopMovingOrSizing()
-      </OnDragStop>
-      <OnMouseWheel>
-        self:OnMouseWheel(delta)
-      </OnMouseWheel>
-      <OnHide>
-        self:OnHide()
-      </OnHide>
-    </Scripts>
-    <Layers>
-      <Layer level="BACKGROUND">
-
-        <Texture parentKey="info">
-          <Anchors>
-            <Anchor point="TOPLEFT" />
-            <Anchor point="RIGHT" />
-          </Anchors>
-          <Size y="42" />
-        </Texture>
-
-        <Texture parentKey="headerbg" alphaMode="MOD">
-          <Size y="32" />
-          <Anchors>
-            <Anchor point="TOPLEFT" />
-            <Anchor point="RIGHT" />
-          </Anchors>
-          <Color a="1" r="1" g="1" b="1" />
-          <Gradient orientation="VERTICAL">
-            <MinColor r="0" g="0" b="0"/>
-            <MaxColor r="1" g="1" b="1"/>
-          </Gradient>
-        </Texture>
-
-        <Texture parentKey="sourcesbg">
-          <Size x="100" />
-          <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.headerbg" />
-            <Anchor point="BOTTOM" />
-          </Anchors>
-          <Color a="1" r="0.2" g="0.2" b="0.2" />
-        </Texture>
-
-
-
-        <Texture parentKey="profilebg">
-          <Size  y="102" />
-          <Anchors>
-            <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.headerbg" />
-            <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" />
-            <Anchor point="RIGHT" />
-          </Anchors>
-          <Color a="1" r="0" g="0" b="0" />
-        </Texture>
-
-        <Texture parentKey="bg">
-          <Anchors>
-            <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.profilebg" />
-            <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" />
-          </Anchors>
-          <Color a="0.5" r="0" g="0" b="0" />
-        </Texture>
-
-        <Texture parentKey="footer">
-          <Size y="52" />
-          <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="0" />
-            <Anchor point="RIGHT"  />
-          </Anchors>
-          <Color a="1" r="0" g="0" b="0" />
-        </Texture>
-      </Layer>
-      <Layer level="OVERLAY">
-
-        <FontString inherits="KTHeaderFont" text="Bindings" parentKey="header">
-          <Anchors>
-            <Anchor point="TOPLEFT" />
-          </Anchors>
-        </FontString>
-
-        <FontString parentKey="profiletext" inherits="KTHeader2Font" justifyH="LEFT" text="Foobar">
-          <Anchors>
-            <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" relativeKey="$parent.header" x="8" y="5" />
-          </Anchors>
-          <Color a="1" r="1" g="0.7" b="0" />
-        </FontString>
-
-        <FontString parentKey="statustext" inherits="NumberFont_Outline_Large" justifyH="LEFT" justifyV="TOP">
-          <Anchors>
-            <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="12" y="7" />
-          </Anchors>
-        </FontString>
-
-
-        <FontString parentKey="bindingstext" inherits="NumberFont_Outline_Large" justifyH="RIGHT" justifyV="TOP">
-          <Anchors>
-            <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeKey="$parent.bg" x="-12" y="7" />
-          </Anchors>
-          <Color a="1" r="0" g="1" b="0" />
-        </FontString>
-      </Layer>
-    </Layers>
-    <Frames>
-      <Button inherits="UIPanelCloseButton" parentKey="CloseButton">
-        <Anchors>
-          <Anchor point="TOPRIGHT" />
-        </Anchors>
-      </Button>
-
-      <CheckButton inherits="UICheckButtonTemplate" parentKey="DummyCheckButton">
-        <Anchors>
-          <Anchor point="BOTTOMLEFT" x="4" y="4" />
-        </Anchors>
-        <ButtonText text="This is some crap" />
-      </CheckButton>
-    </Frames>
-  </Frame>
-
-  <ScrollingMessageFrame hidden="true" fade="false"  name="KeyBinderImportLog" parent="KeyBinder" clampedToScreen="true" parentKey="ImportLog" insertMode="BOTTOM" maxLines="500">
-
-    <Scripts>
-      <OnLoad>
-        self:AddMessage('SkeletonKey import tool')
-      </OnLoad>
-      <OnMouseWheel>
-        if delta >= 0 then
-          if IsControlKeyDown() then
-            -- extremely janky but avoids having one line at the bottom
-            for i =1, self:GetMaxLines() do
-              self:ScrollUp()
-            end
-          end
-
-          return self:ScrollUp()
-        else
-
-          if IsControlKeyDown() then
-            return self:ScrollToBottom()
-          end
-
-          self:ScrollDown()
-        end
-      </OnMouseWheel>
-    </Scripts>
-    <Anchors>
-      <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="0" />
-      <Anchor point="BOTTOM" />
-    </Anchors>
-    <Size x="400" />
-    <Layers>
-      <Layer level="BACKGROUND">
-        <Texture setAllPoints="true">
-          <Color a="1" r="0" g="0" b="0" />
-        </Texture>
-      </Layer>
-    </Layers>
-    <FontString inherits="NumberFontNormal" justifyH="LEFT">
-
-      <Anchors>
-        <Anchor point="TOPLEFT" />
-      </Anchors>
-        </FontString>
-  </ScrollingMessageFrame>
-</Ui>
\ No newline at end of file
--- a/SkeletonKey/KeySlot.lua	Fri Jul 29 03:27:15 2016 -0400
+++ b/SkeletonKey/KeySlot.lua	Fri Jul 29 21:18:15 2016 -0400
@@ -2,7 +2,7 @@
 -- KeySlot.lua
 -- Created: 7/28/2016 11:26 PM
 -- %file-revision%
--- All the internal slot logic is kept here
+-- Code dealing with the slot button innards; they are invoked by frame script and should only chain to Set/Release
 
 local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot')
 local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION
@@ -11,7 +11,6 @@
 local BORDER_ASSIGNED = {1,1,1,1}
 local BORDER_DYNAMIC = {1,1,0,1}
 local BORDER_PENDING = {1,0.5,0,1 }
-
 local BUTTON_HEADERS = {
   ['spell'] = SPELLS,
   ['macro'] = MACRO,
@@ -444,6 +443,119 @@
 end
 
 
+--- Updates the current KeyBinding for the button's command
+kb.SaveSlot = function(self, key)
+
+  if not self.command then
+    return
+  end
+
+  if key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then
+    return
+  end
+  print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key)
+
+  local modifier = ''
+  if IsAltKeyDown() then
+    modifier = 'ALT-'
+  end
+  if IsControlKeyDown() then
+    modifier = modifier.. 'CTRL-'
+  end
+  if IsShiftKeyDown() then
+    modifier = modifier..'SHIFT-'
+  end
+  local binding = modifier..key
+
+  if key == 'ESCAPE' then
+    local keys = {GetBindingKey(self.command) }
+    --print('detected', #keys, 'bindings')
+    for i, key in pairs(keys) do
+      --print('clearing', key)
+      SetBinding(key, nil)
+      SaveBindings(GetCurrentBindingSet())
+      if kb.currentProfile.bindings[key] then
+        kb:print(L('BINDING_REMOVED', self.actionName, kb.configHeaders[db.bindMode]))
+        kb.currentProfile.bindings[key] = nil
+      end
+      if kb.currentProfile.talents[self.actionName] then
+        kb.currentProfile.talents[self.actionName] = nil
+      end
+      bindings[self.actionType][self.actionID] = nil
+    end
+    if kb.currentProfile.bound[self.command] then
+      kb.currentProfile.bound[self.command] = nil
+      --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode]))
+    end
+
+    self.active = false
+  else
+    if kb.SystemBinds[binding] then
+      kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, kb.SystemBinds[binding]))
+      return
+    end
+
+
+    if self.command then
+
+      local previousKeys
+      local previousAction = GetBindingAction(binding)
+      local binding1, binding2, new1, new2
+      print(type(previousAction), previousAction)
+      if previousAction ~= "" and previousAction ~= self.command then
+        if protected[previousAction] then
+          -- bounce out if trying to use a protected key
+          kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, GetBindingAction(binding)))
+          kb.bindingstext:SetText(nil)
+          return
+        else
+          kb:print('Discarding keybind for', previousAction)
+          -- todo: sort out retcon'd talent spells
+        end
+      end
+
+      self.binding = binding
+
+      SetBinding(self.binding, self.command)
+      SaveBindings(GetCurrentBindingSet())
+
+      local talentInfo
+      if self.actionType == 'spell' and kb.TalentCache[self.actionID] then
+        print('conditional binding (talent = "'..self.actionName..'")')
+        talentInfo = {self.macroName, self.actionName, self.actionType, self.actionID}
+        local bindings = {GetBindingKey(self.command) }
+        for i, key in ipairs(bindings) do
+          tinsert(talentInfo, key)
+        end
+      end
+
+      for level, profile in ipairs(kb.orderedProfiles) do
+        if (level == db.bindMode) then
+          profile.bound[self.command] = true
+          if talentInfo then
+            profile.bindings[self.binding] = nil
+          else
+            profile.bindings[self.binding] = self.command
+          end
+          profile.talents[self.actionName] = talentInfo
+        else
+          profile.bindings[self.binding] = nil
+          profile.bound[self.command] = nil
+          kb.currentProfile.talents[self.actionName] = nil
+        end
+        if kb.currentProfile.talents[self.actionID] then
+          kb.currentProfile.talents[self.actionID] = nil
+        end
+      end
+
+      kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.configHeaders[db.bindMode]))
+    end
+  end
+  kb.UpdateSlot(self, true)
+  KeyBinderSaveButton:Enable()
+end
+
+
 
 --- Add to blizzard interfaces
 StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = {
--- a/SkeletonKey/SkeletonKey.lua	Fri Jul 29 03:27:15 2016 -0400
+++ b/SkeletonKey/SkeletonKey.lua	Fri Jul 29 21:18:15 2016 -0400
@@ -36,37 +36,6 @@
 local BINDING_TYPE_SPECIALIZATION = 3
 local BINDING_TYPE_CHARACTER = 2
 local BINDING_TYPE_GLOBAL = 1
-
-
---- Caps Lock derivatives
-local ACTION_SCRIPT = {
-  ['mount'] = "/script C_MountJournal.SummonByID(%d)",
-  ['macro'] = "%s",
-  ['equipset'] = "/script UseEquipmentSet(%d)",
-  ['spell'] = "/cast %s",
-  ['petaction'] = "/cast %s",
-  ['battlepet'] = SLASH_SUMMON_BATTLE_PET1 .. " %s",
-  ['item'] = "/use %s"
-}
-
-
-local PETACTION_SCRIPT = {
-  [PET_ACTION_MOVE_TO] = SLASH_PET_MOVE_TO1,
-  [PET_ACTION_ATTACK] = SLASH_PET_ATTACK1,
-  [PET_ACTION_FOLLOW] = SLASH_PET_FOLLOW1,
-  [PET_ACTION_WAIT] = SLASH_PET_STAY1,
-  [PET_MODE_AGGRESSIVE] = SLASH_PET_AGGRESSIVE1,
-  [PET_MODE_DEFENSIVE] = SLASH_PET_DEFENSIVE1,
-  [PET_MODE_PASSIVE] = SLASH_PET_PASSIVE1,
-  [PET_MODE_ASSIST] = SLASH_PET_ASSIST1,
-}
-
-local professionMappings = {
-  [5] = 3,
-  [7] = 4,
-  [9] = 5,
-  [10] = 6
-}
 kb.configTitle = {
   [BINDING_TYPE_GLOBAL] = 'Global Binds',
   [BINDING_TYPE_CHARACTER] = 'Character: %s',
@@ -179,152 +148,8 @@
 end
 
 
---- Resolve the appropriate command and macroText for the given action parameters
-kb.RegisterAction = function(type, id, name)
-  local macroText, macroName, command = '', '', ''
 
-  if type == 'spell' then
-    if kb.ProfessionCache[id] then
-      command = CLICK_KEYBINDER_KEY .. "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum
-    else
-      command = CLICK_KEYBINDER_KEY ..name
-    end
-  else
-    macroName = type .. ' ' .. name
-    macroText = ACTION_SCRIPT[type]:format(name)
-    local baseName, iterative = macroName, 1
-    while (macros[macroName] and macros[macroName][1] ~= macroText) do
-      print(' * cannot use|cFF00FF00', macroName, '|r"'.. (macros[macroName][1] or '') .. '"')
-      macroName = baseName .. '_' .. iterative
-      iterative = iterative + 1
-    end
-    if macroName ~= baseName then
-      print(' * Creating|cFF00FF00', macroName)
-    else
-      print(' * Re-using|cFF00FF00', macroName)
-    end
-    command = 'CLICK KeyBinderMacro:'.. macroName
-    macros[macroName] = {macroText, command }
-  end
 
-  print('RegisterAction', type, id, '->', command , macroText)
-  return macroName, macroText, command
-end
-
---- Updates the current KeyBinding for the button's command
-kb.StoreBinding = function(self, key)
-
-  if not self.command then
-    return
-  end
-
-  if key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then
-    return
-  end
-  print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key)
-
-  local modifier = ''
-  if IsAltKeyDown() then
-    modifier = 'ALT-'
-  end
-  if IsControlKeyDown() then
-    modifier = modifier.. 'CTRL-'
-  end
-  if IsShiftKeyDown() then
-    modifier = modifier..'SHIFT-'
-  end
-  local binding = modifier..key
-
-  if key == 'ESCAPE' then
-    local keys = {GetBindingKey(self.command) }
-    --print('detected', #keys, 'bindings')
-    for i, key in pairs(keys) do
-      --print('clearing', key)
-      SetBinding(key, nil)
-      SaveBindings(GetCurrentBindingSet())
-      if kb.currentProfile.bindings[key] then
-        kb:print(L('BINDING_REMOVED', self.actionName, kb.configHeaders[db.bindMode]))
-        kb.currentProfile.bindings[key] = nil
-      end
-      if kb.currentProfile.talents[self.actionName] then
-        kb.currentProfile.talents[self.actionName] = nil
-      end
-      bindings[self.actionType][self.actionID] = nil
-    end
-    if kb.currentProfile.bound[self.command] then
-      kb.currentProfile.bound[self.command] = nil
-      --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode]))
-    end
-
-    bindsCommitted = false
-    self.active = false
-  else
-    if kb.SystemBinds[binding] then
-      kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, kb.SystemBinds[binding]))
-      return
-    end
-
-
-    if self.command then
-
-      local previousKeys
-      local previousAction = GetBindingAction(binding)
-      local binding1, binding2, new1, new2
-      print(type(previousAction), previousAction)
-      if previousAction ~= "" and previousAction ~= self.command then
-        if protected[previousAction] then
-          -- bounce out if trying to use a protected key
-          kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, GetBindingAction(binding)))
-          kb.bindingstext:SetText(nil)
-          return
-        else
-          kb:print('Discarding keybind for', previousAction)
-          -- todo: sort out retcon'd talent spells
-        end
-      end
-
-      self.pending = true
-      self.binding = binding
-
-      bindsCommitted = false
-      SetBinding(self.binding, self.command)
-      SaveBindings(GetCurrentBindingSet())
-
-      local talentInfo
-      if self.actionType == 'spell' and kb.TalentCache[self.actionID] then
-        print('conditional binding (talent = "'..self.actionName..'")')
-        talentInfo = {self.macroName, self.actionName, self.actionType, self.actionID}
-        local bindings = {GetBindingKey(self.command) }
-        for i, key in ipairs(bindings) do
-          tinsert(talentInfo, key)
-        end
-      end
-
-      for level, profile in ipairs(kb.orderedProfiles) do
-        if (level == db.bindMode) then
-          profile.bound[self.command] = true
-          if talentInfo then
-            profile.bindings[self.binding] = nil
-          else
-            profile.bindings[self.binding] = self.command
-          end
-          profile.talents[self.actionName] = talentInfo
-        else
-          profile.bindings[self.binding] = nil
-          profile.bound[self.command] = nil
-          kb.currentProfile.talents[self.actionName] = nil
-        end
-        if kb.currentProfile.talents[self.actionID] then
-          kb.currentProfile.talents[self.actionID] = nil
-        end
-      end
-
-      kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.configHeaders[db.bindMode]))
-    end
-  end
-  kb.UpdateSlot(self, true)
-  KeyBinderSaveButton:Enable()
-end
 
 
 kb.inactiveTalentBindings = {}
--- a/SkeletonKey/SkeletonKey.toc	Fri Jul 29 03:27:15 2016 -0400
+++ b/SkeletonKey/SkeletonKey.toc	Fri Jul 29 21:18:15 2016 -0400
@@ -11,7 +11,7 @@
 
 LibStub\LibStub.lua
 libKT-1.0\libKT-1.0.xml
-KeyBinds.xml
+SkeletonKey.xml
 SkeletonKey.lua
 Cache.lua
 BindingsUI.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SkeletonKey/SkeletonKey.xml	Fri Jul 29 21:18:15 2016 -0400
@@ -0,0 +1,257 @@
+<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">
+  <Button name="KeyBinderMacro" inherits="SecureActionButtonTemplate">
+    <Attributes>
+      <Attribute name="*type*" value="macro" />
+    </Attributes>
+  </Button>
+  <Button name="KeyBinderKey" inherits="SecureActionButtonTemplate" />
+  <CheckButton name="KeyButton" virtual="true">
+    <Size x="32" y="32" />
+    <Layers>
+      <Layer level="BACKGROUND">
+        <Texture parentKey="border" setAllPoints="true">
+          <Color a="1" r=".25" g=".25" b=".25" />
+        </Texture>
+      </Layer>
+      <Layer level="BORDER">
+
+        <Texture parentKey="bg">
+          <Anchors>
+            <Anchor point="TOPLEFT" x="2" y="-2" />
+            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
+          </Anchors>
+          <Color a="0.5" r="0" g="0" b="0" />
+        </Texture>
+      </Layer>
+      <Layer level="ARTWORK">
+        <Texture setAllPoints="true" parentKey="icon">
+          <Anchors>
+            <Anchor point="TOPLEFT" x="2" y="-2" />
+            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
+          </Anchors>
+
+          <TexCoords left="0.1" right="0.9" top="0.1" bottom="0.9" />
+
+        </Texture>
+      </Layer>
+      <Layer level="OVERLAY">
+        <FontString inherits="NumberFontNormal" parentKey="header" wordwrap="false" justifyH="LEFT">
+
+          <Anchors>
+            <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="-2" />
+            <Anchor point="RIGHT" x="128" y="0" />
+          </Anchors>
+        </FontString>
+        <FontString inherits="NumberFontNormal" parentKey="bind">
+          <Anchors>
+            <Anchor point="BOTTOMRIGHT" x="-2" y="2" />
+          </Anchors>
+        </FontString>
+        <FontString inherits="KTMacroButtonFont" parentKey="macro">
+          <Anchors>
+            <Anchor point="TOPLEFT" x="2" y="-2" />
+            <Anchor point="RIGHT" x="-2" y="0" />
+          </Anchors>
+        </FontString>
+        <FontString inherits="NumberFontNormal" parentKey="details" justifyH="LEFT">
+          <Anchors>
+            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" x="0" y="-2" relativeKey="$parent.header" />
+            <Anchor point="RIGHT" x="128" y="0" />
+          </Anchors>
+        </FontString>
+
+        <Texture parentKey="ignoreTexture" file="Interface\PaperDollInfoFrame\UI-GearManager-LeaveItem-Transparent" hidden="true">
+          <Anchors>
+            <Anchor point="TOPLEFT" x="0" y="0" />
+            <Anchor point="BOTTOMRIGHT" x="0" y="0" />
+          </Anchors>
+        </Texture>
+      </Layer>
+    </Layers>
+    <HighlightTexture file="Interface\BUTTONS\UI-Button-Outline" alphaMode="ADD">
+      <Anchors>
+        <Anchor point="TOPLEFT" x="-13" y="13" />
+        <Anchor point="BOTTOMRIGHT" x="13" y="-13" />
+      </Anchors>
+    </HighlightTexture>
+  </CheckButton>
+
+  <Frame name="KeyBinder" parent="UIParent" hidden="true" clampedToScreen="true" movable="true" enableMouse="true">
+    <Anchors>
+      <Anchor point="TOP" y="-25" x="0" />
+    </Anchors>
+    <Size x="600" y="200" />
+    <Scripts>
+      <OnLoad>
+        self:RegisterForDrag('LeftButton')
+      </OnLoad>
+      <OnShow>
+      </OnShow>
+      <OnDragStart>
+        self:StartMoving()
+      </OnDragStart>
+      <OnDragStop>
+        self:StopMovingOrSizing()
+      </OnDragStop>
+      <OnMouseWheel>
+        self:OnMouseWheel(delta)
+      </OnMouseWheel>
+      <OnHide>
+        self:OnHide()
+      </OnHide>
+    </Scripts>
+    <Layers>
+      <Layer level="BACKGROUND">
+
+        <Texture parentKey="info">
+          <Anchors>
+            <Anchor point="TOPLEFT" />
+            <Anchor point="RIGHT" />
+          </Anchors>
+          <Size y="42" />
+        </Texture>
+
+        <Texture parentKey="headerbg" alphaMode="MOD">
+          <Size y="32" />
+          <Anchors>
+            <Anchor point="TOPLEFT" />
+            <Anchor point="RIGHT" />
+          </Anchors>
+          <Color a="1" r="1" g="1" b="1" />
+          <Gradient orientation="VERTICAL">
+            <MinColor r="0" g="0" b="0"/>
+            <MaxColor r="1" g="1" b="1"/>
+          </Gradient>
+        </Texture>
+
+        <Texture parentKey="sourcesbg">
+          <Size x="100" />
+          <Anchors>
+            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.headerbg" />
+            <Anchor point="BOTTOM" />
+          </Anchors>
+          <Color a="1" r="0.2" g="0.2" b="0.2" />
+        </Texture>
+
+
+
+        <Texture parentKey="profilebg">
+          <Size  y="102" />
+          <Anchors>
+            <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.headerbg" />
+            <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" />
+            <Anchor point="RIGHT" />
+          </Anchors>
+          <Color a="1" r="0" g="0" b="0" />
+        </Texture>
+
+        <Texture parentKey="bg">
+          <Anchors>
+            <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.profilebg" />
+            <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" />
+          </Anchors>
+          <Color a="0.5" r="0" g="0" b="0" />
+        </Texture>
+
+        <Texture parentKey="footer">
+          <Size y="52" />
+          <Anchors>
+            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="0" />
+            <Anchor point="RIGHT"  />
+          </Anchors>
+          <Color a="1" r="0" g="0" b="0" />
+        </Texture>
+      </Layer>
+      <Layer level="OVERLAY">
+
+        <FontString inherits="KTHeaderFont" text="Bindings" parentKey="header">
+          <Anchors>
+            <Anchor point="TOPLEFT" />
+          </Anchors>
+        </FontString>
+
+        <FontString parentKey="profiletext" inherits="KTHeader2Font" justifyH="LEFT" text="Foobar">
+          <Anchors>
+            <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" relativeKey="$parent.header" x="8" y="5" />
+          </Anchors>
+          <Color a="1" r="1" g="0.7" b="0" />
+        </FontString>
+
+        <FontString parentKey="statustext" inherits="NumberFont_Outline_Large" justifyH="LEFT" justifyV="TOP">
+          <Anchors>
+            <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="12" y="7" />
+          </Anchors>
+        </FontString>
+
+
+        <FontString parentKey="bindingstext" inherits="NumberFont_Outline_Large" justifyH="RIGHT" justifyV="TOP">
+          <Anchors>
+            <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeKey="$parent.bg" x="-12" y="7" />
+          </Anchors>
+          <Color a="1" r="0" g="1" b="0" />
+        </FontString>
+      </Layer>
+    </Layers>
+    <Frames>
+      <Button inherits="UIPanelCloseButton" parentKey="CloseButton">
+        <Anchors>
+          <Anchor point="TOPRIGHT" />
+        </Anchors>
+      </Button>
+
+      <CheckButton inherits="UICheckButtonTemplate" parentKey="DummyCheckButton">
+        <Anchors>
+          <Anchor point="BOTTOMLEFT" x="4" y="4" />
+        </Anchors>
+        <ButtonText text="This is some crap" />
+      </CheckButton>
+    </Frames>
+  </Frame>
+
+  <ScrollingMessageFrame hidden="true" fade="false"  name="KeyBinderImportLog" parent="KeyBinder" clampedToScreen="true" parentKey="ImportLog" insertMode="BOTTOM" maxLines="500">
+
+    <Scripts>
+      <OnLoad>
+        self:AddMessage('SkeletonKey import tool')
+      </OnLoad>
+      <OnMouseWheel>
+        if delta >= 0 then
+          if IsControlKeyDown() then
+            -- extremely janky but avoids having one line at the bottom
+            for i =1, self:GetMaxLines() do
+              self:ScrollUp()
+            end
+          end
+
+          return self:ScrollUp()
+        else
+
+          if IsControlKeyDown() then
+            return self:ScrollToBottom()
+          end
+
+          self:ScrollDown()
+        end
+      </OnMouseWheel>
+    </Scripts>
+    <Anchors>
+      <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="0" />
+      <Anchor point="BOTTOM" />
+    </Anchors>
+    <Size x="400" />
+    <Layers>
+      <Layer level="BACKGROUND">
+        <Texture setAllPoints="true">
+          <Color a="1" r="0" g="0" b="0" />
+        </Texture>
+      </Layer>
+    </Layers>
+    <FontString inherits="NumberFontNormal" justifyH="LEFT">
+
+      <Anchors>
+        <Anchor point="TOPLEFT" />
+      </Anchors>
+        </FontString>
+  </ScrollingMessageFrame>
+</Ui>
\ No newline at end of file