Quantcast

Test commit from dev machine.

Daniel Yates [06-27-11 - 12:29]
Test commit from dev machine.
Filename
Core.lua
Modules/Auras.lua
Modules/AurasConfig.lua
Modules/Border.lua
Modules/BorderConfig.lua
Modules/Buttons.lua
Modules/ButtonsConfig.lua
Modules/Config.lua
Modules/TimerStacks.lua
Modules/TimerStacksConfig.lua
PowerAurasButtons.toc
diff --git a/Core.lua b/Core.lua
index bf8cb9c..8ee66b0 100644
--- a/Core.lua
+++ b/Core.lua
@@ -1,383 +1,383 @@
---[[
-	PowerAurasButtons
-
-	Module: Core
---]]
--- Make a frame for the core module.
-local CoreFrame        = CreateFrame("Frame", "PowerAurasButtons", UIParent);
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	__debug            Debugging flag. Set to true while debugging.
-	L                  Localization table.
-----------------------------------------------------------------------------------------------------
---]]
-local __debug          = nil;
-local L                = setmetatable({}, {__index=function(t,i) return i end});
---[[
-----------------------------------------------------------------------------------------------------
-Module Properties
-	BlizzEvents        Table of all registered Blizzard events, except ADDON_LOADED.
-	Events             Table of all registered module events and their listeners.
-	__debug            Debugging flag. Set to true while debugging. Accessible to all modules.
-	Modules            Table of all registered modules.
-	L                  Localization table. Accessible to all modules.
-----------------------------------------------------------------------------------------------------
---]]
-CoreFrame.BlizzEvents  = {};
-CoreFrame.Events       = {};
-CoreFrame.__debug      = __debug;
-CoreFrame.Modules      = {};
-CoreFrame.L            = L;
---[[
-----------------------------------------------------------------------------------------------------
-Debug
-
-Passes a call to Print if debugging is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:Debug(...)
-	-- Check debug flag.
-	if(__debug) then CoreFrame:Print(...); end
-end
---[[
-----------------------------------------------------------------------------------------------------
-Print
-
-Writes a line. Simple.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:Print(str, ...)
-	if(...) then
-		print(format("|cFF527FCCPower Auras Classic Buttons: |r" .. L[str], ...));
-	else
-		print("|cFF527FCCPower Auras Classic Buttons: |r" .. L[str]);
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-InitModule
-
-Initializes a module, effectively used to load it.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:InitModule(module)
-	CoreFrame:Debug("Initializing module: %s", module);
-	-- See if a frame with this modules name is attached.
-	if(not CoreFrame.Modules[module]) then
-		-- Module not found.
-		CoreFrame:Debug("|cFFC41F3BModule not found: |c%s", module);
-		return;
-	end
-	-- Make sure it hasn't already been loaded.
-	if(CoreFrame.Modules[module].Loaded) then return true; end
-	if(CoreFrame.Modules[module].Failed) then return; end
-	-- Load any dependencies.
-	if(not CoreFrame:InitModuleDeps(module)) then
-		-- Dependency failure..
-		CoreFrame:Debug("|cFFC41F3BDependencies failure for module: |c%s", module);
-		return;
-	end
-	-- Initialize it.
-	if(CoreFrame.Modules[module]:OnInitialize()) then
-		-- Toggle the loaded field to true.
-		CoreFrame.Modules[module].Loaded = true;
-		CoreFrame:FireModuleEvent("OnModuleLoaded", module);
-		CoreFrame:Debug("Initialized module: %s", module);
-		return true;
-	else
-		CoreFrame.Modules[module].Failed = true;
-		CoreFrame:Debug("|cFFC41F3BFailed to initialize module: |c%s", module);
-		return;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-InitModuleDeps
-
-Initializes any dependencies for the module. Returns nil if a dependency failed to load.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:InitModuleDeps(module)
-	-- Get the dependencies.
-	local deps = CoreFrame.Modules[module].Deps;
-	CoreFrame:Debug("Initializing module dependencies for: %s (%s dependencies)", module, #(deps));
-	-- If there's none, return already.
-	if(#(deps) == 0) then return true; end
-	-- Attempt to load the dependencies.
-	for _, dep in pairs(deps) do
-		-- If one fails to load, it's the end.
-		if(not CoreFrame:InitModule(dep)) then return; end
-	end
-	-- Loaded.
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-InitAllModules
-
-Initializes all unloaded registered modules.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:InitAllModules()
-	-- Go forth.
-	for module, _ in pairs(CoreFrame.Modules) do
-		-- Initialize.
-		CoreFrame:InitModule(module);
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterModule
-
-Registers a module - called so that InitModule knows what frames to initialize.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:RegisterModule(name, deps, canDisable)
-	CoreFrame:Debug("Registering module: %s", name);
-	-- Don't re-register modules.
-	if(CoreFrame.Modules[name]) then
-		-- Module already registered.
-		CoreFrame:Debug("|cFFC41F3BModule already registered: |c%s", name);
-		return;
-	end
-	-- Create.
-	local module = CreateFrame("Frame", nil, CoreFrame);
-	-- local module = {};
-	-- Sort out fields/properties.
-	module.Name = name;
-	module.Loaded = nil;
-	module.Failed = nil;
-	module.CanDisable = canDisable or nil;
-	module.Deps = deps or {};
-	-- Register and return.
-	CoreFrame.Modules[name] = module;
-	return module;
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsModuleEnabled
-
-Checks if a module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:IsModuleEnabled(name)
-	-- Is it?
-	if(CoreFrame.Modules[name]) then
-		-- Enabled.
-		return CoreFrame.Modules[name]:IsEnabled();
-	else
-		-- Nope...
-		return nil;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsModuleLoaded
-
-Checks if a module is loaded.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:IsModuleLoaded(name)
-	-- Is it?
-	if(CoreFrame.Modules[name]) then
-		-- Enabled.
-		return CoreFrame.Modules[name].Loaded;
-	else
-		-- Nope...
-		return nil;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterModuleEvent
-
-Registers a module event. Any module can call these events, by default.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:RegisterModuleEvent(event)
-	CoreFrame:Debug("Registering module event: %s", event);
-	-- Attach.
-	CoreFrame.Events[event] = CoreFrame.Events[event] or {};
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterModuleEventListener
-
-Adds an event listener to a given event name.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:RegisterModuleEventListener(event, frame, func)
-	CoreFrame:Debug("Registering module event listener for event: %s", event);
-	-- Event needs to exist.
-	if(not CoreFrame.Events[event]) then
-		CoreFrame.Events[event] = {};
-	end
-	-- Attach.
-	tinsert(CoreFrame.Events[event], func or frame[event]);
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterBlizzEventListener
-
-Adds an event listener to a given event name.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:RegisterBlizzEventListener(event, frame, func)
-	CoreFrame:Debug("Registering blizzard event listener for event: %s", event);
-	-- Event needs to exist.
-	if(not CoreFrame.BlizzEvents[event]) then
-		CoreFrame:RegisterEvent(event);
-		CoreFrame.BlizzEvents[event] = {};
-	end
-	-- Attach.
-	tinsert(CoreFrame.BlizzEvents[event], func or frame[event]);
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-FireModuleEvent
-
-Fires a module event.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:FireModuleEvent(event, ...)
-	-- Event needs to exist.
-	if(not CoreFrame.Events[event]) then
-		-- Event not found.
-		CoreFrame:Debug("|cFFC41F3BEvent not found: |c%s", event);
-		return;
-	end
-	-- Fire.
-	for k,func in pairs(CoreFrame.Events[event]) do
-		func(self, ...);
-	end
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-FireBlizzEvent
-
-Fires a blizzard event.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:FireBlizzEvent(event, ...)
-	CoreFrame:Debug("Firing blizzard event: %s", event);
-	-- Event needs to exist.
-	if(not CoreFrame.BlizzEvents[event]) then
-		-- Event not found.
-		CoreFrame:Debug("Blizzard event not found: %s", event);
-		return;
-	end
-	-- Fire.
-	for k,func in pairs(CoreFrame.BlizzEvents[event]) do
-		func(self, ...);
-	end
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetSetting
-
-Retrieves a setting from the database.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:GetSetting(setting)
-	-- Go forth.
-	return PowerAurasButtons_SettingsDB[setting];
-end
---[[
-----------------------------------------------------------------------------------------------------
-SetSetting
-
-Sets a setting into the database.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:SetSetting(setting, value)
-	-- Go forth.
-	PowerAurasButtons_SettingsDB[setting] = value;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetModuleSetting
-
-Retrieves a setting from the database for a specific module.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:GetModuleSetting(module, setting)
-	-- Go forth.
-	return PowerAurasButtons_SettingsDB[module][setting];
-end
---[[
-----------------------------------------------------------------------------------------------------
-SetModuleSetting
-
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:SetModuleSetting(module, setting, value)
-	-- Go forth.
-	PowerAurasButtons_SettingsDB[module][setting] = value;
-end
---[[
-----------------------------------------------------------------------------------------------------
-FixSettings
-
-Fixes all saved variables and migrates older ones across.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:FixSettings()
-	-- Make sure they're all set. In the case of SettingsDB, add defaults (hence why it's a func).
-	if(not PowerAurasButtons_AurasDB) then PowerAurasButtons_AurasDB = {}; end
-	if(not PowerAurasButtons_CharacterAurasDB) then PowerAurasButtons_CharacterAurasDB = {}; end
-	-- Table for defaults.
-	if(not PowerAurasButtons_SettingsDB) then
-		-- Modules store their own config in here.
-		PowerAurasButtons_SettingsDB = {};
-		-- Fix module settings too.
-		for module, frame in pairs(CoreFrame.Modules) do
-			if(frame.FixSettings) then
-				frame:FixSettings(true);
-			end
-		end
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-Events
-
-Required Events:
-	ADDON_LOADED
-----------------------------------------------------------------------------------------------------
---]]
-CoreFrame:RegisterEvent("ADDON_LOADED");
---[[
-----------------------------------------------------------------------------------------------------
-Event Handler
-
-Handles the aforementioned events.
-----------------------------------------------------------------------------------------------------
---]]
-function CoreFrame:OnEvent(event, ...)
-	-- Check events (DAMN YOU NEW FEATURES!)
-	if(event == "ADDON_LOADED") then
-		-- Make sure we're the loaded one.
-		if(... == "PowerAurasButtons") then
-			-- Fix config first.
-			CoreFrame:FixSettings();
-			-- Create an epic event.
-			CoreFrame:RegisterModuleEvent("OnModuleLoaded");
-			-- Debugging message.
-			CoreFrame:Debug("Initializing modules");
-			-- Initialize core modules.
-			CoreFrame:InitAllModules();
-			CoreFrame:Debug("Modules initialized");
-		end
-	elseif(CoreFrame.BlizzEvents[event]) then
-		-- Fire all handlers.
-		CoreFrame:FireBlizzEvent(event, ...);
-	end
-end
--- Register.
+--[[
+	PowerAurasButtons
+
+	Module: Core
+--]]
+-- Make a frame for the core module.
+local CoreFrame        = CreateFrame("Frame", "PowerAurasButtons", UIParent);
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	__debug            Debugging flag. Set to true while debugging.
+	L                  Localization table.
+----------------------------------------------------------------------------------------------------
+--]]
+local __debug          = nil;
+local L                = setmetatable({}, {__index=function(t,i) return i end});
+--[[
+----------------------------------------------------------------------------------------------------
+Module Properties
+	BlizzEvents        Table of all registered Blizzard events, except ADDON_LOADED.
+	Events             Table of all registered module events and their listeners.
+	__debug            Debugging flag. Set to true while debugging. Accessible to all modules.
+	Modules            Table of all registered modules.
+	L                  Localization table. Accessible to all modules.
+----------------------------------------------------------------------------------------------------
+--]]
+CoreFrame.BlizzEvents  = {};
+CoreFrame.Events       = {};
+CoreFrame.__debug      = __debug;
+CoreFrame.Modules      = {};
+CoreFrame.L            = L;
+--[[
+----------------------------------------------------------------------------------------------------
+Debug
+
+Passes a call to Print if debugging is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:Debug(...)
+	-- Check debug flag.
+	if(__debug) then CoreFrame:Print(...); end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+Print
+
+Writes a line. Simple.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:Print(str, ...)
+	if(...) then
+		print(format("|cFF527FCCPower Auras Classic Buttons: |r" .. L[str], ...));
+	else
+		print("|cFF527FCCPower Auras Classic Buttons: |r" .. L[str]);
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+InitModule
+
+Initializes a module, effectively used to load it.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:InitModule(module)
+	CoreFrame:Debug("Initializing module: %s", module);
+	-- See if a frame with this modules name is attached.
+	if(not CoreFrame.Modules[module]) then
+		-- Module not found.
+		CoreFrame:Debug("|cFFC41F3BModule not found: |c%s", module);
+		return;
+	end
+	-- Make sure it hasn't already been loaded.
+	if(CoreFrame.Modules[module].Loaded) then return true; end
+	if(CoreFrame.Modules[module].Failed) then return; end
+	-- Load any dependencies.
+	if(not CoreFrame:InitModuleDeps(module)) then
+		-- Dependency failure..
+		CoreFrame:Debug("|cFFC41F3BDependencies failure for module: |c%s", module);
+		return;
+	end
+	-- Initialize it.
+	if(CoreFrame.Modules[module]:OnInitialize()) then
+		-- Toggle the loaded field to true.
+		CoreFrame.Modules[module].Loaded = true;
+		CoreFrame:FireModuleEvent("OnModuleLoaded", module);
+		CoreFrame:Debug("Initialized module: %s", module);
+		return true;
+	else
+		CoreFrame.Modules[module].Failed = true;
+		CoreFrame:Debug("|cFFC41F3BFailed to initialize module: |c%s", module);
+		return;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+InitModuleDeps
+
+Initializes any dependencies for the module. Returns nil if a dependency failed to load.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:InitModuleDeps(module)
+	-- Get the dependencies.
+	local deps = CoreFrame.Modules[module].Deps;
+	CoreFrame:Debug("Initializing module dependencies for: %s (%s dependencies)", module, #(deps));
+	-- If there's none, return already.
+	if(#(deps) == 0) then return true; end
+	-- Attempt to load the dependencies.
+	for _, dep in pairs(deps) do
+		-- If one fails to load, it's the end.
+		if(not CoreFrame:InitModule(dep)) then return; end
+	end
+	-- Loaded.
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+InitAllModules
+
+Initializes all unloaded registered modules.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:InitAllModules()
+	-- Go forth.
+	for module, _ in pairs(CoreFrame.Modules) do
+		-- Initialize.
+		CoreFrame:InitModule(module);
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterModule
+
+Registers a module - called so that InitModule knows what frames to initialize.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:RegisterModule(name, deps, canDisable)
+	CoreFrame:Debug("Registering module: %s", name);
+	-- Don't re-register modules.
+	if(CoreFrame.Modules[name]) then
+		-- Module already registered.
+		CoreFrame:Debug("|cFFC41F3BModule already registered: |c%s", name);
+		return;
+	end
+	-- Create.
+	local module = CreateFrame("Frame", nil, CoreFrame);
+	-- local module = {};
+	-- Sort out fields/properties.
+	module.Name = name;
+	module.Loaded = nil;
+	module.Failed = nil;
+	module.CanDisable = canDisable or nil;
+	module.Deps = deps or {};
+	-- Register and return.
+	CoreFrame.Modules[name] = module;
+	return module;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsModuleEnabled
+
+Checks if a module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:IsModuleEnabled(name)
+	-- Is it?
+	if(CoreFrame.Modules[name]) then
+		-- Enabled.
+		return CoreFrame.Modules[name]:IsEnabled();
+	else
+		-- Nope...
+		return nil;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsModuleLoaded
+
+Checks if a module is loaded.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:IsModuleLoaded(name)
+	-- Is it?
+	if(CoreFrame.Modules[name]) then
+		-- Enabled.
+		return CoreFrame.Modules[name].Loaded;
+	else
+		-- Nope...
+		return nil;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterModuleEvent
+
+Registers a module event. Any module can call these events, by default.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:RegisterModuleEvent(event)
+	CoreFrame:Debug("Registering module event: %s", event);
+	-- Attach.
+	CoreFrame.Events[event] = CoreFrame.Events[event] or {};
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterModuleEventListener
+
+Adds an event listener to a given event name.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:RegisterModuleEventListener(event, frame, func)
+	CoreFrame:Debug("Registering module event listener for event: %s", event);
+	-- Event needs to exist.
+	if(not CoreFrame.Events[event]) then
+		CoreFrame.Events[event] = {};
+	end
+	-- Attach.
+	tinsert(CoreFrame.Events[event], func or frame[event]);
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterBlizzEventListener
+
+Adds an event listener to a given event name.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:RegisterBlizzEventListener(event, frame, func)
+	CoreFrame:Debug("Registering blizzard event listener for event: %s", event);
+	-- Event needs to exist.
+	if(not CoreFrame.BlizzEvents[event]) then
+		CoreFrame:RegisterEvent(event);
+		CoreFrame.BlizzEvents[event] = {};
+	end
+	-- Attach.
+	tinsert(CoreFrame.BlizzEvents[event], func or frame[event]);
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FireModuleEvent
+
+Fires a module event.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:FireModuleEvent(event, ...)
+	-- Event needs to exist.
+	if(not CoreFrame.Events[event]) then
+		-- Event not found.
+		CoreFrame:Debug("|cFFC41F3BEvent not found: |c%s", event);
+		return;
+	end
+	-- Fire.
+	for k,func in pairs(CoreFrame.Events[event]) do
+		func(self, ...);
+	end
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FireBlizzEvent
+
+Fires a blizzard event.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:FireBlizzEvent(event, ...)
+	CoreFrame:Debug("Firing blizzard event: %s", event);
+	-- Event needs to exist.
+	if(not CoreFrame.BlizzEvents[event]) then
+		-- Event not found.
+		CoreFrame:Debug("Blizzard event not found: %s", event);
+		return;
+	end
+	-- Fire.
+	for k,func in pairs(CoreFrame.BlizzEvents[event]) do
+		func(self, ...);
+	end
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetSetting
+
+Retrieves a setting from the database.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:GetSetting(setting)
+	-- Go forth.
+	return PowerAurasButtons_SettingsDB[setting];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SetSetting
+
+Sets a setting into the database.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:SetSetting(setting, value)
+	-- Go forth.
+	PowerAurasButtons_SettingsDB[setting] = value;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetModuleSetting
+
+Retrieves a setting from the database for a specific module.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:GetModuleSetting(module, setting)
+	-- Go forth.
+	return PowerAurasButtons_SettingsDB[module][setting];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SetModuleSetting
+
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:SetModuleSetting(module, setting, value)
+	-- Go forth.
+	PowerAurasButtons_SettingsDB[module][setting] = value;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FixSettings
+
+Fixes all saved variables and migrates older ones across.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:FixSettings()
+	-- Make sure they're all set. In the case of SettingsDB, add defaults (hence why it's a func).
+	if(not PowerAurasButtons_AurasDB) then PowerAurasButtons_AurasDB = {}; end
+	if(not PowerAurasButtons_CharacterAurasDB) then PowerAurasButtons_CharacterAurasDB = {}; end
+	-- Table for defaults.
+	if(not PowerAurasButtons_SettingsDB) then
+		-- Modules store their own config in here.
+		PowerAurasButtons_SettingsDB = {};
+		-- Fix module settings too.
+		for module, frame in pairs(CoreFrame.Modules) do
+			if(frame.FixSettings) then
+				frame:FixSettings(true);
+			end
+		end
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+Events
+
+Required Events:
+	ADDON_LOADED
+----------------------------------------------------------------------------------------------------
+--]]
+CoreFrame:RegisterEvent("ADDON_LOADED");
+--[[
+----------------------------------------------------------------------------------------------------
+Event Handler
+
+Handles the aforementioned events.
+----------------------------------------------------------------------------------------------------
+--]]
+function CoreFrame:OnEvent(event, ...)
+	-- Check events (DAMN YOU NEW FEATURES!)
+	if(event == "ADDON_LOADED") then
+		-- Make sure we're the loaded one.
+		if(... == "PowerAurasButtons") then
+			-- Fix config first.
+			CoreFrame:FixSettings();
+			-- Create an epic event.
+			CoreFrame:RegisterModuleEvent("OnModuleLoaded");
+			-- Debugging message.
+			CoreFrame:Debug("Initializing modules");
+			-- Initialize core modules.
+			CoreFrame:InitAllModules();
+			CoreFrame:Debug("Modules initialized");
+		end
+	elseif(CoreFrame.BlizzEvents[event]) then
+		-- Fire all handlers.
+		CoreFrame:FireBlizzEvent(event, ...);
+	end
+end
+-- Register.
 CoreFrame:SetScript("OnEvent", CoreFrame.OnEvent);
\ No newline at end of file
diff --git a/Modules/Auras.lua b/Modules/Auras.lua
index 1d064b6..9a583ac 100644
--- a/Modules/Auras.lua
+++ b/Modules/Auras.lua
@@ -1,289 +1,289 @@
---[[
-	PowerAurasButtons
-
-	Module: Auras
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("Auras");
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	ActiveAuras        Stores a list of auras alongside their associated action data tables.
-	BlizzAuras         Stores a list of active spell overlays fired by Blizzard's spell events.
-----------------------------------------------------------------------------------------------------
---]]
-local ActiveAuras      = {};
-local BlizzAuras       = {};
---[[
-----------------------------------------------------------------------------------------------------
-OnAuraShow
-
-Triggered when an aura shows. Adds the aura to the active list and triggers a button update.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnAuraShow(auraID)
-	-- Only continue if we have an aura ID.
-	if(not auraID or (PowaAuras.Auras[auraID] and PowaAuras.Auras[auraID].off)) then return; end
-	-- In addition, if this aura is already active then don't reshow it.
-	if(ModuleFrame:IsAuraShown(auraID)) then return; end
-	-- It needs actions to be shown.
-	local actions = ModuleFrame:GetAuraActions(auraID);
-	if(not actions or #(actions) == 0) then
-		return;
-	end
-	-- Register as active.
-	ActiveAuras[auraID] = true;
-	-- Right, fire events.
-	CoreFrame:FireModuleEvent("OnAuraShow", auraID);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnAuraHide
-
-Triggered when an aura hides. Removes the aura from the list and triggers a button update.
-The secondary aura argument is ignored.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnAuraHide(aura)
-	-- Continue if there is a valid aura passed.
-	if(not aura) then return; end
-	-- In addition, if this aura is already NOT active then don't bother updating.
-	if(not ModuleFrame:IsAuraShown(aura.id)) then return; end
-	-- Register as active.
-	ActiveAuras[aura.id] = nil;
-	-- Right, fire events.
-	CoreFrame:FireModuleEvent("OnAuraHide", aura.id);
-end
---[[
-----------------------------------------------------------------------------------------------------
-SPELL_ACTIVATION_OVERLAY_GLOW_SHOW
-
-Triggered when a blizzard aura shows. Adds the aura to the active list and triggers a button update.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:SPELL_ACTIVATION_OVERLAY_GLOW_SHOW(auraID)
-	-- No need to register twice.
-	if(BlizzAuras[auraID]) then return; end
-	-- Register as active. if the settings tell us to.
-	BlizzAuras[auraID] = true;
-	-- Right, fire events.
-	CoreFrame:FireModuleEvent("OnAuraShow", auraID);
-end
---[[
-----------------------------------------------------------------------------------------------------
-SPELL_ACTIVATION_OVERLAY_GLOW_HIDE
-
-Triggered when a blizzard aura hides. Removes the aura from the list and triggers a button update.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:SPELL_ACTIVATION_OVERLAY_GLOW_HIDE(auraID)
-	-- Only unregister if needed.
-	if(not BlizzAuras[auraID]) then return; end
-	-- Register as inactive.
-	BlizzAuras[auraID] = nil;
-	-- Right, fire events.
-	CoreFrame:FireModuleEvent("OnAuraHide", auraID);
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetActionTable
-
-Returns the listing from the ActionTable table which has the given key, or nil.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetActionTable(key)
-	return (key and ActionTable[key]) or (not key and ActionTable) or nil;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetAuras
-
-Retrieves all of active auras.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetAuras()
-	return ActiveAuras, BlizzAuras;
-end
---[[
-----------------------------------------------------------------------------------------------------
-ResetAuras
-
-Resets the active aura table and rescans currently active auras.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:ResetAuras()
-	-- Reset.
-	ActiveAuras = {};
-	-- Scan.
-	for i=1,360 do
-		if(PowaAuras.Auras[i] and PowaAuras.Auras[i].Showing) then
-			 ModuleFrame:OnAuraShow(i);
-		end
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsAuraShown
-
-Sees if a given aura ID is registered as being active.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsAuraShown(auraID)
-	-- Check it.
-	if(ActiveAuras[auraID]) then
-		return true;
-	else
-		return nil;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetAuraActions
-
-Retrieves all of the actions assigned to a specific aura ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetAuraActions(auraID)
-	-- Get the correct configuration table.
-	if(auraID > 120) then
-		-- Global config.
-		return PowerAurasButtons_AurasDB[auraID-120] or {};
-	else
-		-- Per-char config.
-		return PowerAurasButtons_CharacterAurasDB[auraID] or {};
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-SetAuraActions
-
-Sets a table of actions to the given aura ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:SetAuraActions(auraID, actions)
-	-- Get the correct configuration table.
-	if(auraID > 120) then
-		-- Global config.
-		PowerAurasButtons_AurasDB[auraID-120] = actions;
-	else
-		-- Per-char config.
-		PowerAurasButtons_CharacterAurasDB[auraID] = actions;
-	end
-	-- Done.
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetAuraAction
-
-Retrieves a single aura action.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetAuraAction(auraID, actionID)
-	-- Get the actions table and retrieve the index.
-	return ModuleFrame:GetAuraActions(auraID)[actionID];
-end
---[[
-----------------------------------------------------------------------------------------------------
-SetAuraAction
-
-Updates a single aura action.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:SetAuraAction(auraID, actionID, actionData)
-	-- Get the actions table.
-	local actions = ModuleFrame:GetAuraActions(auraID);
-	-- Write.
-	actions[actionID] = actionData;
-	-- Save.
-	ModuleFrame:SetAuraActions(auraID, actions);
-end
---[[
-----------------------------------------------------------------------------------------------------
-MergeAuraAction
-
-Merges two action data tables, toggling off switches to on.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:MergeAuraAction(actionTable, actionData)
-	-- Go over the data table.
-	if(not actionData) then return actionTable; end
-	for key, value in pairs(actionData) do
-		-- If the key is any of ours (type/id), ignore.
-		if(key ~= "type" and key ~= "id") then
-			-- Write.
-			actionTable[key] = actionTable[key] or actionData[key];
-		end
-	end
-	-- Done.
-	return actionTable;
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateAuraAction
-
-Adds a new action to the given aura ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateAuraAction(auraID)
-	-- Make sure it has actions.
-	local actions = ModuleFrame:GetAuraActions(auraID);
-	if(not actions) then actions = {}; end
-	-- Add the action.
-	tinsert(actions, { ["type"] = "spell", ["id"] = 0 });
-	-- Save.
-	ModuleFrame:SetAuraActions(auraID, actions);
-	-- Fire OnActionCreate.
-	CoreFrame:FireModuleEvent("OnActionCreate", auraID, #(actions));
-	-- Return the count of the actions.
-	return #(actions);
-end
---[[
-----------------------------------------------------------------------------------------------------
-RemoveAuraAction
-
-Removes an action from the given aura ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:RemoveAuraAction(auraID, actionID)
-	-- Get the actions.
-	local actions = ModuleFrame:GetAuraActions(auraID);
-	if(not actions) then actions = {}; end
-	-- Remove if possible.
-	tremove(actions, actionID);
-	-- Save.
-	ModuleFrame:SetAuraActions(auraID, actions);
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsEnabled
-
-Checks to see if the module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsEnabled()
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Hook Power Auras' aura hide/display mechanisms. Create events for them.
-	hooksecurefunc(PowaAuras, "DisplayAura", ModuleFrame.OnAuraShow);
-	hooksecurefunc(PowaAuras, "SetAuraHideRequest", ModuleFrame.OnAuraHide);
-	-- Register Blizzard aura events.
-	CoreFrame:RegisterBlizzEventListener("SPELL_ACTIVATION_OVERLAY_GLOW_SHOW", ModuleFrame);
-	CoreFrame:RegisterBlizzEventListener("SPELL_ACTIVATION_OVERLAY_GLOW_HIDE", ModuleFrame);
-	-- Make events.
-	CoreFrame:RegisterModuleEvent("OnActionCreate");
-	CoreFrame:RegisterModuleEvent("OnAuraShow");
-	CoreFrame:RegisterModuleEvent("OnAuraHide");
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: Auras
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("Auras");
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	ActiveAuras        Stores a list of auras alongside their associated action data tables.
+	BlizzAuras         Stores a list of active spell overlays fired by Blizzard's spell events.
+----------------------------------------------------------------------------------------------------
+--]]
+local ActiveAuras      = {};
+local BlizzAuras       = {};
+--[[
+----------------------------------------------------------------------------------------------------
+OnAuraShow
+
+Triggered when an aura shows. Adds the aura to the active list and triggers a button update.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnAuraShow(auraID)
+	-- Only continue if we have an aura ID.
+	if(not auraID or (PowaAuras.Auras[auraID] and PowaAuras.Auras[auraID].off)) then return; end
+	-- In addition, if this aura is already active then don't reshow it.
+	if(ModuleFrame:IsAuraShown(auraID)) then return; end
+	-- It needs actions to be shown.
+	local actions = ModuleFrame:GetAuraActions(auraID);
+	if(not actions or #(actions) == 0) then
+		return;
+	end
+	-- Register as active.
+	ActiveAuras[auraID] = true;
+	-- Right, fire events.
+	CoreFrame:FireModuleEvent("OnAuraShow", auraID);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnAuraHide
+
+Triggered when an aura hides. Removes the aura from the list and triggers a button update.
+The secondary aura argument is ignored.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnAuraHide(aura)
+	-- Continue if there is a valid aura passed.
+	if(not aura) then return; end
+	-- In addition, if this aura is already NOT active then don't bother updating.
+	if(not ModuleFrame:IsAuraShown(aura.id)) then return; end
+	-- Register as active.
+	ActiveAuras[aura.id] = nil;
+	-- Right, fire events.
+	CoreFrame:FireModuleEvent("OnAuraHide", aura.id);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SPELL_ACTIVATION_OVERLAY_GLOW_SHOW
+
+Triggered when a blizzard aura shows. Adds the aura to the active list and triggers a button update.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:SPELL_ACTIVATION_OVERLAY_GLOW_SHOW(auraID)
+	-- No need to register twice.
+	if(BlizzAuras[auraID]) then return; end
+	-- Register as active. if the settings tell us to.
+	BlizzAuras[auraID] = true;
+	-- Right, fire events.
+	CoreFrame:FireModuleEvent("OnAuraShow", auraID);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SPELL_ACTIVATION_OVERLAY_GLOW_HIDE
+
+Triggered when a blizzard aura hides. Removes the aura from the list and triggers a button update.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:SPELL_ACTIVATION_OVERLAY_GLOW_HIDE(auraID)
+	-- Only unregister if needed.
+	if(not BlizzAuras[auraID]) then return; end
+	-- Register as inactive.
+	BlizzAuras[auraID] = nil;
+	-- Right, fire events.
+	CoreFrame:FireModuleEvent("OnAuraHide", auraID);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetActionTable
+
+Returns the listing from the ActionTable table which has the given key, or nil.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetActionTable(key)
+	return (key and ActionTable[key]) or (not key and ActionTable) or nil;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetAuras
+
+Retrieves all of active auras.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetAuras()
+	return ActiveAuras, BlizzAuras;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+ResetAuras
+
+Resets the active aura table and rescans currently active auras.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:ResetAuras()
+	-- Reset.
+	ActiveAuras = {};
+	-- Scan.
+	for i=1,360 do
+		if(PowaAuras.Auras[i] and PowaAuras.Auras[i].Showing) then
+			 ModuleFrame:OnAuraShow(i);
+		end
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsAuraShown
+
+Sees if a given aura ID is registered as being active.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsAuraShown(auraID)
+	-- Check it.
+	if(ActiveAuras[auraID]) then
+		return true;
+	else
+		return nil;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetAuraActions
+
+Retrieves all of the actions assigned to a specific aura ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetAuraActions(auraID)
+	-- Get the correct configuration table.
+	if(auraID > 120) then
+		-- Global config.
+		return PowerAurasButtons_AurasDB[auraID-120] or {};
+	else
+		-- Per-char config.
+		return PowerAurasButtons_CharacterAurasDB[auraID] or {};
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SetAuraActions
+
+Sets a table of actions to the given aura ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:SetAuraActions(auraID, actions)
+	-- Get the correct configuration table.
+	if(auraID > 120) then
+		-- Global config.
+		PowerAurasButtons_AurasDB[auraID-120] = actions;
+	else
+		-- Per-char config.
+		PowerAurasButtons_CharacterAurasDB[auraID] = actions;
+	end
+	-- Done.
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetAuraAction
+
+Retrieves a single aura action.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetAuraAction(auraID, actionID)
+	-- Get the actions table and retrieve the index.
+	return ModuleFrame:GetAuraActions(auraID)[actionID];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+SetAuraAction
+
+Updates a single aura action.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:SetAuraAction(auraID, actionID, actionData)
+	-- Get the actions table.
+	local actions = ModuleFrame:GetAuraActions(auraID);
+	-- Write.
+	actions[actionID] = actionData;
+	-- Save.
+	ModuleFrame:SetAuraActions(auraID, actions);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+MergeAuraAction
+
+Merges two action data tables, toggling off switches to on.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:MergeAuraAction(actionTable, actionData)
+	-- Go over the data table.
+	if(not actionData) then return actionTable; end
+	for key, value in pairs(actionData) do
+		-- If the key is any of ours (type/id), ignore.
+		if(key ~= "type" and key ~= "id") then
+			-- Write.
+			actionTable[key] = actionTable[key] or actionData[key];
+		end
+	end
+	-- Done.
+	return actionTable;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateAuraAction
+
+Adds a new action to the given aura ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateAuraAction(auraID)
+	-- Make sure it has actions.
+	local actions = ModuleFrame:GetAuraActions(auraID);
+	if(not actions) then actions = {}; end
+	-- Add the action.
+	tinsert(actions, { ["type"] = "spell", ["id"] = 0 });
+	-- Save.
+	ModuleFrame:SetAuraActions(auraID, actions);
+	-- Fire OnActionCreate.
+	CoreFrame:FireModuleEvent("OnActionCreate", auraID, #(actions));
+	-- Return the count of the actions.
+	return #(actions);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RemoveAuraAction
+
+Removes an action from the given aura ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:RemoveAuraAction(auraID, actionID)
+	-- Get the actions.
+	local actions = ModuleFrame:GetAuraActions(auraID);
+	if(not actions) then actions = {}; end
+	-- Remove if possible.
+	tremove(actions, actionID);
+	-- Save.
+	ModuleFrame:SetAuraActions(auraID, actions);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsEnabled
+
+Checks to see if the module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsEnabled()
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Hook Power Auras' aura hide/display mechanisms. Create events for them.
+	hooksecurefunc(PowaAuras, "DisplayAura", ModuleFrame.OnAuraShow);
+	hooksecurefunc(PowaAuras, "SetAuraHideRequest", ModuleFrame.OnAuraHide);
+	-- Register Blizzard aura events.
+	CoreFrame:RegisterBlizzEventListener("SPELL_ACTIVATION_OVERLAY_GLOW_SHOW", ModuleFrame);
+	CoreFrame:RegisterBlizzEventListener("SPELL_ACTIVATION_OVERLAY_GLOW_HIDE", ModuleFrame);
+	-- Make events.
+	CoreFrame:RegisterModuleEvent("OnActionCreate");
+	CoreFrame:RegisterModuleEvent("OnAuraShow");
+	CoreFrame:RegisterModuleEvent("OnAuraHide");
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/AurasConfig.lua b/Modules/AurasConfig.lua
index 01dc8a6..3b2eedf 100644
--- a/Modules/AurasConfig.lua
+++ b/Modules/AurasConfig.lua
@@ -1,188 +1,188 @@
---[[
-	PowerAurasButtons
-
-	Module: AurasConfig
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("AurasConfig", { "Auras" });
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateConfigurationFrame
-
-Creates the configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateConfigurationFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Make the parent frame.
-	local ActionEditor = CreateFrame("Frame", nil, UIParent);
-	ActionEditor:SetHeight(110);
-	-- Add the appropriate elements to the editor frame. Start with type.
-	ActionEditor.TypeLabel = Modules.Config:CreateHeaderWidget("Action Type", ActionEditor, 0);
-	-- Type changing callback.
-	local typechange = function(self)
-		-- Go forth.
-		if(self == ActionEditor.TypeSpell) then
-			-- Enable the spell button.
-			ActionEditor.TypeSpell:Select();
-			ActionEditor.TypeItem:Deselect();
-			ActionEditor.TypeMacro:Deselect();
-			Modules.Config:UpdateActionData("type", "spell");
-		elseif(self == ActionEditor.TypeItem) then
-			-- Item button.
-			ActionEditor.TypeItem:Select();
-			ActionEditor.TypeSpell:Deselect();
-			ActionEditor.TypeMacro:Deselect();
-			Modules.Config:UpdateActionData("type", "item");
-		elseif(self == ActionEditor.TypeMacro) then
-			-- Macro button.
-			ActionEditor.TypeMacro:Select();
-			ActionEditor.TypeSpell:Deselect();
-			ActionEditor.TypeItem:Deselect();
-			Modules.Config:UpdateActionData("type", "macro");
-		end
-	end
-	-- Button #1: Spell.
-	ActionEditor.TypeSpell = Modules.Config:CreateButtonWidget(ActionEditor, "Spell",
-		"Interface\\GossipFrame\\TrainerGossipIcon");
-	ActionEditor.TypeSpell:SetPoint("TOP", ActionEditor, "TOP", -115, -25);
-	ActionEditor.TypeSpell:SetScript("OnClick", typechange);
-	-- Button #2: Item
-	ActionEditor.TypeItem = Modules.Config:CreateButtonWidget(ActionEditor, "Item",
-		"Interface\\GossipFrame\\VendorGossipIcon");
-	ActionEditor.TypeItem:SetPoint("TOP", ActionEditor, "TOP", 0, -25);
-	ActionEditor.TypeItem:SetScript("OnClick", typechange);
-	-- Button #3: Macro
-	ActionEditor.TypeMacro = Modules.Config:CreateButtonWidget(ActionEditor, "Macro",
-		"Interface\\GossipFrame\\BinderGossipIcon");
-	ActionEditor.TypeMacro:SetPoint("TOP", ActionEditor, "TOP", 115, -25);
-	ActionEditor.TypeMacro:SetScript("OnClick", typechange);
-
-	-- Action Name/ID.
-	ActionEditor.IDLabel = Modules.Config:CreateHeaderWidget("Action Name/ID", ActionEditor, -56);
-	-- Add in the amazing editbox.
-	ActionEditor.IDEditbox = CreateFrame("EditBox", nil, ActionEditor, "InputBoxTemplate");
-	ActionEditor.IDEditbox:SetPoint("TOP", ActionEditor, "TOP", 0, -81);
-	ActionEditor.IDEditbox:SetHeight(24);
-	ActionEditor.IDEditbox:SetWidth(225);
-	ActionEditor.IDEditbox:SetAutoFocus(false);
-	ActionEditor.IDEditbox:SetMultiLine(false);
-	-- Create a save script.
-	ActionEditor.IDEditbox.Save = function()
-		-- See if the contents are text or number.
-		local contents = tonumber(ActionEditor.IDEditbox:GetText(), 10);
-		if(not contents) then
-			-- Reset contents var.
-			contents = ActionEditor.IDEditbox:GetText();
-			-- Convert the text to an ID.
-			if(Modules.Config:GetCurrentActionData()["type"] == "spell") then
-				-- Easy.
-				contents = select(2, GetSpellBookItemInfo(contents));
-			elseif(Modules.Config:GetCurrentActionData()["type"] == "item") then
-				-- Not so easy.
-				local link = select(2, GetItemInfo(contents));
-				if(link) then
-					contents = tonumber(select(5, string.find(link,
-						"|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?"..
-						"(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?")), 10);
-				end
-			elseif(Modules.Config:GetCurrentActionData()["type"] == "macro") then
-				-- Easy.
-				contents = select(1, GetMacroIndexByName(contents));
-			end
-		end
-		-- Save.
-		if(type(contents) == "number") then
-			Modules.Config:UpdateActionData("id", contents);
-		else
-			CoreFrame:Print("Could not convert '%s' to an ID.", ActionEditor.IDEditbox:GetText());
-			Modules.Config:UpdateActionData("id", nil);
-		end
-		-- Clear focus.
-		ActionEditor.IDEditbox:ClearFocus();
-	end
-	-- Register scripts.
-	ActionEditor.IDEditbox:SetScript("OnEnterPressed", ActionEditor.IDEditbox.Save);
-	ActionEditor.IDEditbox:SetScript("OnEscapePressed", ActionEditor.IDEditbox.Save);
-
-	-- Tooltips (localization handled by the config module)
-	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeSpell, {
-		title = "Type: Spell",
-		text = "Select this to make this action affect the display of a spell button."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeItem, {
-		title = "Type: Item",
-		text = "Select this to make this action affect the display of an item button."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeMacro, {
-		title = "Type: Macro",
-		text = "Select this to make this action affect the display of a macro button."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.IDEditbox, {
-		title = "Action Name/ID",
-		text = "The name or ID or the spell, item or macro to alter the display of."
-	});
-
-	-- Add the necessary functions.
-	ActionEditor.UpdateAction = function(self, actionData)
-		-- Update the type buttons.
-		if(actionData["type"] and actionData["type"] == "spell") then
-			-- Enable the spell button.
-			ActionEditor.TypeSpell:Select();
-			ActionEditor.TypeItem:Deselect();
-			ActionEditor.TypeMacro:Deselect();
-		elseif(actionData["type"] and actionData["type"] == "item") then
-			-- Enable the item button.
-			ActionEditor.TypeItem:Select();
-			ActionEditor.TypeSpell:Deselect();
-			ActionEditor.TypeMacro:Deselect();
-		elseif(actionData["type"] and actionData["type"] == "macro") then
-			-- Enable the macro button.
-			ActionEditor.TypeMacro:Select();
-			ActionEditor.TypeSpell:Deselect();
-			ActionEditor.TypeItem:Deselect();
-		else
-			-- Enable no buttons.
-			ActionEditor.TypeSpell:Deselect();
-			ActionEditor.TypeItem:Deselect();
-			ActionEditor.TypeMacro:Deselect();
-		end
-		-- Update the editboxes.
-		if(actionData["id"] and actionData["type"] and actionData["type"] == "spell") then
-			-- Update the editbox.
-			ActionEditor.IDEditbox:SetText(GetSpellInfo(actionData["id"]) or actionData["id"]);
-			-- Update the editbox.
-		elseif(actionData["id"] and actionData["type"] and actionData["type"] == "item") then
-			ActionEditor.IDEditbox:SetText(GetItemInfo(actionData["id"]) or actionData["id"]);
-			-- Update the editbox.
-		elseif(actionData["id"] and actionData["type"] and actionData["type"] == "macro") then
-			-- Update the editbox.
-			ActionEditor.IDEditbox:SetText(GetMacroInfo(actionData["id"]) or actionData["id"]);
-		elseif(actionData["id"]) then
-			-- Just use the ID/Text.
-			ActionEditor.IDEditbox:SetText(actionData["id"]);
-		else
-			-- Clear the editbox.
-			ActionEditor.IDEditbox:SetText("");
-		end
-	end;
-
-	-- Done.
-	Modules.Config:RegisterActionConfigFrame(ActionEditor, 1);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Register module events for config frames.
-	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: AurasConfig
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("AurasConfig", { "Auras" });
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateConfigurationFrame
+
+Creates the configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateConfigurationFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Make the parent frame.
+	local ActionEditor = CreateFrame("Frame", nil, UIParent);
+	ActionEditor:SetHeight(110);
+	-- Add the appropriate elements to the editor frame. Start with type.
+	ActionEditor.TypeLabel = Modules.Config:CreateHeaderWidget("Action Type", ActionEditor, 0);
+	-- Type changing callback.
+	local typechange = function(self)
+		-- Go forth.
+		if(self == ActionEditor.TypeSpell) then
+			-- Enable the spell button.
+			ActionEditor.TypeSpell:Select();
+			ActionEditor.TypeItem:Deselect();
+			ActionEditor.TypeMacro:Deselect();
+			Modules.Config:UpdateActionData("type", "spell");
+		elseif(self == ActionEditor.TypeItem) then
+			-- Item button.
+			ActionEditor.TypeItem:Select();
+			ActionEditor.TypeSpell:Deselect();
+			ActionEditor.TypeMacro:Deselect();
+			Modules.Config:UpdateActionData("type", "item");
+		elseif(self == ActionEditor.TypeMacro) then
+			-- Macro button.
+			ActionEditor.TypeMacro:Select();
+			ActionEditor.TypeSpell:Deselect();
+			ActionEditor.TypeItem:Deselect();
+			Modules.Config:UpdateActionData("type", "macro");
+		end
+	end
+	-- Button #1: Spell.
+	ActionEditor.TypeSpell = Modules.Config:CreateButtonWidget(ActionEditor, "Spell",
+		"Interface\\GossipFrame\\TrainerGossipIcon");
+	ActionEditor.TypeSpell:SetPoint("TOP", ActionEditor, "TOP", -115, -25);
+	ActionEditor.TypeSpell:SetScript("OnClick", typechange);
+	-- Button #2: Item
+	ActionEditor.TypeItem = Modules.Config:CreateButtonWidget(ActionEditor, "Item",
+		"Interface\\GossipFrame\\VendorGossipIcon");
+	ActionEditor.TypeItem:SetPoint("TOP", ActionEditor, "TOP", 0, -25);
+	ActionEditor.TypeItem:SetScript("OnClick", typechange);
+	-- Button #3: Macro
+	ActionEditor.TypeMacro = Modules.Config:CreateButtonWidget(ActionEditor, "Macro",
+		"Interface\\GossipFrame\\BinderGossipIcon");
+	ActionEditor.TypeMacro:SetPoint("TOP", ActionEditor, "TOP", 115, -25);
+	ActionEditor.TypeMacro:SetScript("OnClick", typechange);
+
+	-- Action Name/ID.
+	ActionEditor.IDLabel = Modules.Config:CreateHeaderWidget("Action Name/ID", ActionEditor, -56);
+	-- Add in the amazing editbox.
+	ActionEditor.IDEditbox = CreateFrame("EditBox", nil, ActionEditor, "InputBoxTemplate");
+	ActionEditor.IDEditbox:SetPoint("TOP", ActionEditor, "TOP", 0, -81);
+	ActionEditor.IDEditbox:SetHeight(24);
+	ActionEditor.IDEditbox:SetWidth(225);
+	ActionEditor.IDEditbox:SetAutoFocus(false);
+	ActionEditor.IDEditbox:SetMultiLine(false);
+	-- Create a save script.
+	ActionEditor.IDEditbox.Save = function()
+		-- See if the contents are text or number.
+		local contents = tonumber(ActionEditor.IDEditbox:GetText(), 10);
+		if(not contents) then
+			-- Reset contents var.
+			contents = ActionEditor.IDEditbox:GetText();
+			-- Convert the text to an ID.
+			if(Modules.Config:GetCurrentActionData()["type"] == "spell") then
+				-- Easy.
+				contents = select(2, GetSpellBookItemInfo(contents));
+			elseif(Modules.Config:GetCurrentActionData()["type"] == "item") then
+				-- Not so easy.
+				local link = select(2, GetItemInfo(contents));
+				if(link) then
+					contents = tonumber(select(5, string.find(link,
+						"|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?"..
+						"(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?")), 10);
+				end
+			elseif(Modules.Config:GetCurrentActionData()["type"] == "macro") then
+				-- Easy.
+				contents = select(1, GetMacroIndexByName(contents));
+			end
+		end
+		-- Save.
+		if(type(contents) == "number") then
+			Modules.Config:UpdateActionData("id", contents);
+		else
+			CoreFrame:Print("Could not convert '%s' to an ID.", ActionEditor.IDEditbox:GetText());
+			Modules.Config:UpdateActionData("id", nil);
+		end
+		-- Clear focus.
+		ActionEditor.IDEditbox:ClearFocus();
+	end
+	-- Register scripts.
+	ActionEditor.IDEditbox:SetScript("OnEnterPressed", ActionEditor.IDEditbox.Save);
+	ActionEditor.IDEditbox:SetScript("OnEscapePressed", ActionEditor.IDEditbox.Save);
+
+	-- Tooltips (localization handled by the config module)
+	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeSpell, {
+		title = "Type: Spell",
+		text = "Select this to make this action affect the display of a spell button."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeItem, {
+		title = "Type: Item",
+		text = "Select this to make this action affect the display of an item button."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.TypeMacro, {
+		title = "Type: Macro",
+		text = "Select this to make this action affect the display of a macro button."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.IDEditbox, {
+		title = "Action Name/ID",
+		text = "The name or ID or the spell, item or macro to alter the display of."
+	});
+
+	-- Add the necessary functions.
+	ActionEditor.UpdateAction = function(self, actionData)
+		-- Update the type buttons.
+		if(actionData["type"] and actionData["type"] == "spell") then
+			-- Enable the spell button.
+			ActionEditor.TypeSpell:Select();
+			ActionEditor.TypeItem:Deselect();
+			ActionEditor.TypeMacro:Deselect();
+		elseif(actionData["type"] and actionData["type"] == "item") then
+			-- Enable the item button.
+			ActionEditor.TypeItem:Select();
+			ActionEditor.TypeSpell:Deselect();
+			ActionEditor.TypeMacro:Deselect();
+		elseif(actionData["type"] and actionData["type"] == "macro") then
+			-- Enable the macro button.
+			ActionEditor.TypeMacro:Select();
+			ActionEditor.TypeSpell:Deselect();
+			ActionEditor.TypeItem:Deselect();
+		else
+			-- Enable no buttons.
+			ActionEditor.TypeSpell:Deselect();
+			ActionEditor.TypeItem:Deselect();
+			ActionEditor.TypeMacro:Deselect();
+		end
+		-- Update the editboxes.
+		if(actionData["id"] and actionData["type"] and actionData["type"] == "spell") then
+			-- Update the editbox.
+			ActionEditor.IDEditbox:SetText(GetSpellInfo(actionData["id"]) or actionData["id"]);
+			-- Update the editbox.
+		elseif(actionData["id"] and actionData["type"] and actionData["type"] == "item") then
+			ActionEditor.IDEditbox:SetText(GetItemInfo(actionData["id"]) or actionData["id"]);
+			-- Update the editbox.
+		elseif(actionData["id"] and actionData["type"] and actionData["type"] == "macro") then
+			-- Update the editbox.
+			ActionEditor.IDEditbox:SetText(GetMacroInfo(actionData["id"]) or actionData["id"]);
+		elseif(actionData["id"]) then
+			-- Just use the ID/Text.
+			ActionEditor.IDEditbox:SetText(actionData["id"]);
+		else
+			-- Clear the editbox.
+			ActionEditor.IDEditbox:SetText("");
+		end
+	end;
+
+	-- Done.
+	Modules.Config:RegisterActionConfigFrame(ActionEditor, 1);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Register module events for config frames.
+	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/Border.lua b/Modules/Border.lua
index 982a227..329debf 100644
--- a/Modules/Border.lua
+++ b/Modules/Border.lua
@@ -1,158 +1,158 @@
---[[
-	PowerAurasButtons
-
-	Module: Border
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("Border", { "Buttons" }, true);
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	ButtonBorders      Stores a table of buttons and their border data.
-	EnabledButtons     Stores a table of all buttons with active borders - we use this to hide them
-	                   when the button goes inactive/no longer needs a border.
-----------------------------------------------------------------------------------------------------
---]]
-local ButtonBorders    = {};
-local EnabledButtons   = {};
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonUpdate
-
-Fired when a button is updated. Used to draw the border.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonUpdate(buttonID)
-	-- Get the button and border object.
-	local button = _G[buttonID];
-	local border = button:GetCheckedTexture();
-	-- Only color if it's a button we're supposed to process.
-	if(ButtonBorders[buttonID] and ButtonBorders[buttonID][1]) then
-		-- Set the color.
-		button:SetChecked(true);
-		-- Set the new color.
-		border:SetVertexColor(unpack(ButtonBorders[buttonID][2]));
-		border:Show();
-	elseif(EnabledButtons[buttonID]) then
-		-- Disable this button.
-		border:SetVertexColor(1, 1, 1, 1);
-		button:SetChecked(false);
-		EnabledButtons[buttonID] = nil;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonProcess
-
-Resets the displayed auras for a specific button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonProcess(buttonID)
-	-- Wipe.
-	if(ButtonBorders[buttonID]) then
-		wipe(ButtonBorders[buttonID]);
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonDisplayAura
-
-Adds the displayed aura to the list of active auras for the given button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonDisplayAura(buttonID, auraID, actionData)
-	-- Add this aura if we need to.
-	if(not actionData["border"]) then return; end
-	if(not ButtonBorders[buttonID]) then ButtonBorders[buttonID] = {}; end
-	-- Calculate.
-	if(not ButtonBorders[buttonID][1] or
-	(actionData["border_priority"] or 25) > (ButtonBorders[buttonID][1] or 25)) then
-		-- Make sure it's enabled.
-		EnabledButtons[buttonID] = true;
-		-- It's a higher priority than the currently recorded one.
-		ButtonBorders[buttonID][1] = actionData["border_priority"] or 25;
-		ButtonBorders[buttonID][2] = actionData["border_color"] or { 1, 1, 1, 1 };
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnActionCreate
-
-Fired when an action is created. Used to set defaults in the newly made action ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnActionCreate(auraID, actionID)
-	-- Get action.
-	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
-	-- Write.
-	actionData["border"] = nil;
-	actionData["border_priority"] = 25;
-	actionData["border_color"] = { 1, 1, 1, 1 };
-	-- Save.
-	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsEnabled
-
-Checks to see if the module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsEnabled()
-	return CoreFrame:GetModuleSetting("Border", "Enabled");
-end
---[[
-----------------------------------------------------------------------------------------------------
-FixSettings
-
-Fixes all saved variables and migrates older ones across.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FixSettings(force)
-	-- Do the module settings exist?
-	if(not CoreFrame:GetSetting("Border") or force) then
-		-- We'd best fix that then.
-		PowerAurasButtons_SettingsDB["Border"] = {
-			["Enabled"] = true
-		};
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Fix settings first.
-	ModuleFrame:FixSettings();
-	-- Make sure enabled.
-	if(not ModuleFrame:IsEnabled()) then
-		-- Count as an unsuccessful module load.
-		return nil;
-	end
-	-- Register Blizzard button/LAB stuff.
-	if(LibStub) then
-		local LAB = LibStub("LibActionButton-1.0", true);
-		if(LAB) then
-			-- Add a button update hook.
-			LAB:RegisterCallback("OnButtonState", function(_, button)
-				ModuleFrame:OnButtonUpdate(button:GetName());
-			end);
-		end
-	end
-	-- Aaand the Blizzard hook.
-	hooksecurefunc("ActionButton_UpdateState", function(button)
-		ModuleFrame:OnButtonUpdate(button:GetName());
-	end);
-	-- Register module events for aura showing/hiding and button updates.
-	CoreFrame:RegisterModuleEventListener("OnButtonProcess", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnButtonDisplayAura", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnButtonUpdate", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: Border
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("Border", { "Buttons" }, true);
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	ButtonBorders      Stores a table of buttons and their border data.
+	EnabledButtons     Stores a table of all buttons with active borders - we use this to hide them
+	                   when the button goes inactive/no longer needs a border.
+----------------------------------------------------------------------------------------------------
+--]]
+local ButtonBorders    = {};
+local EnabledButtons   = {};
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonUpdate
+
+Fired when a button is updated. Used to draw the border.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonUpdate(buttonID)
+	-- Get the button and border object.
+	local button = _G[buttonID];
+	local border = button:GetCheckedTexture();
+	-- Only color if it's a button we're supposed to process.
+	if(ButtonBorders[buttonID] and ButtonBorders[buttonID][1]) then
+		-- Set the color.
+		button:SetChecked(true);
+		-- Set the new color.
+		border:SetVertexColor(unpack(ButtonBorders[buttonID][2]));
+		border:Show();
+	elseif(EnabledButtons[buttonID]) then
+		-- Disable this button.
+		border:SetVertexColor(1, 1, 1, 1);
+		button:SetChecked(false);
+		EnabledButtons[buttonID] = nil;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonProcess
+
+Resets the displayed auras for a specific button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonProcess(buttonID)
+	-- Wipe.
+	if(ButtonBorders[buttonID]) then
+		wipe(ButtonBorders[buttonID]);
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonDisplayAura
+
+Adds the displayed aura to the list of active auras for the given button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonDisplayAura(buttonID, auraID, actionData)
+	-- Add this aura if we need to.
+	if(not actionData["border"]) then return; end
+	if(not ButtonBorders[buttonID]) then ButtonBorders[buttonID] = {}; end
+	-- Calculate.
+	if(not ButtonBorders[buttonID][1] or
+	(actionData["border_priority"] or 25) > (ButtonBorders[buttonID][1] or 25)) then
+		-- Make sure it's enabled.
+		EnabledButtons[buttonID] = true;
+		-- It's a higher priority than the currently recorded one.
+		ButtonBorders[buttonID][1] = actionData["border_priority"] or 25;
+		ButtonBorders[buttonID][2] = actionData["border_color"] or { 1, 1, 1, 1 };
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnActionCreate
+
+Fired when an action is created. Used to set defaults in the newly made action ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnActionCreate(auraID, actionID)
+	-- Get action.
+	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
+	-- Write.
+	actionData["border"] = nil;
+	actionData["border_priority"] = 25;
+	actionData["border_color"] = { 1, 1, 1, 1 };
+	-- Save.
+	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsEnabled
+
+Checks to see if the module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsEnabled()
+	return CoreFrame:GetModuleSetting("Border", "Enabled");
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FixSettings
+
+Fixes all saved variables and migrates older ones across.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FixSettings(force)
+	-- Do the module settings exist?
+	if(not CoreFrame:GetSetting("Border") or force) then
+		-- We'd best fix that then.
+		PowerAurasButtons_SettingsDB["Border"] = {
+			["Enabled"] = true
+		};
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Fix settings first.
+	ModuleFrame:FixSettings();
+	-- Make sure enabled.
+	if(not ModuleFrame:IsEnabled()) then
+		-- Count as an unsuccessful module load.
+		return nil;
+	end
+	-- Register Blizzard button/LAB stuff.
+	if(LibStub) then
+		local LAB = LibStub("LibActionButton-1.0", true);
+		if(LAB) then
+			-- Add a button update hook.
+			LAB:RegisterCallback("OnButtonState", function(_, button)
+				ModuleFrame:OnButtonUpdate(button:GetName());
+			end);
+		end
+	end
+	-- Aaand the Blizzard hook.
+	hooksecurefunc("ActionButton_UpdateState", function(button)
+		ModuleFrame:OnButtonUpdate(button:GetName());
+	end);
+	-- Register module events for aura showing/hiding and button updates.
+	CoreFrame:RegisterModuleEventListener("OnButtonProcess", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnButtonDisplayAura", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnButtonUpdate", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/BorderConfig.lua b/Modules/BorderConfig.lua
index 2d0aa9d..269270f 100644
--- a/Modules/BorderConfig.lua
+++ b/Modules/BorderConfig.lua
@@ -1,140 +1,140 @@
---[[
-	PowerAurasButtons
-
-	Module: BorderConfig
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("BorderConfig", { "Border", "Config" });
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateConfigurationFrame
-
-Creates the configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateConfigurationFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Make the parent frame.
-	local ActionEditor = CreateFrame("Frame", nil, UIParent);
-	ActionEditor:SetHeight(55);
-	-- Label.
-	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Border", ActionEditor,
-		0);
-	-- Display borders?
-	ActionEditor.DisplayBorder = Modules.Config:CreateButtonWidget(ActionEditor, "Display Border");
-	ActionEditor.DisplayBorder:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 5, -30);
-	ActionEditor.DisplayBorder:SetScript("OnClick", function(self)
-		-- Toggle self.
-		if(self.Selected) then
-			self:Deselect();
-			Modules.Config:UpdateActionData("border", nil);
-		else
-			self:Select();
-			Modules.Config:UpdateActionData("border", true);
-		end
-	end);
-
-	-- Color picker.
-	ActionEditor.Color = Modules.Config:CreateColorWidget(ActionEditor);
-	ActionEditor.Color:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 155, -35);
-	ActionEditor.Color:SetScript("OnClick", function()
-		-- Display the color picker.
-		ColorPickerFrame:SetColorRGB(ActionEditor.Color.Swatch:GetVertexColor());
-		-- Allow transparency.
-		ColorPickerFrame.hasOpacity = nil;
-		ColorPickerFrame.opacity = 1;
-		ColorPickerFrame.previousValues = ActionEditor.Color.Swatch.Backup;
-		-- Save functions.
-		local saveFunc = function(restore)
-			-- Locals.
-			local r, g, b, a = nil, nil, nil, 1;
-			-- Get values.
-			if(not restore) then
-				r, g, b = ColorPickerFrame:GetColorRGB();
-			else
-				-- Restoring from restore table.
-				r, g, b, a = unpack(restore);
-			end
-			-- Save.
-			Modules.Config:UpdateActionData("border_color", { r, g, b, a });
-		end;
-		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
-		-- Go.
-		ColorPickerFrame:Hide();
-		ColorPickerFrame:Show();
-	end);
-
-	-- Border priority slider.
-	ActionEditor.Priority = CreateFrame("Slider", "PowerAurasButtons_BorderPrioritySlider",
-		ActionEditor, "OptionsSliderTemplate");
-	ActionEditor.Priority:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 185, -34);
-	ActionEditor.Priority:SetMinMaxValues(1, 50);
-	ActionEditor.Priority:SetValue(1);
-	ActionEditor.Priority:SetValueStep(1);
-	ActionEditor.Priority:SetWidth(150);
-
-	PowerAurasButtons_BorderPrioritySliderLow:SetText(0);
-	PowerAurasButtons_BorderPrioritySliderHigh:SetText(25);
-
-	ActionEditor.Priority:SetScript("OnValueChanged", function()
-		Modules.Config:UpdateActionData("border_priority", ceil(ActionEditor.Priority:GetValue()));
-	end);
-
-	-- Tooltips (localization handled by the config module)
-	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayBorder, {
-		title = "Display Border |cFFFF0000*BETA*|r",
-		text = "Displays a colored border around the button when the aura is active."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.Color, {
-		title = "Border Color",
-		text = "The color of the border."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.Priority, {
-		title = "Border Priority",
-		text = "The priority of the border.\n\n" ..
-			"If multiple auras attempt to color a border, only the one with the highest " ..
-			"priority will be shown."
-	});
-
-	-- Add the necessary functions.
-	ActionEditor.UpdateAction = function(self, actionData)
-		if(actionData["border"]) then
-			ActionEditor.DisplayBorder:Select();
-		else
-			ActionEditor.DisplayBorder:Deselect();
-		end
-		if(actionData["border_priority"]) then
-			ActionEditor.Priority:SetValue(actionData["border_priority"]);
-			PowerAurasButtons_BorderPrioritySliderText:SetText(actionData["border_priority"]);
-		else
-			ActionEditor.Priority:SetValue(25);
-			PowerAurasButtons_BorderPrioritySliderText:SetText(25);
-		end
-		if(actionData["border_color"]) then
-			ActionEditor.Color.Swatch:SetVertexColor(unpack(actionData["border_color"]));
-			ActionEditor.Color.Swatch.Backup = actionData["border_color"];
-		else
-			ActionEditor.Color.Swatch:SetVertexColor(1, 1, 1, 1);
-			ActionEditor.Color.Swatch.Backup = { 1, 1, 1, 1 };
-		end
-	end;
-
-	-- Done.
-	Modules.Config:RegisterActionConfigFrame(ActionEditor);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Register module events for config frames.
-	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: BorderConfig
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("BorderConfig", { "Border", "Config" });
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateConfigurationFrame
+
+Creates the configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateConfigurationFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Make the parent frame.
+	local ActionEditor = CreateFrame("Frame", nil, UIParent);
+	ActionEditor:SetHeight(55);
+	-- Label.
+	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Border", ActionEditor,
+		0);
+	-- Display borders?
+	ActionEditor.DisplayBorder = Modules.Config:CreateButtonWidget(ActionEditor, "Display Border");
+	ActionEditor.DisplayBorder:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 5, -30);
+	ActionEditor.DisplayBorder:SetScript("OnClick", function(self)
+		-- Toggle self.
+		if(self.Selected) then
+			self:Deselect();
+			Modules.Config:UpdateActionData("border", nil);
+		else
+			self:Select();
+			Modules.Config:UpdateActionData("border", true);
+		end
+	end);
+
+	-- Color picker.
+	ActionEditor.Color = Modules.Config:CreateColorWidget(ActionEditor);
+	ActionEditor.Color:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 155, -35);
+	ActionEditor.Color:SetScript("OnClick", function()
+		-- Display the color picker.
+		ColorPickerFrame:SetColorRGB(ActionEditor.Color.Swatch:GetVertexColor());
+		-- Allow transparency.
+		ColorPickerFrame.hasOpacity = nil;
+		ColorPickerFrame.opacity = 1;
+		ColorPickerFrame.previousValues = ActionEditor.Color.Swatch.Backup;
+		-- Save functions.
+		local saveFunc = function(restore)
+			-- Locals.
+			local r, g, b, a = nil, nil, nil, 1;
+			-- Get values.
+			if(not restore) then
+				r, g, b = ColorPickerFrame:GetColorRGB();
+			else
+				-- Restoring from restore table.
+				r, g, b, a = unpack(restore);
+			end
+			-- Save.
+			Modules.Config:UpdateActionData("border_color", { r, g, b, a });
+		end;
+		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
+		-- Go.
+		ColorPickerFrame:Hide();
+		ColorPickerFrame:Show();
+	end);
+
+	-- Border priority slider.
+	ActionEditor.Priority = CreateFrame("Slider", "PowerAurasButtons_BorderPrioritySlider",
+		ActionEditor, "OptionsSliderTemplate");
+	ActionEditor.Priority:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 185, -34);
+	ActionEditor.Priority:SetMinMaxValues(1, 50);
+	ActionEditor.Priority:SetValue(1);
+	ActionEditor.Priority:SetValueStep(1);
+	ActionEditor.Priority:SetWidth(150);
+
+	PowerAurasButtons_BorderPrioritySliderLow:SetText(0);
+	PowerAurasButtons_BorderPrioritySliderHigh:SetText(25);
+
+	ActionEditor.Priority:SetScript("OnValueChanged", function()
+		Modules.Config:UpdateActionData("border_priority", ceil(ActionEditor.Priority:GetValue()));
+	end);
+
+	-- Tooltips (localization handled by the config module)
+	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayBorder, {
+		title = "Display Border |cFFFF0000*BETA*|r",
+		text = "Displays a colored border around the button when the aura is active."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.Color, {
+		title = "Border Color",
+		text = "The color of the border."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.Priority, {
+		title = "Border Priority",
+		text = "The priority of the border.\n\n" ..
+			"If multiple auras attempt to color a border, only the one with the highest " ..
+			"priority will be shown."
+	});
+
+	-- Add the necessary functions.
+	ActionEditor.UpdateAction = function(self, actionData)
+		if(actionData["border"]) then
+			ActionEditor.DisplayBorder:Select();
+		else
+			ActionEditor.DisplayBorder:Deselect();
+		end
+		if(actionData["border_priority"]) then
+			ActionEditor.Priority:SetValue(actionData["border_priority"]);
+			PowerAurasButtons_BorderPrioritySliderText:SetText(actionData["border_priority"]);
+		else
+			ActionEditor.Priority:SetValue(25);
+			PowerAurasButtons_BorderPrioritySliderText:SetText(25);
+		end
+		if(actionData["border_color"]) then
+			ActionEditor.Color.Swatch:SetVertexColor(unpack(actionData["border_color"]));
+			ActionEditor.Color.Swatch.Backup = actionData["border_color"];
+		else
+			ActionEditor.Color.Swatch:SetVertexColor(1, 1, 1, 1);
+			ActionEditor.Color.Swatch.Backup = { 1, 1, 1, 1 };
+		end
+	end;
+
+	-- Done.
+	Modules.Config:RegisterActionConfigFrame(ActionEditor);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Register module events for config frames.
+	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/Buttons.lua b/Modules/Buttons.lua
index aa480e3..e9eebda 100644
--- a/Modules/Buttons.lua
+++ b/Modules/Buttons.lua
@@ -1,345 +1,345 @@
---[[
-	PowerAurasButtons
-
-	Module: Buttons
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("Buttons", { "Auras" });
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	Buttons            Stores all registered buttons in a table.
-	ButtonData         Stores the switches for each button - whether it should glow, etc.
-	ThrottleActive     Stores the current throttle state.
-	ThrottlePending    Stores the status of any pending mass updates.
-	ThrottleTimer      Stores the current throttle timer for mass updates.
-----------------------------------------------------------------------------------------------------
---]]
-local Buttons          = {};
-local ButtonData       = {};
-local ThrottleActive   = nil;
-local ThrottlePending  = nil;
-local ThrottleTimer    = 0;
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonUpdate
-
-Event handler for button updates. Updates glows depending on assigned auras, etc.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonUpdate(button)
-	-- Only bother updating if we can see it.
-	if(not button or not button:IsShown()) then return; end
-	-- Test the button for glowability.
-	ModuleFrame:ProcessButtonActions(button);
-	-- Fire button update event.
-	CoreFrame:FireModuleEvent("OnButtonUpdate", button:GetName());
-	-- So, does the glow need showing or hiding?
-	if(ModuleFrame:GetButtonData(button:GetName())["glow"]) then
-		-- Show the glow.
-		ActionButton_ShowOverlayGlow(button);
-	else
-		-- Hide the glow.
-		ActionButton_HideOverlayGlow(button);
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetButtonData
-
-Retrieves the button data table for the given button ID. Returns nil on failure.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetButtonData(buttonID)
-	-- Go.
-	return ButtonData[buttonID] or nil;
-end
---[[
-----------------------------------------------------------------------------------------------------
-ProcessButtonActions
-
-Processes all of the assigned actions on a button. This will determine whether a button should
-be glowing, showing displays, etc.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:ProcessButtonActions(button)
-	-- Few locals.
-	local buttonID = button:GetName();
-	-- Get the button data table if it exists. Otherwise, make a new one. We recycle the old one
-	-- so the memory size won't fluctuate.
-	local buttonData = ButtonData[buttonID] or {};
-	-- Wipe the data.
-	wipe(buttonData);
-	-- Fire button processing event.
-	CoreFrame:FireModuleEvent("OnButtonProcess", buttonID);
-	-- Get the non blizzard auras.
-	local CustomAuras, BlizzAuras = Modules.Auras:GetAuras();
-	-- More locals.
-	local buttonAction, buttonActionType, buttonActionID, buttonMacro, displayCount;
-	-- Get the button action ID.
-	buttonAction = button._state_action or button.action;
-	-- Action needs to be integer.
-	if(not buttonAction or type(buttonAction) ~= "number") then
-		-- Action isn't valid.
-		ButtonData[buttonID] = buttonData;
-		return;
-	end
-	-- Get the button action data.
-	buttonActionType, buttonActionID = GetActionInfo(buttonAction);
-	-- Get macro names if needed.
-	if(buttonActionType == "macro") then
-		buttonMacro = GetMacroSpell(buttonActionID) or GetMacroItem(buttonActionID);
-	end
-	-- Right, first off we need to go over all the auras see if they're linked to this one.
-	for auraID, _ in pairs(CustomAuras) do
-		-- Aura needs to be active.
-		if(Modules.Auras:IsAuraShown(auraID)) then
-			-- And go over the actions.
-			for auraActionID, auraActionData in pairs(Modules.Auras:GetAuraActions(auraID)) do
-				-- Action needs to be a valid ID (> 0)
-				if(auraActionData["id"] and auraActionData["id"] > 0) then
-					-- If the type/data keys match, or this is a macro/spell combo then continue.
-					if(buttonActionType == auraActionData["type"]
-					or (buttonActionType == "macro" and auraActionData["type"] == "spell")
-					or (buttonActionType == "macro" and auraActionData["type"] == "item")) then
-						-- Compare ID's. If they match, we're golden. If they don't, do macro
-						-- comparisons.
-						if((buttonActionID == auraActionData["id"]
-						and buttonActionType == auraActionData["type"])
-						or buttonMacro and (auraActionData["type"] == "spell"
-						and GetSpellInfo(auraActionData["id"]) == buttonMacro
-						or auraActionData["type"] == "item"
-						and GetItemInfo(auraActionData["id"]) == buttonMacro)) then
-							-- Enable glows if the action says so.
-							Modules.Auras:MergeAuraAction(buttonData, auraActionData);
-							-- Fire the OnAuraDisplay event.
-							CoreFrame:FireModuleEvent("OnButtonDisplayAura", buttonID, auraID,
-								auraActionData, auraActionID);
-						end
-					end
-				end
-			end
-		end
-	end
-	-- Blizzard auras need checking if glow isn't on, and if enabled.
-	if(CoreFrame:GetModuleSetting("Buttons", "ShowBlizzardGlows")) then
-		if(not buttonData["glow"] and buttonActionType == "spell"
-		and IsSpellOverlayed(buttonActionID)) then
-			-- It needs to glow.
-			buttonData["glow"] = true;
-		elseif(not buttonData["glow"] and buttonActionType == "macro") then
-			-- Macros should glow too.
-			buttonMacro = GetMacroSpell(buttonActionID) or GetMacroItem(buttonActionID);
-			-- Loop over active Blizzard auras.
-			for blizzAuraID, _ in pairs(BlizzAuras) do
-				-- Check ID.
-				if(not buttonData["glow"] and buttonMacro
-				and (buttonMacro == GetSpellInfo(blizzAuraID)
-				or GetItemInfo(blizzAuraID) == buttonMacro)) then
-					-- Yeah, it's a match. Timers/Stacks aren't on for blizz ones.
-					buttonData["glow"] = true;
-				end
-			end
-		end
-	end
-	-- Update.
-	ButtonData[buttonID] = buttonData;
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnUpdateTrigger
-
-Fired when OnAuraShow/OnAuraHide are called. Performs a mass button update.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnUpdateTrigger()
-	-- Check to see if update throttling is enabled. If it is, we'll queue this update.
-	if(CoreFrame:GetModuleSetting("Buttons", "Throttle") > 0 and ThrottleActive) then
-		-- We're throttled.
-		ThrottlePending = true;
-	else
-		-- Throttle further updates (won't do anything if disabled!)
-		ModuleFrame:ThrottleUpdates();
-		-- Iterate over the active buttons and go to town on it.
-		for buttonID, button in pairs(Buttons) do
-			-- Buttons that should be made but aren't registered yet are recorded as TRUE values.
-			-- On each mass update we try to replace these with actual buttons, this fixes issues
-			-- with Dominos.
-			if(button and button == true) then
-				Buttons[buttonID] = _G[buttonID] or true;
-			end
-			-- Pass to UpdateButton.
-			if(button and button ~= true) then
-				ModuleFrame:OnButtonUpdate(Buttons[buttonID]);
-			end
-		end
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-ThrottleUpdates
-
-Throttles further updates if the feature is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:ThrottleUpdates()
-	-- Make sure it's enabled.
-	if(CoreFrame:GetModuleSetting("Buttons", "Throttle") == 0) then return; end
-	-- Stop further updates.
-	ThrottleActive = true;
-	-- Reset our throttle timer.
-	ThrottleTimer = 0;
-	-- Register update script.
-	ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnUpdate
-
-Acts as our function for throttling update requests. It's called OnUpdate but is only present
-while we're throttling - we unregister it after.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnUpdate(elapsed)
-	-- Update time elapsed.
-	ThrottleTimer = ThrottleTimer + elapsed;
-	-- Time up?
-	if(ThrottleTimer < CoreFrame:GetModuleSetting("Buttons", "Throttle")) then return; end
-	-- Remove update script.
-	ModuleFrame:SetScript("OnUpdate", nil);
-	-- Time up! Rip this off.
-	ThrottleActive = nil;
-	-- Any updates queued?
-	if(ThrottlePending) then
-		-- Trigger update, remove the var.
-		ThrottlePending = nil;
-		-- This will trigger re-throttling if another request comes along while processing this
-		-- one. It's intended.
-		ModuleFrame:OnUpdateTrigger();
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterButtons
-
-Registers buttons into our button array for glow activation purposes.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:RegisterButtons(key, count)
-	-- Register, nils included (it's a Dominos thing)
-	local button = nil;
-	for i=1,(count or 12) do
-		-- Register it.
-		Buttons[key .. i] = _G[key .. i] or true;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnActionCreate
-
-Fired when an action is created. Used to set defaults in the newly made action ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnActionCreate(auraID, actionID)
-	-- Get action.
-	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
-	-- Write.
-	actionData["glow"] = true;
-	-- Save.
-	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsEnabled
-
-Checks to see if the module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsEnabled()
-	return true;
-end
---[[
-----------------------------------------------------------------------------------------------------
-FixSettings
-
-Fixes all saved variables and migrates older ones across.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FixSettings(force)
-	-- Do the module settings exist?
-	if(not CoreFrame:GetSetting("Buttons") or force) then
-		-- We'd best fix that then.
-		PowerAurasButtons_SettingsDB["Buttons"] = {
-			["Throttle"] = 0.05,
-			["RegisterBlizzardButtons"] = true,
-			["ShowBlizzardGlows"] = true
-		};
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Fix settings first.
-	ModuleFrame:FixSettings();
-	-- Register the needed buttons.
-	if(Dominos) then
-		-- Dominos reuses the Blizzard AB's and creates 60 of its own.
-		CoreFrame:Debug("Dominos detected");
-		ModuleFrame:RegisterButtons("DominosActionButton", 60);
-	elseif(LibStub) then
-		-- Bartender4 is a tad more tricky. It uses LAB which makes buttons as needed.
-		-- So we need to check for LAB (and LibStub), then scan all loaded buttons and make
-		-- sure future ones are added.
-		local LAB = LibStub("LibActionButton-1.0", true);
-		if(LAB) then
-			CoreFrame:Debug("Bartender4/LibActionButton detected");
-			-- LibActionButton found. Go over all of the buttons.
-			for button in pairs(LAB:GetAllButtons()) do
-				Buttons[button:GetName()] = button;
-			end
-			-- In addition, make sure this applies to future buttons.
-			LAB:RegisterCallback("OnButtonCreated", function(_, button)
-				Buttons[button:GetName()] = button;
-			end);
-			-- Add a button update hook.
-			LAB:RegisterCallback("OnButtonUpdate", function(_, button)
-				ModuleFrame:OnButtonUpdate(button);
-			end);
-		end
-	end
-	-- Odds are you're using the default buttons if you're not using Dominos/BT.
-	-- Register them if not told otherwise.
-	if(CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons") or Dominos) then
-		CoreFrame:Debug("Registering Blizzard buttons");
-		ModuleFrame:RegisterButtons("ActionButton");
-		ModuleFrame:RegisterButtons("BonusActionButton");
-		ModuleFrame:RegisterButtons("MultiBarRightButton");
-		ModuleFrame:RegisterButtons("MultiBarLeftButton");
-		ModuleFrame:RegisterButtons("MultiBarBottomRightButton");
-		ModuleFrame:RegisterButtons("MultiBarBottomLeftButton");
-	end
-	-- If you use Dominos or have the Blizzard buttons on, you need this.
-	if(Dominos or CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons")) then
-		-- Hook for button updates.
-		hooksecurefunc("ActionButton_Update", function(button)
-			ModuleFrame:OnButtonUpdate(button);
-		end);
-	end
-	-- Create some events for modules to hook on to.
-	CoreFrame:RegisterModuleEvent("OnButtonUpdate");
-	CoreFrame:RegisterModuleEvent("OnButtonProcess");
-	CoreFrame:RegisterModuleEvent("OnButtonDisplayAura");
-	-- Register OnAuraShow/OnAuraHide.
-	CoreFrame:RegisterModuleEventListener("OnAuraShow", ModuleFrame, ModuleFrame.OnUpdateTrigger);
-	CoreFrame:RegisterModuleEventListener("OnAuraHide", ModuleFrame, ModuleFrame.OnUpdateTrigger);
-	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: Buttons
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("Buttons", { "Auras" });
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	Buttons            Stores all registered buttons in a table.
+	ButtonData         Stores the switches for each button - whether it should glow, etc.
+	ThrottleActive     Stores the current throttle state.
+	ThrottlePending    Stores the status of any pending mass updates.
+	ThrottleTimer      Stores the current throttle timer for mass updates.
+----------------------------------------------------------------------------------------------------
+--]]
+local Buttons          = {};
+local ButtonData       = {};
+local ThrottleActive   = nil;
+local ThrottlePending  = nil;
+local ThrottleTimer    = 0;
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonUpdate
+
+Event handler for button updates. Updates glows depending on assigned auras, etc.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonUpdate(button)
+	-- Only bother updating if we can see it.
+	if(not button or not button:IsShown()) then return; end
+	-- Test the button for glowability.
+	ModuleFrame:ProcessButtonActions(button);
+	-- Fire button update event.
+	CoreFrame:FireModuleEvent("OnButtonUpdate", button:GetName());
+	-- So, does the glow need showing or hiding?
+	if(ModuleFrame:GetButtonData(button:GetName())["glow"]) then
+		-- Show the glow.
+		ActionButton_ShowOverlayGlow(button);
+	else
+		-- Hide the glow.
+		ActionButton_HideOverlayGlow(button);
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetButtonData
+
+Retrieves the button data table for the given button ID. Returns nil on failure.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetButtonData(buttonID)
+	-- Go.
+	return ButtonData[buttonID] or nil;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+ProcessButtonActions
+
+Processes all of the assigned actions on a button. This will determine whether a button should
+be glowing, showing displays, etc.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:ProcessButtonActions(button)
+	-- Few locals.
+	local buttonID = button:GetName();
+	-- Get the button data table if it exists. Otherwise, make a new one. We recycle the old one
+	-- so the memory size won't fluctuate.
+	local buttonData = ButtonData[buttonID] or {};
+	-- Wipe the data.
+	wipe(buttonData);
+	-- Fire button processing event.
+	CoreFrame:FireModuleEvent("OnButtonProcess", buttonID);
+	-- Get the non blizzard auras.
+	local CustomAuras, BlizzAuras = Modules.Auras:GetAuras();
+	-- More locals.
+	local buttonAction, buttonActionType, buttonActionID, buttonMacro, displayCount;
+	-- Get the button action ID.
+	buttonAction = button._state_action or button.action;
+	-- Action needs to be integer.
+	if(not buttonAction or type(buttonAction) ~= "number") then
+		-- Action isn't valid.
+		ButtonData[buttonID] = buttonData;
+		return;
+	end
+	-- Get the button action data.
+	buttonActionType, buttonActionID = GetActionInfo(buttonAction);
+	-- Get macro names if needed.
+	if(buttonActionType == "macro") then
+		buttonMacro = GetMacroSpell(buttonActionID) or GetMacroItem(buttonActionID);
+	end
+	-- Right, first off we need to go over all the auras see if they're linked to this one.
+	for auraID, _ in pairs(CustomAuras) do
+		-- Aura needs to be active.
+		if(Modules.Auras:IsAuraShown(auraID)) then
+			-- And go over the actions.
+			for auraActionID, auraActionData in pairs(Modules.Auras:GetAuraActions(auraID)) do
+				-- Action needs to be a valid ID (> 0)
+				if(auraActionData["id"] and auraActionData["id"] > 0) then
+					-- If the type/data keys match, or this is a macro/spell combo then continue.
+					if(buttonActionType == auraActionData["type"]
+					or (buttonActionType == "macro" and auraActionData["type"] == "spell")
+					or (buttonActionType == "macro" and auraActionData["type"] == "item")) then
+						-- Compare ID's. If they match, we're golden. If they don't, do macro
+						-- comparisons.
+						if((buttonActionID == auraActionData["id"]
+						and buttonActionType == auraActionData["type"])
+						or buttonMacro and (auraActionData["type"] == "spell"
+						and GetSpellInfo(auraActionData["id"]) == buttonMacro
+						or auraActionData["type"] == "item"
+						and GetItemInfo(auraActionData["id"]) == buttonMacro)) then
+							-- Enable glows if the action says so.
+							Modules.Auras:MergeAuraAction(buttonData, auraActionData);
+							-- Fire the OnAuraDisplay event.
+							CoreFrame:FireModuleEvent("OnButtonDisplayAura", buttonID, auraID,
+								auraActionData, auraActionID);
+						end
+					end
+				end
+			end
+		end
+	end
+	-- Blizzard auras need checking if glow isn't on, and if enabled.
+	if(CoreFrame:GetModuleSetting("Buttons", "ShowBlizzardGlows")) then
+		if(not buttonData["glow"] and buttonActionType == "spell"
+		and IsSpellOverlayed(buttonActionID)) then
+			-- It needs to glow.
+			buttonData["glow"] = true;
+		elseif(not buttonData["glow"] and buttonActionType == "macro") then
+			-- Macros should glow too.
+			buttonMacro = GetMacroSpell(buttonActionID) or GetMacroItem(buttonActionID);
+			-- Loop over active Blizzard auras.
+			for blizzAuraID, _ in pairs(BlizzAuras) do
+				-- Check ID.
+				if(not buttonData["glow"] and buttonMacro
+				and (buttonMacro == GetSpellInfo(blizzAuraID)
+				or GetItemInfo(blizzAuraID) == buttonMacro)) then
+					-- Yeah, it's a match. Timers/Stacks aren't on for blizz ones.
+					buttonData["glow"] = true;
+				end
+			end
+		end
+	end
+	-- Update.
+	ButtonData[buttonID] = buttonData;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnUpdateTrigger
+
+Fired when OnAuraShow/OnAuraHide are called. Performs a mass button update.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnUpdateTrigger()
+	-- Check to see if update throttling is enabled. If it is, we'll queue this update.
+	if(CoreFrame:GetModuleSetting("Buttons", "Throttle") > 0 and ThrottleActive) then
+		-- We're throttled.
+		ThrottlePending = true;
+	else
+		-- Throttle further updates (won't do anything if disabled!)
+		ModuleFrame:ThrottleUpdates();
+		-- Iterate over the active buttons and go to town on it.
+		for buttonID, button in pairs(Buttons) do
+			-- Buttons that should be made but aren't registered yet are recorded as TRUE values.
+			-- On each mass update we try to replace these with actual buttons, this fixes issues
+			-- with Dominos.
+			if(button and button == true) then
+				Buttons[buttonID] = _G[buttonID] or true;
+			end
+			-- Pass to UpdateButton.
+			if(button and button ~= true) then
+				ModuleFrame:OnButtonUpdate(Buttons[buttonID]);
+			end
+		end
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+ThrottleUpdates
+
+Throttles further updates if the feature is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:ThrottleUpdates()
+	-- Make sure it's enabled.
+	if(CoreFrame:GetModuleSetting("Buttons", "Throttle") == 0) then return; end
+	-- Stop further updates.
+	ThrottleActive = true;
+	-- Reset our throttle timer.
+	ThrottleTimer = 0;
+	-- Register update script.
+	ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnUpdate
+
+Acts as our function for throttling update requests. It's called OnUpdate but is only present
+while we're throttling - we unregister it after.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnUpdate(elapsed)
+	-- Update time elapsed.
+	ThrottleTimer = ThrottleTimer + elapsed;
+	-- Time up?
+	if(ThrottleTimer < CoreFrame:GetModuleSetting("Buttons", "Throttle")) then return; end
+	-- Remove update script.
+	ModuleFrame:SetScript("OnUpdate", nil);
+	-- Time up! Rip this off.
+	ThrottleActive = nil;
+	-- Any updates queued?
+	if(ThrottlePending) then
+		-- Trigger update, remove the var.
+		ThrottlePending = nil;
+		-- This will trigger re-throttling if another request comes along while processing this
+		-- one. It's intended.
+		ModuleFrame:OnUpdateTrigger();
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterButtons
+
+Registers buttons into our button array for glow activation purposes.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:RegisterButtons(key, count)
+	-- Register, nils included (it's a Dominos thing)
+	local button = nil;
+	for i=1,(count or 12) do
+		-- Register it.
+		Buttons[key .. i] = _G[key .. i] or true;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnActionCreate
+
+Fired when an action is created. Used to set defaults in the newly made action ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnActionCreate(auraID, actionID)
+	-- Get action.
+	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
+	-- Write.
+	actionData["glow"] = true;
+	-- Save.
+	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsEnabled
+
+Checks to see if the module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsEnabled()
+	return true;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FixSettings
+
+Fixes all saved variables and migrates older ones across.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FixSettings(force)
+	-- Do the module settings exist?
+	if(not CoreFrame:GetSetting("Buttons") or force) then
+		-- We'd best fix that then.
+		PowerAurasButtons_SettingsDB["Buttons"] = {
+			["Throttle"] = 0.05,
+			["RegisterBlizzardButtons"] = true,
+			["ShowBlizzardGlows"] = true
+		};
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Fix settings first.
+	ModuleFrame:FixSettings();
+	-- Register the needed buttons.
+	if(Dominos) then
+		-- Dominos reuses the Blizzard AB's and creates 60 of its own.
+		CoreFrame:Debug("Dominos detected");
+		ModuleFrame:RegisterButtons("DominosActionButton", 60);
+	elseif(LibStub) then
+		-- Bartender4 is a tad more tricky. It uses LAB which makes buttons as needed.
+		-- So we need to check for LAB (and LibStub), then scan all loaded buttons and make
+		-- sure future ones are added.
+		local LAB = LibStub("LibActionButton-1.0", true);
+		if(LAB) then
+			CoreFrame:Debug("Bartender4/LibActionButton detected");
+			-- LibActionButton found. Go over all of the buttons.
+			for button in pairs(LAB:GetAllButtons()) do
+				Buttons[button:GetName()] = button;
+			end
+			-- In addition, make sure this applies to future buttons.
+			LAB:RegisterCallback("OnButtonCreated", function(_, button)
+				Buttons[button:GetName()] = button;
+			end);
+			-- Add a button update hook.
+			LAB:RegisterCallback("OnButtonUpdate", function(_, button)
+				ModuleFrame:OnButtonUpdate(button);
+			end);
+		end
+	end
+	-- Odds are you're using the default buttons if you're not using Dominos/BT.
+	-- Register them if not told otherwise.
+	if(CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons") or Dominos) then
+		CoreFrame:Debug("Registering Blizzard buttons");
+		ModuleFrame:RegisterButtons("ActionButton");
+		ModuleFrame:RegisterButtons("BonusActionButton");
+		ModuleFrame:RegisterButtons("MultiBarRightButton");
+		ModuleFrame:RegisterButtons("MultiBarLeftButton");
+		ModuleFrame:RegisterButtons("MultiBarBottomRightButton");
+		ModuleFrame:RegisterButtons("MultiBarBottomLeftButton");
+	end
+	-- If you use Dominos or have the Blizzard buttons on, you need this.
+	if(Dominos or CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons")) then
+		-- Hook for button updates.
+		hooksecurefunc("ActionButton_Update", function(button)
+			ModuleFrame:OnButtonUpdate(button);
+		end);
+	end
+	-- Create some events for modules to hook on to.
+	CoreFrame:RegisterModuleEvent("OnButtonUpdate");
+	CoreFrame:RegisterModuleEvent("OnButtonProcess");
+	CoreFrame:RegisterModuleEvent("OnButtonDisplayAura");
+	-- Register OnAuraShow/OnAuraHide.
+	CoreFrame:RegisterModuleEventListener("OnAuraShow", ModuleFrame, ModuleFrame.OnUpdateTrigger);
+	CoreFrame:RegisterModuleEventListener("OnAuraHide", ModuleFrame, ModuleFrame.OnUpdateTrigger);
+	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/ButtonsConfig.lua b/Modules/ButtonsConfig.lua
index cb9915f..0f09cfb 100644
--- a/Modules/ButtonsConfig.lua
+++ b/Modules/ButtonsConfig.lua
@@ -1,145 +1,145 @@
---[[
-	PowerAurasButtons
-
-	Module: ButtonsConfig
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("ButtonsConfig", { "Buttons", "Config" });
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateConfigurationFrame
-
-Creates the configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateConfigurationFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Make the parent frame.
-	local ActionEditor = CreateFrame("Frame", nil, UIParent);
-	ActionEditor:SetHeight(51);
-	-- Label.
-	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Buttons", ActionEditor,
-		0);
-	-- Display glows?
-	ActionEditor.DisplayGlow = Modules.Config:CreateButtonWidget(ActionEditor, "Display Glow");
-	ActionEditor.DisplayGlow:SetPoint("TOP", ActionEditor, "TOP", 0, -25);
-	ActionEditor.DisplayGlow:SetScript("OnClick", function(self)
-			-- Toggle self.
-			if(self.Selected) then
-				self:Deselect();
-				Modules.Config:UpdateActionData("glow", nil);
-			else
-				self:Select();
-				Modules.Config:UpdateActionData("glow", true);
-			end
-		end);
-	-- Tooltips (localization handled by the config module)
-	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayGlow, {
-		title = "Display Glow",
-		text = "Displays the shiny glow on the button when this aura is active."
-	});
-	-- Add the necessary functions.
-	ActionEditor.UpdateAction = function(self, actionData)
-		if(actionData["glow"]) then
-			ActionEditor.DisplayGlow:Select();
-		else
-			ActionEditor.DisplayGlow:Deselect();
-		end
-	end;
-	-- Done.
-	Modules.Config:RegisterActionConfigFrame(ActionEditor, 2);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateInterfaceOptionsFrame
-
-Creates the interface options configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateInterfaceOptionsFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Base frame.
-	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Buttons");
-	-- Two things needed: Slider, checkbutton. Slider first.
-	InterfaceOptions.ThrottleSlider = CreateFrame("Slider", "PowerAurasButtons_ButtonsThrottle",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.ThrottleSlider:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -80);
-	InterfaceOptions.ThrottleSlider:SetMinMaxValues(0.05, 1);
-	InterfaceOptions.ThrottleSlider:SetValue(CoreFrame:GetModuleSetting("Buttons", "Throttle"));
-	InterfaceOptions.ThrottleSlider:SetValueStep(0.05);
-	InterfaceOptions.ThrottleSlider:SetWidth(250);
-
-	PowerAurasButtons_ButtonsThrottleLow:SetText("0.05");
-	PowerAurasButtons_ButtonsThrottleHigh:SetText("1");
-	PowerAurasButtons_ButtonsThrottleText:SetText(CoreFrame.L["Update Throttle"] .. " (" ..
-		CoreFrame:GetModuleSetting("Buttons", "Throttle") .. " " .. CoreFrame.L["Seconds"] .. ")");
-	-- Update on value change.
-	InterfaceOptions.ThrottleSlider:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		CoreFrame:SetModuleSetting("Buttons", "Throttle",
-			tonumber(string.format("%.2f", self:GetValue()), 10));
-		-- Update label too.
-		PowerAurasButtons_ButtonsThrottleText:SetText(CoreFrame.L["Update Throttle"] .. " (" ..
-			tonumber(string.format("%.2f", self:GetValue()), 10) .. " " ..
-			CoreFrame.L["Seconds"] .. ")");
-	end);
-	-- Checkbutton.
-	InterfaceOptions.Blizz = CreateFrame("CheckButton", "PowerAurasButtons_ButtonsBlizz",
-		InterfaceOptions, "ChatConfigCheckButtonTemplate");
-	InterfaceOptions.Blizz:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -115);
-	PowerAurasButtons_ButtonsBlizzText:SetText(CoreFrame.L["Register Blizzard Buttons"]);
-	InterfaceOptions.Blizz:SetChecked(
-		CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons"));
-	-- Save on click.
-	InterfaceOptions.Blizz:SetScript("OnClick", function(self)
-		-- Requires a reload to take effect, so get a glowbox ready and running.
-		Modules.Config:CreateGlowBoxWidget(InterfaceOptions);
-		-- Save.
-		CoreFrame:SetModuleSetting("Buttons", "RegisterBlizzardButtons", self:GetChecked());
-	end);
-	-- One more checkbutton.
-	InterfaceOptions.SGlow = CreateFrame("CheckButton", "PowerAurasButtons_ButtonsShowBlizzGlows",
-		InterfaceOptions, "ChatConfigCheckButtonTemplate");
-	InterfaceOptions.SGlow:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -140);
-	PowerAurasButtons_ButtonsShowBlizzGlowsText:SetText(CoreFrame.L["Show Blizzard Glows"]);
-	InterfaceOptions.SGlow:SetChecked(
-		CoreFrame:GetModuleSetting("Buttons", "ShowBlizzardGlows"));
-	-- Save on click.
-	InterfaceOptions.SGlow:SetScript("OnClick", function(self)
-		-- Save.
-		CoreFrame:SetModuleSetting("Buttons", "ShowBlizzardGlows", self:GetChecked());
-	end);
-	-- Tooltips.
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.ThrottleSlider, {
-		title = "Update Throttle",
-		text = "Controls the throttle for mass button updates. This affects both " ..
-			"performance and responsiveness, so leaving it at around 0.05 to 0.1 is a good idea."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.Blizz, {
-		title = "Register Blizzard Buttons",
-		text = "Select this if you want Blizzard's default action buttons to be included. " ..
-			"If you are using another addon like Bartender or Dominos, you can disable this."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.SGlow, {
-		title = "Show Blizzard Glows |cFFFF0000*BETA*|r",
-		text = "Select this if you want Blizzard's default action button glows to be displayed."
-	});
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Register module events for config frames.
-	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnCreateInterfaceOptionsFrame", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: ButtonsConfig
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("ButtonsConfig", { "Buttons", "Config" });
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateConfigurationFrame
+
+Creates the configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateConfigurationFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Make the parent frame.
+	local ActionEditor = CreateFrame("Frame", nil, UIParent);
+	ActionEditor:SetHeight(51);
+	-- Label.
+	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Buttons", ActionEditor,
+		0);
+	-- Display glows?
+	ActionEditor.DisplayGlow = Modules.Config:CreateButtonWidget(ActionEditor, "Display Glow");
+	ActionEditor.DisplayGlow:SetPoint("TOP", ActionEditor, "TOP", 0, -25);
+	ActionEditor.DisplayGlow:SetScript("OnClick", function(self)
+			-- Toggle self.
+			if(self.Selected) then
+				self:Deselect();
+				Modules.Config:UpdateActionData("glow", nil);
+			else
+				self:Select();
+				Modules.Config:UpdateActionData("glow", true);
+			end
+		end);
+	-- Tooltips (localization handled by the config module)
+	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayGlow, {
+		title = "Display Glow",
+		text = "Displays the shiny glow on the button when this aura is active."
+	});
+	-- Add the necessary functions.
+	ActionEditor.UpdateAction = function(self, actionData)
+		if(actionData["glow"]) then
+			ActionEditor.DisplayGlow:Select();
+		else
+			ActionEditor.DisplayGlow:Deselect();
+		end
+	end;
+	-- Done.
+	Modules.Config:RegisterActionConfigFrame(ActionEditor, 2);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateInterfaceOptionsFrame
+
+Creates the interface options configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateInterfaceOptionsFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Base frame.
+	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Buttons");
+	-- Two things needed: Slider, checkbutton. Slider first.
+	InterfaceOptions.ThrottleSlider = CreateFrame("Slider", "PowerAurasButtons_ButtonsThrottle",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.ThrottleSlider:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -80);
+	InterfaceOptions.ThrottleSlider:SetMinMaxValues(0.05, 1);
+	InterfaceOptions.ThrottleSlider:SetValue(CoreFrame:GetModuleSetting("Buttons", "Throttle"));
+	InterfaceOptions.ThrottleSlider:SetValueStep(0.05);
+	InterfaceOptions.ThrottleSlider:SetWidth(250);
+
+	PowerAurasButtons_ButtonsThrottleLow:SetText("0.05");
+	PowerAurasButtons_ButtonsThrottleHigh:SetText("1");
+	PowerAurasButtons_ButtonsThrottleText:SetText(CoreFrame.L["Update Throttle"] .. " (" ..
+		CoreFrame:GetModuleSetting("Buttons", "Throttle") .. " " .. CoreFrame.L["Seconds"] .. ")");
+	-- Update on value change.
+	InterfaceOptions.ThrottleSlider:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		CoreFrame:SetModuleSetting("Buttons", "Throttle",
+			tonumber(string.format("%.2f", self:GetValue()), 10));
+		-- Update label too.
+		PowerAurasButtons_ButtonsThrottleText:SetText(CoreFrame.L["Update Throttle"] .. " (" ..
+			tonumber(string.format("%.2f", self:GetValue()), 10) .. " " ..
+			CoreFrame.L["Seconds"] .. ")");
+	end);
+	-- Checkbutton.
+	InterfaceOptions.Blizz = CreateFrame("CheckButton", "PowerAurasButtons_ButtonsBlizz",
+		InterfaceOptions, "ChatConfigCheckButtonTemplate");
+	InterfaceOptions.Blizz:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -115);
+	PowerAurasButtons_ButtonsBlizzText:SetText(CoreFrame.L["Register Blizzard Buttons"]);
+	InterfaceOptions.Blizz:SetChecked(
+		CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons"));
+	-- Save on click.
+	InterfaceOptions.Blizz:SetScript("OnClick", function(self)
+		-- Requires a reload to take effect, so get a glowbox ready and running.
+		Modules.Config:CreateGlowBoxWidget(InterfaceOptions);
+		-- Save.
+		CoreFrame:SetModuleSetting("Buttons", "RegisterBlizzardButtons", self:GetChecked());
+	end);
+	-- One more checkbutton.
+	InterfaceOptions.SGlow = CreateFrame("CheckButton", "PowerAurasButtons_ButtonsShowBlizzGlows",
+		InterfaceOptions, "ChatConfigCheckButtonTemplate");
+	InterfaceOptions.SGlow:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -140);
+	PowerAurasButtons_ButtonsShowBlizzGlowsText:SetText(CoreFrame.L["Show Blizzard Glows"]);
+	InterfaceOptions.SGlow:SetChecked(
+		CoreFrame:GetModuleSetting("Buttons", "ShowBlizzardGlows"));
+	-- Save on click.
+	InterfaceOptions.SGlow:SetScript("OnClick", function(self)
+		-- Save.
+		CoreFrame:SetModuleSetting("Buttons", "ShowBlizzardGlows", self:GetChecked());
+	end);
+	-- Tooltips.
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.ThrottleSlider, {
+		title = "Update Throttle",
+		text = "Controls the throttle for mass button updates. This affects both " ..
+			"performance and responsiveness, so leaving it at around 0.05 to 0.1 is a good idea."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.Blizz, {
+		title = "Register Blizzard Buttons",
+		text = "Select this if you want Blizzard's default action buttons to be included. " ..
+			"If you are using another addon like Bartender or Dominos, you can disable this."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.SGlow, {
+		title = "Show Blizzard Glows |cFFFF0000*BETA*|r",
+		text = "Select this if you want Blizzard's default action button glows to be displayed."
+	});
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Register module events for config frames.
+	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnCreateInterfaceOptionsFrame", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/Config.lua b/Modules/Config.lua
index 6d7d533..fa90da0 100644
--- a/Modules/Config.lua
+++ b/Modules/Config.lua
@@ -1,1032 +1,1032 @@
---[[
-	PowerAurasButtons
-
-	Module: Config
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
--- Weird dependencies here, it's to make sure the aura and buttons config frames are placed on
--- top of any others in the action editor.
-local ModuleFrame      = CoreFrame:RegisterModule("Config", { "AurasConfig" }, true);
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	ActionEditor       Stores the action editor setting thing frame.
-	ActionEditorBase   Stores the action editor base frame.
-	ActionEditorList   Stores the action editor list frame.
-	Action             Stores the currently selected action ID.
-	ActionData         Stores the currently selected action data.
-	Aura               Stores the ID of the current aura.
-	EditorFrames       Stores a table of all frames appended to the action editor.
-	EditorFramesCount  Stores a count of all added editor frames, because #() is so annoying.
-	InterfaceOptions   Stores the main interface options panel.
-	L                  Localization table.
-	ReindexedAuras     Stores a table of reindex auras. Used to move, copy and delete action sets.
-----------------------------------------------------------------------------------------------------
---]]
-local ActionEditor      = nil;
-local ActionEditorBase  = nil;
-local ActionEditorList  = nil;
-local Action            = nil;
-local ActionData        = nil;
-local Aura              = nil;
-local EditorFrames      = {};
-local EditorFramesCount = 0;
-local InterfaceOptions  = nil;
-local L                 = CoreFrame.L;
-local ReindexedAuras    = {};
---[[
-----------------------------------------------------------------------------------------------------
-tcopy
-
-Does a somewhat deep table copy.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:tcopy(t)
-	local t2 = {};
-	for k,v in pairs(t) do
-		t2[k] = (type(v) == "table" and ModuleFrame:tcopy(v) or v);
-	end
-	return t2;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetCurrentActionData
-
-Returns the current ActionData table.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetCurrentActionData()
-	return ActionData;
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateInterfaceOptions
-
-Creates the Interface Options frame.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateInterfaceOptions()
-	-- Make a parent frame.
-	InterfaceOptions = CreateFrame("Frame", nil, UIParent);
-	-- Set name and parent.
-	InterfaceOptions.name = "Power Auras Classic: Buttons";
-	-- Add the child to the Interface Options panel.
-	InterfaceOptions_AddCategory(InterfaceOptions);
-
-	-- Make the frame a bit more snazzy with titles and crap.
-	InterfaceOptions.Title = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalLarge");
-	InterfaceOptions.Title:SetText("Power Auras Classic: Buttons");
-	InterfaceOptions.Title:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -15);
-
-	-- Subtitle too.
-	InterfaceOptions.SubTitle = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalSmall");
-	InterfaceOptions.SubTitle:SetHeight(30);
-	InterfaceOptions.SubTitle:SetText(GetAddOnMetadata("PowerAurasButtons", "Notes"));
-	InterfaceOptions.SubTitle:SetTextColor(1, 1, 1);
-	InterfaceOptions.SubTitle:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -40);
-	InterfaceOptions.SubTitle:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -10, -40);
-	InterfaceOptions.SubTitle:SetJustifyH("LEFT");
-	InterfaceOptions.SubTitle:SetJustifyV("TOP");
-
-	-- Right, let's add some more metadata strings.
-	InterfaceOptions.TitleVersion = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalSmall");
-	InterfaceOptions.TitleVersion:SetText(L["Version"] .. ":");
-	InterfaceOptions.TitleVersion:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -80);
-	InterfaceOptions.TitleVersion:SetWidth(100);
-	InterfaceOptions.TitleVersion:SetJustifyH("RIGHT");
-	InterfaceOptions.TitleVersion:SetJustifyV("TOP");
-	InterfaceOptions.Version = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalSmall");
-	InterfaceOptions.Version:SetText(GetAddOnMetadata("PowerAurasButtons", "Version"));
-	InterfaceOptions.Version:SetTextColor(1, 1, 1);
-	InterfaceOptions.Version:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -80);
-	InterfaceOptions.Version:SetJustifyH("LEFT");
-	InterfaceOptions.Version:SetJustifyV("TOP");
-
-	InterfaceOptions.TitleAuthor = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalSmall");
-	InterfaceOptions.TitleAuthor:SetText(L["Author"] .. ":");
-	InterfaceOptions.TitleAuthor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -95);
-	InterfaceOptions.TitleAuthor:SetWidth(100);
-	InterfaceOptions.TitleAuthor:SetJustifyH("RIGHT");
-	InterfaceOptions.TitleAuthor:SetJustifyV("TOP");
-	InterfaceOptions.Author = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormalSmall");
-	InterfaceOptions.Author:SetText(GetAddOnMetadata("PowerAurasButtons", "Author"));
-	InterfaceOptions.Author:SetTextColor(1, 1, 1);
-	InterfaceOptions.Author:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -95);
-	InterfaceOptions.Author:SetJustifyH("LEFT");
-	InterfaceOptions.Author:SetJustifyV("TOP");
-
-	if(CoreFrame.__debug) then
-		InterfaceOptions.TitleDebug = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-			"GameFontNormalSmall");
-		InterfaceOptions.TitleDebug:SetText(L["Debug"] .. ":");
-		InterfaceOptions.TitleDebug:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -110);
-		InterfaceOptions.TitleDebug:SetWidth(100);
-		InterfaceOptions.TitleDebug:SetJustifyH("RIGHT");
-		InterfaceOptions.TitleDebug:SetJustifyV("TOP");
-		InterfaceOptions.Debug = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-			"GameFontNormalSmall");
-		InterfaceOptions.Debug:SetText("|cFF00FF00Enabled|r");
-		InterfaceOptions.Debug:SetTextColor(1, 1, 1);
-		InterfaceOptions.Debug:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -110);
-		InterfaceOptions.Debug:SetJustifyH("LEFT");
-		InterfaceOptions.Debug:SetJustifyV("TOP");
-	end
-
-	-- Now for the module switcher. Make a title...
-
-	InterfaceOptions.ModulesTitle = InterfaceOptions:CreateFontString(nil, "ARTWORK",
-		"GameFontNormal");
-	InterfaceOptions.ModulesTitle:SetText(L["Module Manager"]);
-	InterfaceOptions.ModulesTitle:SetPoint("TOP", InterfaceOptions, "TOP", 0, -130);
-	-- Make a scrolly area.
-	InterfaceOptions.Modules = CreateFrame("Frame", nil, InterfaceOptions);
-	InterfaceOptions.Modules:SetBackdrop({
-		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
-		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-		tile = true, tileSize = 16, edgeSize = 16,
-		insets = { left = 3, right = 3, top = 5, bottom = 3 }
-	});
-	InterfaceOptions.Modules:SetBackdropColor(0, 0, 0, 0.75);
-	InterfaceOptions.Modules:SetBackdropBorderColor(0.4, 0.4, 0.4);
-	InterfaceOptions.Modules:SetPoint("TOP", InterfaceOptions, "TOP", 0, -145);
-	InterfaceOptions.Modules:SetHeight(200);
-	InterfaceOptions.Modules:SetWidth(375);
-	-- List frame needs a scroll frame.
-	InterfaceOptions.Modules.Scroll = CreateFrame("ScrollFrame",
-		"PowerAurasButtons_ModuleScrollFrame", InterfaceOptions.Modules,
-		"UIPanelScrollFrameTemplate");
-	InterfaceOptions.Modules.Scroll:SetPoint("TOPLEFT", InterfaceOptions.Modules, "TOPLEFT", 5, -5);
-	InterfaceOptions.Modules.Scroll:SetPoint("BOTTOMRIGHT", InterfaceOptions.Modules,
-		"BOTTOMRIGHT", -26, 4);
-	-- Scroll frame needs something to actually scroll.
-	InterfaceOptions.Modules.List = CreateFrame("Frame", nil, InterfaceOptions.Modules.Scroll);
-	InterfaceOptions.Modules.List:SetPoint("TOPLEFT", InterfaceOptions.Modules.Scroll, "TOPLEFT");
-	-- Height needs to be set.
-	InterfaceOptions.Modules.List:SetHeight(0);
-	-- The height needs to match the content, but the width can be that of the box...
-	InterfaceOptions.Modules.List:SetWidth(350);
-	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
-	InterfaceOptions.Modules.Scroll:SetScrollChild(InterfaceOptions.Modules.List);
-	-- Store the row frames in this table - we'll reuse them as needed.
-	InterfaceOptions.Modules.List.Items = {};
-	InterfaceOptions.Modules.List.Rows = {};
-
-	-- Make a small function, hook it to OnShow. It'll scan the modules and update the list.
-	local scanModules;
-	scanModules = function()
-		-- Make a table of all modules that can be enabled/disabled.
-		wipe(InterfaceOptions.Modules.List.Items);
-		for module, frame in pairs(CoreFrame.Modules) do
-			if(frame.CanDisable) then tinsert(InterfaceOptions.Modules.List.Items, module); end
-		end
-		-- Hide existing rows.
-		for _, row in pairs(InterfaceOptions.Modules.List.Rows) do
-			row:Hide();
-		end
-		-- Using that, fill in the rows.
-		for i, module in pairs(InterfaceOptions.Modules.List.Items) do
-			-- Make rows dynamically and reuse existing ones.
-			if(not InterfaceOptions.Modules.List.Rows[i]) then
-				local row = CreateFrame("Frame", nil, InterfaceOptions.Modules.List);
-				-- Add textures.
-				row.Texture = row:CreateTexture(nil, "BACKGROUND");
-				row.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
-				row.Texture:SetAllPoints(row);
-				row.Texture:SetVertexColor(1, 1, 1, 0.15);
-				-- Height, anchor.
-				row:SetHeight(20);
-				row:SetPoint("TOPLEFT", InterfaceOptions.Modules.List, "TOPLEFT", 0, -((i-1)*20));
-				row:SetPoint("TOPRIGHT", InterfaceOptions.Modules.List, "TOPRIGHT", 0, -((i-1)*20));
-				-- Label.
-				row.Label = row:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-				row.Label:SetHeight(20);
-				row.Label:SetPoint("TOPLEFT", row, "TOPLEFT", 10, 0);
-				row.Label:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 10, 0);
-				-- And a delete button.
-				row.Button = CreateFrame("Button", nil, row);
-				row.Button:SetPoint("RIGHT", row, "RIGHT", -2, 0);
-				row.Button:SetWidth(16);
-				row.Button:SetHeight(16);
-				-- Register the row.
-				InterfaceOptions.Modules.List.Rows[i] = row;
-				-- And when you click, we toggle.
-				row.Button:SetScript("OnClick", function()
-					local module = row.Label:GetText();
-					if(CoreFrame:IsModuleEnabled(module)) then
-						-- Disable the module.
-						CoreFrame:SetModuleSetting(module, "Enabled", nil);
-					else
-						-- Enable the module.
-						CoreFrame:SetModuleSetting(module, "Enabled", true);
-					end
-					-- ReloadUI is needed :)
-					ModuleFrame:CreateGlowBoxWidget(InterfaceOptions);
-					-- Rescan.
-					scanModules();
-				end);
-				-- Tooltip.
-				ModuleFrame:RegisterConfigTooltip(row.Button, {
-					override = function()
-						-- Check module status.
-						if(CoreFrame:IsModuleEnabled(module)) then
-							GameTooltip:SetText(L["Disable Module"]);
-							GameTooltip:AddLine(L["Click to disable this module."], 1, 1, 1, 1);
-						else
-							GameTooltip:SetText(L["Enable Module"]);
-							GameTooltip:AddLine(L["Click to enable this module."], 1, 1, 1, 1);
-						end
-					end
-				});
-			end
-			-- Get row.
-			local row = InterfaceOptions.Modules.List.Rows[i];
-			-- Set stuff.
-			row.Label:SetText(module);
-			-- Is the module enabled?
-			if(CoreFrame:IsModuleEnabled(module)) then
-				-- Enabled, so show disable stuff and color the background greenish.
-				row.Button:SetNormalTexture("Interface\\FriendsFrame\\StatusIcon-DnD");
-				row.Button:SetHighlightTexture("Interface\\FriendsFrame\\StatusIcon-DnD", "BLEND");
-				row.Button:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
-				row.Button:GetHighlightTexture():SetVertexColor(1.0, 1.0, 1.0, 1.0);
-				row.Texture:SetVertexColor(0.3, 0.8, 0.3, 0.6);
-			else
-				-- Disabled. Show enable stuff and color BG red.
-				row.Button:SetNormalTexture("Interface\\FriendsFrame\\StatusIcon-Online");
-				row.Button:SetHighlightTexture("Interface\\FriendsFrame\\StatusIcon-Online",
-					"BLEND");
-				row.Button:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
-				row.Button:GetHighlightTexture():SetVertexColor(1.0, 1.0, 1.0, 1.0);
-				row.Texture:SetVertexColor(1.0, 0.5, 0.5, 1.0);
-			end
-			-- Add height to the list.
-			InterfaceOptions.Modules.List:SetHeight(i*20);
-			row:Show();
-		end
-	end
-	-- Set the script.
-	InterfaceOptions:SetScript("OnShow", scanModules);
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateActionEditor
-
-Creates the action editing frame.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateActionEditor()
-	-- Make the editor frame.
-	ActionEditorBase = CreateFrame("Frame", nil, PowaBarConfigFrame, "TranslucentFrameTemplate");
-	ActionEditorBase:SetPoint("TOPLEFT", PowaBarConfigFrame, "TOPRIGHT", -13, 1);
-	ActionEditorBase:SetHeight(462);
-	ActionEditorBase:SetWidth(400);
-	ActionEditorBase:EnableMouse(true);
-	-- Make it look nice. Add a header.
-	ActionEditorBase.Header = ActionEditorBase:CreateTexture(nil, "ARTWORK");
-	ActionEditorBase.Header:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header");
-	ActionEditorBase.Header:SetPoint("TOP", ActionEditorBase, "TOP", 0, 13);
-	ActionEditorBase.Header:SetHeight(68);
-	ActionEditorBase.Header:SetWidth(300);
-	-- Shove a title in that too.
-	ActionEditorBase.Title = ActionEditorBase:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-	ActionEditorBase.Title:SetText(L["Action Editor"]);
-	ActionEditorBase.Title:SetPoint("TOP", ActionEditorBase.Header, "TOP", 0, -16);
-
-	-- Create the list frame.
-	ActionEditorList = CreateFrame("Frame", nil, ActionEditorBase);
-	ActionEditorList:SetBackdrop({
-		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
-		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-		tile = true, tileSize = 16, edgeSize = 16,
-		insets = { left = 3, right = 3, top = 5, bottom = 3 }
-	});
-	ActionEditorList:SetBackdropColor(0, 0, 0, 0.75);
-	ActionEditorList:SetBackdropBorderColor(0.4, 0.4, 0.4);
-	ActionEditorList:SetPoint("TOP", ActionEditorBase, "TOP", 0, -25);
-	ActionEditorList:SetHeight(200);
-	ActionEditorList:SetWidth(375);
-
-	-- List frame needs a scroll frame.
-	ActionEditorList.Scroll = CreateFrame("ScrollFrame", "PowerAurasButtons_ConfigScrollFrame",
-		ActionEditorList, "UIPanelScrollFrameTemplate");
-	ActionEditorList.Scroll:SetPoint("TOPLEFT", ActionEditorList, "TOPLEFT", 5, -5);
-	ActionEditorList.Scroll:SetPoint("BOTTOMRIGHT", ActionEditorList, "BOTTOMRIGHT", -26, 4);
-
-	-- Scroll frame needs something to actually scroll.
-	ActionEditorList.List = CreateFrame("Frame", nil, ActionEditorList.Scroll);
-	ActionEditorList.List:SetPoint("TOPLEFT", ActionEditorList.Scroll, "TOPLEFT");
-	-- Height needs to be set, we do this when an aura is selected.
-	ActionEditorList.List:SetHeight(0);
-	-- The height needs to match the content, but the width can be that of the box...
-	ActionEditorList.List:SetWidth(ActionEditorList.Scroll:GetWidth());
-	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
-	ActionEditorList.Scroll:SetScrollChild(ActionEditorList.List);
-	-- Store the row frames in this table - we'll reuse them as needed.
-	ActionEditorList.List.Items = {};
-
-	-- And finally, the editor frame.
-	ActionEditor = CreateFrame("Frame", nil, ActionEditorBase);
-	ActionEditor:SetBackdrop({
-		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
-		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-		tile = true, tileSize = 16, edgeSize = 16,
-		insets = { left = 3, right = 3, top = 5, bottom = 3 }
-	});
-	ActionEditor:SetBackdropColor(0, 0, 0, 0.75);
-	ActionEditor:SetBackdropBorderColor(0.4, 0.4, 0.4);
-	ActionEditor:SetPoint("TOP", ActionEditorList, "BOTTOM", 0, 0);
-	ActionEditor:SetHeight(225);
-	ActionEditor:SetWidth(375);
-	-- Helper functions for hiding/displaying elements.
-	ActionEditor.TogglePanel = function(self, show)
-		-- Check the show param.
-		if(show) then
-			-- Show then.
-			ActionEditor:Show();
-			ActionEditorBase:SetHeight(462);
-		else
-			-- Hide!
-			ActionEditor:Hide();
-			ActionEditorBase:SetHeight(237);
-		end
-	end
-	-- Need a scroll here too.
-	ActionEditor.Scroll = CreateFrame("ScrollFrame", "PowerAurasButtons_ActionScrollFrame",
-		ActionEditor, "UIPanelScrollFrameTemplate");
-	ActionEditor.Scroll:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 5, -5);
-	ActionEditor.Scroll:SetPoint("BOTTOMRIGHT", ActionEditor, "BOTTOMRIGHT", -26, 4);
-
-	-- Scroll frame needs something to actually scroll.
-	ActionEditor.List = CreateFrame("Frame", nil, ActionEditor.Scroll);
-	ActionEditor.List:SetPoint("TOPLEFT", ActionEditor.Scroll, "TOPLEFT");
-	-- Height needs to be set, we do this when an aura is selected.
-	ActionEditor.List:SetHeight(0);
-	-- The height needs to match the content, but the width can be that of the box...
-	ActionEditor.List:SetWidth(ActionEditor.Scroll:GetWidth());
-	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
-	ActionEditor.Scroll:SetScrollChild(ActionEditor.List);
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateButtonWidget
-
-Creates a button widget for the CreateActionEditor function.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateButtonWidget(parent, text, icon, disable)
-	-- Make the button.
-	local button = CreateFrame("Button", nil, parent);
-	-- Style it.
-	button:SetHeight(26);
-	button:SetWidth(110);
-	button:SetBackdrop({
-		bgFile = "Interface\\QuestFrame\\UI-QuestLogTitleHighlight",
-		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-		tile = false, tileSize = 16, edgeSize = 16,
-		insets = { left = 3, right = 3, top = 3, bottom = 3 }
-	});
-	button:SetBackdropColor(1, 1, 1, 0.15);
-	button:SetBackdropBorderColor(0.4, 0.4, 0.4);
-	-- Disabled?
-	if(disable) then
-		button:SetAlpha(0.5);
-	else
-		-- Mouseover stuff.
-		button:SetScript("OnEnter", function()
-			button:SetBackdropColor(0.196, 0.388, 0.8, 1.0);
-		end);
-		button:SetScript("OnLeave", function()
-			if(not button.Selected) then button:SetBackdropColor(1, 1, 1, 0.15); end
-		end);
-	end
-
-	-- Label.
-	button.Label = button:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-	button.Label:SetHeight(26);
-	button.Label:SetPoint("CENTER", button, "CENTER", 0, 0);
-	button.Label:SetText(text);
-
-	-- Icon.
-	if(icon) then
-		button.Icon = button:CreateTexture(nil, "ARTWORK");
-		button.Icon:SetPoint("LEFT", button, "LEFT", 5, 0);
-		button.Icon:SetWidth(16);
-		button.Icon:SetHeight(16);
-		button.Icon:SetTexture(icon);
-	end
-
-	-- And add a couple of helpful functions to the button.
-	button.Select = function()
-		button.Selected = true;
-		button:SetBackdropColor(0.196, 0.388, 0.8, 1.0);
-	end;
-	button.Deselect = function()
-		button.Selected = nil;
-		button:SetBackdropColor(1, 1, 1, 0.15);
-	end;
-
-	-- Deselect by default..
-	button:Deselect();
-	-- Done.
-	return button;
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateHeaderWidget
-
-Creates a header widget for the CreateActionEditor function.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateHeaderWidget(text, parent, y)
-	-- Make the label.
-	local label = parent:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-	label:SetHeight(20);
-	label:SetPoint("TOP", parent, "TOP", 0, y);
-	label:SetText(L[text]);
-	-- Header background stuff.
-	label.bg = parent:CreateTexture(nil, "ARTWORK");
-	label.bg:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
-	label.bg:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, y);
-	label.bg:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, y);
-	label.bg:SetHeight(20);
-	label.bg:SetVertexColor(1, 1, 1, 0.15);
-	-- Done.
-	return label;
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateColorWidget
-
-Creates a color selection widget.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateColorWidget(parent)
-	-- Make.
-	frame = CreateFrame("Button", nil, parent);
-	frame:SetWidth(16);
-	frame:SetHeight(16);
-	frame.Swatch = frame:CreateTexture(nil, "OVERLAY");
-	frame.Swatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch");
-	frame.Swatch:SetAllPoints(frame);
-	frame.SwatchBG = frame:CreateTexture(nil, "BACKGROUND");
-	frame.SwatchBG:SetWidth(14);
-	frame.SwatchBG:SetHeight(14);
-	frame.SwatchBG:SetTexture(1, 1, 1, 1);
-	frame.SwatchBG:SetPoint("CENTER", frame.Swatch);
-	frame.SwatchTrans = frame:CreateTexture(nil, "BACKGROUND");
-	frame.SwatchTrans:SetWidth(12);
-	frame.SwatchTrans:SetHeight(12);
-	frame.SwatchTrans:SetTexture("Tileset\\Generic\\Checkers");
-	frame.SwatchTrans:SetTexCoord(.25, 0, 0.5, .25);
-	frame.SwatchTrans:SetDesaturated(true);
-	frame.SwatchTrans:SetVertexColor(1, 1, 1, 0.75);
-	frame.SwatchTrans:SetPoint("CENTER", frame.Swatch);
-	frame.SwatchTrans:Show();
-	-- Done.
-	return frame;
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateGlowBoxWidget
-
-Creates a glowbox widget for the given frame. This by default shows a Reload Required message.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateGlowBoxWidget(parent)
-	-- Only make if needed.
-	if(not parent.GlowBox) then
-		-- Sort out the glowbox.
-		parent.GlowBox = CreateFrame("Frame", nil, parent, "GlowBoxTemplate");
-		parent.GlowBox:SetPoint("BOTTOMRIGHT", InterfaceOptionsFrameOkay, "TOPRIGHT", 0, 25);
-		parent.GlowBox:SetWidth(275);
-		parent.GlowBox:SetHeight(50);
-		parent.GlowBox.Arrow = CreateFrame("Frame", nil, parent.GlowBox, "GlowBoxArrowTemplate");
-		parent.GlowBox.Arrow:SetPoint("TOPRIGHT", parent.GlowBox, "BOTTOMRIGHT");
-		-- Glowbox titles.
-		parent.GlowBox.Title = parent.GlowBox:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-		parent.GlowBox.Title:SetText(L["Reload Required"]);
-		parent.GlowBox.Title:SetPoint("TOPLEFT", parent.GlowBox, "TOPLEFT", 10, -5);
-		parent.GlowBox.Title:SetPoint("TOPRIGHT", parent.GlowBox, "TOPRIGHT", -10, -5);
-		parent.GlowBox.Title:SetJustifyH("CENTER");
-		parent.GlowBox.Title:SetJustifyV("TOP");
-		-- And now text.
-		parent.GlowBox.Text = parent.GlowBox:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-		parent.GlowBox.Text:SetText(
-			L["You have altered settings which require an interface reload to take effect."]);
-		parent.GlowBox.Text:SetPoint("TOPLEFT", parent.GlowBox, "TOPLEFT", 10, -20);
-		parent.GlowBox.Text:SetPoint("BOTTOMRIGHT", parent.GlowBox, "BOTTOMRIGHT", -10, 5);
-		parent.GlowBox.Text:SetJustifyH("LEFT");
-		parent.GlowBox.Text:SetJustifyV("TOP");
-		parent.GlowBox.Text:SetTextColor(1, 1, 1);
-		-- Make the okay function on the parent reload the UI.
-		parent.okay = function()
-			-- Reload.
-			ReloadUI();
-		end
-	end
-	-- Show the glowbox.
-	parent.GlowBox:Show();
-end
---[[
-----------------------------------------------------------------------------------------------------
-UpdateSelectedAura
-
-Updates the opened aura in the power auras config frame.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:UpdateSelectedAura(auraID, actionID)
-	-- Set aura.
-	Aura = auraID;
-	-- Get all actions for this aura.
-	local actions = Modules.Auras:GetAuraActions(auraID);
-	-- Hide all rows.
-	for _, row in pairs(ActionEditorList.List.Items) do
-		row:Hide();
-		row:Deselect();
-	end
-	-- Do we have actions?
-	if(actions and #(actions) > 0) then
-		-- It has actions. Go over them.
-		for actionID, actionData in pairs(actions) do
-			-- Fetch the item row.
-			local row = ModuleFrame:FetchActionRow(actionID);
-			-- Set the icon and text.
-			if(actionData["type"] == "spell" and actionData["id"]) then
-				row.Icon:SetTexture("Interface\\GossipFrame\\TrainerGossipIcon");
-				row.Label:SetText(GetSpellLink(actionData["id"]), L["Invalid spell ID"]);
-			elseif(actionData["type"] == "macro" and actionData["id"]) then
-				row.Icon:SetTexture("Interface\\GossipFrame\\BinderGossipIcon");
-				row.Label:SetText(GetMacroInfo(actionData["id"]) or L["Invalid macro ID"]);
-			elseif(actionData["type"] == "item" and actionData["id"]) then
-				row.Icon:SetTexture("Interface\\GossipFrame\\VendorGossipIcon");
-				row.Label:SetText(select(2, GetItemInfo(actionData["id"])), L["Invalid item ID"]);
-			else
-				row.Icon:SetTexture("Interface\\GossipFrame\\ActiveQuestIcon");
-				row.Label:SetText(L["No action set"]);
-			end
-			-- Show it.
-			row:Show();
-		end
-	elseif(not actions) then
-		-- See if actions is nil - if so, make some.
-		Modules.Auras:SetAuraActions(auraID, {});
-		actions = {};
-	end
-	-- Add the "add new item..." row.
-	local addRow = ModuleFrame:FetchActionAddRow();
-	addRow:SetPoint("TOPLEFT", ActionEditorList.List, "TOPLEFT", 0, -(#(actions)*20));
-	addRow:SetPoint("TOPRIGHT", ActionEditorList.List, "TOPRIGHT", 0, -(#(actions)*20));
-	-- Update the list frame height.
-	ActionEditorList.List:SetHeight((#(actions) + 1)*20);
-	-- Show frame.
-	ActionEditorBase:Show();
-	-- Reset selected action.
-	ModuleFrame:UpdateSelectedAction(actionID);
-end
---[[
-----------------------------------------------------------------------------------------------------
-UpdateSelectedAction
-
-Updates the selected action in the action editor frame.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:UpdateSelectedAction(actionID)
-	-- Update vars.
-	Action = actionID;
-	ActionData = actionID and Modules.Auras:GetAuraAction(Aura, actionID);
-	-- Make sure no other row is classed as 'selected'.
-	for id, row in pairs(ActionEditorList.List.Items) do
-		if(actionID and actionID == id) then row:Select(); else row:Deselect(); end
-	end
-	-- Right, was an action passed?
-	if(not actionID) then
-		-- Hide the actual editor frame.
-		ActionEditor:TogglePanel();
-	else
-		-- Show editor frame.
-		ActionEditor:TogglePanel(true);
-		-- Go over the editor frames and trigger an UpdateAction.
-		for _, frame in pairs(EditorFrames) do
-			frame:UpdateAction(ActionData);
-			frame:Show();
-		end
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-UpdateActionData
-
-Updates the action data for the selected action.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:UpdateActionData(index, value)
-	-- Set.
-	ActionData[index] = value;
-	-- Save.
-	Modules.Auras:SetAuraAction(Aura, Action, ActionData);
-	-- Reload.
-	ModuleFrame:UpdateSelectedAura(Aura, Action);
-	if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
-end
---[[
-----------------------------------------------------------------------------------------------------
-FetchActionAddRow
-
-Creates and returns the "Add new item..." row for the action list.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FetchActionAddRow()
-	-- Make if not exists.
-	if(not ActionEditorList.AddRow) then
-		local addRow = CreateFrame("Frame", nil, ActionEditorList.List);
-		addRow:EnableMouse(true);
-		-- Add textures.
-		addRow.Texture = addRow:CreateTexture(nil, "BACKGROUND");
-		addRow.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
-		addRow.Texture:SetAllPoints(addRow);
-		addRow.Texture:SetVertexColor(1, 1, 1, 0.15);
-		-- Add an onenter/onleave script for the highlight toggle.
-		addRow:SetScript("OnEnter", function()
-			addRow.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
-		end);
-		addRow:SetScript("OnLeave", function()
-			addRow.Texture:SetVertexColor(1, 1, 1, 0.15);
-		end);
-		-- Height, anchor.
-		addRow:SetHeight(20);
-		-- Label.
-		addRow.Label = addRow:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-		addRow.Label:SetHeight(20);
-		addRow.Label:SetPoint("TOPLEFT", addRow, "TOPLEFT", 24, 0);
-		addRow.Label:SetPoint("BOTTOMLEFT", addRow, "BOTTOMLEFT", 24, 0);
-		addRow.Label:SetText(L["Add new action..."]);
-		-- Event handler for clicking the row.
-		addRow:SetScript("OnMouseUp", function()
-			-- Pass the action creation call to the Auras module and reload.
-			ModuleFrame:UpdateSelectedAura(Aura, Modules.Auras:CreateAuraAction(Aura));
-		end);
-		-- Save.
-		ActionEditorList.AddRow = addRow;
-	end
-	-- Done.
-	return ActionEditorList.AddRow;
-end
---[[
-----------------------------------------------------------------------------------------------------
-FetchActionRow
-
-Creates and returns an action editor row for the editor list. Reuses rows if they exist.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FetchActionRow(actionID)
-	-- Row exist or not?
-	if(not ActionEditorList.List.Items[actionID]) then
-		-- Make it.
-		local row = CreateFrame("Frame", nil, ActionEditorList.List);
-		row:EnableMouse(true);
-		-- Add textures.
-		row.Texture = row:CreateTexture(nil, "BACKGROUND");
-		row.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
-		row.Texture:SetAllPoints(row);
-		row.Texture:SetVertexColor(1, 1, 1, 0.15);
-		-- Add an onenter/onleave script for the highlight toggle.
-		row:SetScript("OnEnter", function()
-			row.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
-		end);
-		row:SetScript("OnLeave", function()
-			if(not row.Selected) then row.Texture:SetVertexColor(1, 1, 1, 0.15); end
-		end);
-		-- Height, anchor.
-		row:SetHeight(20);
-		row:SetPoint("TOPLEFT", ActionEditorList.List, "TOPLEFT", 0, -((actionID-1)*20));
-		row:SetPoint("TOPRIGHT", ActionEditorList.List, "TOPRIGHT", 0, -((actionID-1)*20));
-		-- Add an icon texture and a label.
-		row.Icon = row:CreateTexture(nil, "ARTWORK");
-		row.Icon:SetPoint("TOPLEFT", row, "TOPLEFT", 2, -2);
-		row.Icon:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 2, 2);
-		row.Icon:SetWidth(16);
-		-- Label.
-		row.Label = row:CreateFontString(nil, "ARTWORK", "GameFontNormal");
-		row.Label:SetHeight(20);
-		row.Label:SetPoint("TOPLEFT", row, "TOPLEFT", 24, 0);
-		row.Label:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 24, 0);
-		-- And a delete button.
-		row.Delete = CreateFrame("Button", nil, row);
-		row.Delete:SetNormalTexture("Interface\\FriendsFrame\\ClearBroadcastIcon");
-		row.Delete:SetHighlightTexture("Interface\\FriendsFrame\\ClearBroadcastIcon", "BLEND");
-		row.Delete:SetPoint("RIGHT", row, "RIGHT", -2, 0);
-		row.Delete:SetWidth(16);
-		row.Delete:SetHeight(16);
-		-- Put a tooltip onto the delete button.
-		ModuleFrame:RegisterConfigTooltip(row.Delete, {
-			title = "Delete Action",
-			text = "Click to delete this action."
-		});
-		-- Sort out the texture colours.
-		row.Delete:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.25);
-		row.Delete:GetHighlightTexture():SetVertexColor(0.75, 0.0, 0.0, 1.0);
-		-- When you click the delete button...Delete.
-		row.Delete:SetScript("OnClick", function()
-			-- Remove.
-			Modules.Auras:RemoveAuraAction(Aura, actionID);
-			-- Reload the aura.
-			ModuleFrame:UpdateSelectedAura(Aura);
-		end);
-		-- And when we click, trigger a chosen action update.
-		row:SetScript("OnMouseUp", function()
-			ModuleFrame:UpdateSelectedAction(actionID);
-		end);
-		-- And add a couple of helpful functions to the row.
-		row.Select = function()
-			row.Selected = true;
-			row.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
-		end;
-		row.Deselect = function()
-			row.Selected = nil;
-			row.Texture:SetVertexColor(1, 1, 1, 0.15);
-		end;
-		-- Save.
-		row:Deselect();
-		ActionEditorList.List.Items[actionID] = row;
-		-- Make sure it's hidden.
-		row:Hide();
-	end
-	-- Return it.
-	return ActionEditorList.List.Items[actionID];
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterActionConfigFrame
-
-Appends an additional frame to the action editor window.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:RegisterActionConfigFrame(frame, position)
-	-- Was a position set?
-	if(position and EditorFramesCount >= position) then
-		-- Reparent the frame.
-		frame:SetParent(ActionEditor.List);
-		-- We're going to need to inject this frame into the position and move things as needed.
-		-- Thankfully, each frame is anchored to another so we just need to move the one we're
-		-- moving down.
-		local oldFrame = EditorFrames[position];
-		oldFrame:ClearAllPoints();
-		oldFrame:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -5);
-		oldFrame:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", 0, -5);
-		-- And position the new frame...
-		frame:SetPoint("TOPLEFT",
-			EditorFrames[(position-1)] or ActionEditor.List,
-			EditorFrames[(position-1)] and "BOTTOMLEFT" or "TOPLEFT",
-			0,
-			EditorFrames[(position-1)] and -5 or 0
-		);
-		frame:SetPoint("TOPRIGHT",
-			EditorFrames[(position-1)] or ActionEditor.List,
-			EditorFrames[(position-1)] and "BOTTOMRIGHT" or "TOPRIGHT",
-			0,
-			EditorFrames[(position-1)] and -5 or 0
-		);
-		-- Inject.
-		tinsert(EditorFrames, position, frame);
-		EditorFramesCount = EditorFramesCount+1;
-	else
-		-- Re-parent and re-position the frame as if no position was set.
-		frame:SetParent(ActionEditor.List);
-		frame:SetPoint("TOPLEFT",
-			EditorFrames[EditorFramesCount] or ActionEditor.List,
-			EditorFrames[EditorFramesCount] and "BOTTOMLEFT" or "TOPLEFT",
-			0,
-			EditorFrames[EditorFramesCount] and -5 or 0
-		);
-		frame:SetPoint("TOPRIGHT",
-			EditorFrames[EditorFramesCount] or ActionEditor.List,
-			EditorFrames[EditorFramesCount] and "BOTTOMRIGHT" or "TOPRIGHT",
-			0,
-			EditorFrames[EditorFramesCount] and -5 or 0
-		);
-		-- Add to the table.
-		tinsert(EditorFrames, frame);
-		EditorFramesCount = EditorFramesCount+1;
-	end
-	-- Alter the height of the scroll frame.
-	ActionEditor.List:SetHeight(ActionEditor.List:GetHeight() + frame:GetHeight() + 5);
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterInterfaceOptionsFrame
-
-Appends an additional frame to the Interface Options panel.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:RegisterInterfaceOptionsFrame(name)
-	-- Make a child frame.
-	local childFrame = CreateFrame("Frame", nil, InterfaceOptions);
-	-- Set name and parent.
-	childFrame.name = name;
-	childFrame.parent = "Power Auras Classic: Buttons";
-	-- Add the child to the Interface Options panel.
-	InterfaceOptions_AddCategory(childFrame);
-	-- Make the frame a bit more snazzy with titles and crap.
-	childFrame.Title = childFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge");
-	childFrame.Title:SetText("Power Auras Classic: Buttons");
-	childFrame.Title:SetPoint("TOPLEFT", childFrame, "TOPLEFT", 10, -15);
-	-- Subtitle too.
-	childFrame.SubTitle = childFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall");
-	childFrame.SubTitle:SetText(L[name]);
-	childFrame.SubTitle:SetTextColor(1, 1, 1);
-	childFrame.SubTitle:SetPoint("TOPLEFT", childFrame, "TOPLEFT", 10, -40);
-	childFrame.SubTitle:SetPoint("TOPRIGHT", childFrame, "TOPRIGHT", -10, -40);
-	childFrame.SubTitle:SetHeight(30);
-	childFrame.SubTitle:SetJustifyH("LEFT");
-	childFrame.SubTitle:SetJustifyV("TOP");
-	-- And return it.
-	return childFrame;
-end
---[[
-----------------------------------------------------------------------------------------------------
-RegisterConfigTooltip
-
-Adds a tooltip to the given frame.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:RegisterConfigTooltip(frame, options)
-	-- Fill in anchor/offsets if blank.
-	if(not options) then options = {}; end
-	if(not options.anchor) then options.anchor = "ANCHOR_RIGHT"; end
-	if(not options.offsetX) then options.offsetX = 0; end
-	if(not options.offsetY) then options.offsetY = 0; end
-	if(not options.title) then options.title = ""; end
-	if(not options.text) then options.text = ""; end
-	-- Allow a tip refresh.
-	frame.RefreshTooltip = function()
-		-- Hide tip.
-		GameTooltip:Hide();
-		-- Reparent.
-		GameTooltip:SetOwner(frame, options.anchor, options.offsetX, options.offsetY);
-		-- Set back up.
-		if(not options.override) then
-			-- Go nuts brah.
-			GameTooltip:SetText(L[options.title]);
-			-- Enable line wrapping. I totally did NOT just find out that existed.
-			GameTooltip:AddLine(L[options.text], 1, 1, 1, 1);
-		else
-			-- Run the override func.
-			options.override();
-		end
-		-- Show tip.
-		GameTooltip:Show();
-	end
-	-- Use the RefreshTooltip function as a display method.
-	frame:SetScript("OnEnter", frame.RefreshTooltip);
-	-- Hide on leave.
-	frame:SetScript("OnLeave", function() GameTooltip:Hide(); end);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnModuleLoaded
-
-Fired by the module handler, contains the name of the loaded module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnModuleLoaded(module)
-	-- Bounce it to our events.
-	CoreFrame:FireModuleEvent("OnCreateConfigurationFrame", module);
-	CoreFrame:FireModuleEvent("OnCreateInterfaceOptionsFrame", module);
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsEnabled
-
-Checks to see if the module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsEnabled()
-	return CoreFrame:GetModuleSetting("Config", "Enabled");
-end
---[[
-----------------------------------------------------------------------------------------------------
-FixSettings
-
-Fixes all saved variables and migrates older ones across.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FixSettings(force)
-	-- Do the module settings exist?
-	if(not CoreFrame:GetSetting("Config") or force) then
-		-- We'd best fix that then.
-		PowerAurasButtons_SettingsDB["Config"] = {
-			["Enabled"] = true
-		};
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Fix settings first.
-	ModuleFrame:FixSettings();
-	-- Make sure enabled.
-	if(not ModuleFrame:IsEnabled()) then
-		-- Disabling the config module is...Different. It still counts as a failure, dependency
-		-- wise, but it will allow you to still turn modules on and off.
-		ModuleFrame:CreateInterfaceOptions();
-		-- Done.
-		return nil;
-	end
-	-- Create the action editor frame.
-	ModuleFrame:CreateActionEditor();
-	-- Create the interface options pane.
-	ModuleFrame:CreateInterfaceOptions();
-	-- Create some events for modules to hook on to.
-	CoreFrame:RegisterModuleEvent("OnCreateConfigurationFrame");
-	CoreFrame:RegisterModuleEvent("OnCreateInterfaceOptionsFrame");
-	-- Fire those events for already loaded modules (passing nil as the module name).
-	CoreFrame:FireModuleEvent("OnCreateConfigurationFrame", nil);
-	CoreFrame:FireModuleEvent("OnCreateInterfaceOptionsFrame", nil);
-	-- Listen to the OnModuleLoaded event.
-	CoreFrame:RegisterModuleEventListener("OnModuleLoaded", ModuleFrame);
-	-- This function runs when the PA options pane opens.
-	local script = function()
-		-- Update the aura if it's valid and show the config frame if it's not up.
-		if(PowaAuras.Auras[PowaAuras.CurrentAuraId] and PowaBarConfigFrame:IsShown()) then
-			-- Update aura.
-			ModuleFrame:UpdateSelectedAura(PowaAuras.CurrentAuraId);
-		else
-			-- Hide if it's not valid or not open.
-			ActionEditorBase:Hide();
-		end
-	end
-	-- Add needed hooks.
-	PowaBarConfigFrame:HookScript("OnShow", script);
-	PowaBarConfigFrame:HookScript("OnHide", script);
-	hooksecurefunc(PowaAuras, "InitPage", script);
-	hooksecurefunc(PowaAuras, "UpdateMainOption", script);
-	-- Also hook copying/moving. We can move aura sets like that.
-	hooksecurefunc(PowaAuras, "DoCopyEffect", function(_, idFrom, idTo, isMove)
-		-- Figure out the config tables for each.
-		local oldConfig = PowerAurasButtons_CharacterAurasDB;
-		local newConfig = PowerAurasButtons_CharacterAurasDB;
-		if(idFrom > 120) then oldConfig = PowerAurasButtons_AurasDB; end
-		if(idTo > 120) then newConfig = PowerAurasButtons_AurasDB; end
-		-- See if we had any auras in these spots.
-		if(oldConfig[idFrom]) then
-			-- Right, place these at the new location.
-			newConfig[idTo] = ModuleFrame:tcopy(oldConfig[idFrom]);
-			-- Was it a move?
-			if(isMove) then
-				-- Remove the old config.
-				wipe(oldConfig[idFrom]);
-			end
-		end
-		-- Button update.
-		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
-	end);
-	-- And aura deleting (we would hook DeleteAura but it messes up with moving effects).
-	hooksecurefunc(PowaAuras, "OptionDeleteEffect", function(_, auraID)
-		-- Determine the config table this one belonged to.
-		local config = PowerAurasButtons_CharacterAurasDB;
-		if(auraID > 120) then config = PowerAurasButtons_AurasDB; end
-		-- Did it exist?
-		if(config[auraID] and not tContains(ReindexedAuras, auraID)) then
-			-- Remove it.
-			wipe(config[auraID]);
-		end
-		-- Clear the reindex table.
-		wipe(ReindexedAuras);
-		-- Button update.
-		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
-	end);
-	-- If you delete an aura, it'll cause a re-indexing of ones after (delete #1 and #2 moves).
-	hooksecurefunc(PowaAuras, "ReindexAura", function(_, idFrom, idTo)
-		-- Figure out the config tables for each.
-		local oldConfig = PowerAurasButtons_CharacterAurasDB;
-		local newConfig = PowerAurasButtons_CharacterAurasDB;
-		if(idFrom > 120) then oldConfig = PowerAurasButtons_AurasDB; end
-		if(idTo > 120) then newConfig = PowerAurasButtons_AurasDB; end
-		-- Move old to new.
-		if(oldConfig[idFrom]) then
-			-- Right, place these at the new location.
-			newConfig[idTo] = ModuleFrame:tcopy(oldConfig[idFrom]);
-			-- Reindexing does NOT cause DeleteAura to fire.
-			wipe(oldConfig[idFrom]);
-			-- Add this to the table of reindexed auras.
-			tinsert(ReindexedAuras, idTo);
-		end
-		-- Button update.
-		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
-	end);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: Config
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+-- Weird dependencies here, it's to make sure the aura and buttons config frames are placed on
+-- top of any others in the action editor.
+local ModuleFrame      = CoreFrame:RegisterModule("Config", { "AurasConfig" }, true);
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	ActionEditor       Stores the action editor setting thing frame.
+	ActionEditorBase   Stores the action editor base frame.
+	ActionEditorList   Stores the action editor list frame.
+	Action             Stores the currently selected action ID.
+	ActionData         Stores the currently selected action data.
+	Aura               Stores the ID of the current aura.
+	EditorFrames       Stores a table of all frames appended to the action editor.
+	EditorFramesCount  Stores a count of all added editor frames, because #() is so annoying.
+	InterfaceOptions   Stores the main interface options panel.
+	L                  Localization table.
+	ReindexedAuras     Stores a table of reindex auras. Used to move, copy and delete action sets.
+----------------------------------------------------------------------------------------------------
+--]]
+local ActionEditor      = nil;
+local ActionEditorBase  = nil;
+local ActionEditorList  = nil;
+local Action            = nil;
+local ActionData        = nil;
+local Aura              = nil;
+local EditorFrames      = {};
+local EditorFramesCount = 0;
+local InterfaceOptions  = nil;
+local L                 = CoreFrame.L;
+local ReindexedAuras    = {};
+--[[
+----------------------------------------------------------------------------------------------------
+tcopy
+
+Does a somewhat deep table copy.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:tcopy(t)
+	local t2 = {};
+	for k,v in pairs(t) do
+		t2[k] = (type(v) == "table" and ModuleFrame:tcopy(v) or v);
+	end
+	return t2;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetCurrentActionData
+
+Returns the current ActionData table.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetCurrentActionData()
+	return ActionData;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateInterfaceOptions
+
+Creates the Interface Options frame.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateInterfaceOptions()
+	-- Make a parent frame.
+	InterfaceOptions = CreateFrame("Frame", nil, UIParent);
+	-- Set name and parent.
+	InterfaceOptions.name = "Power Auras Classic: Buttons";
+	-- Add the child to the Interface Options panel.
+	InterfaceOptions_AddCategory(InterfaceOptions);
+
+	-- Make the frame a bit more snazzy with titles and crap.
+	InterfaceOptions.Title = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalLarge");
+	InterfaceOptions.Title:SetText("Power Auras Classic: Buttons");
+	InterfaceOptions.Title:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -15);
+
+	-- Subtitle too.
+	InterfaceOptions.SubTitle = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalSmall");
+	InterfaceOptions.SubTitle:SetHeight(30);
+	InterfaceOptions.SubTitle:SetText(GetAddOnMetadata("PowerAurasButtons", "Notes"));
+	InterfaceOptions.SubTitle:SetTextColor(1, 1, 1);
+	InterfaceOptions.SubTitle:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -40);
+	InterfaceOptions.SubTitle:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -10, -40);
+	InterfaceOptions.SubTitle:SetJustifyH("LEFT");
+	InterfaceOptions.SubTitle:SetJustifyV("TOP");
+
+	-- Right, let's add some more metadata strings.
+	InterfaceOptions.TitleVersion = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalSmall");
+	InterfaceOptions.TitleVersion:SetText(L["Version"] .. ":");
+	InterfaceOptions.TitleVersion:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -80);
+	InterfaceOptions.TitleVersion:SetWidth(100);
+	InterfaceOptions.TitleVersion:SetJustifyH("RIGHT");
+	InterfaceOptions.TitleVersion:SetJustifyV("TOP");
+	InterfaceOptions.Version = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalSmall");
+	InterfaceOptions.Version:SetText(GetAddOnMetadata("PowerAurasButtons", "Version"));
+	InterfaceOptions.Version:SetTextColor(1, 1, 1);
+	InterfaceOptions.Version:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -80);
+	InterfaceOptions.Version:SetJustifyH("LEFT");
+	InterfaceOptions.Version:SetJustifyV("TOP");
+
+	InterfaceOptions.TitleAuthor = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalSmall");
+	InterfaceOptions.TitleAuthor:SetText(L["Author"] .. ":");
+	InterfaceOptions.TitleAuthor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -95);
+	InterfaceOptions.TitleAuthor:SetWidth(100);
+	InterfaceOptions.TitleAuthor:SetJustifyH("RIGHT");
+	InterfaceOptions.TitleAuthor:SetJustifyV("TOP");
+	InterfaceOptions.Author = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormalSmall");
+	InterfaceOptions.Author:SetText(GetAddOnMetadata("PowerAurasButtons", "Author"));
+	InterfaceOptions.Author:SetTextColor(1, 1, 1);
+	InterfaceOptions.Author:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -95);
+	InterfaceOptions.Author:SetJustifyH("LEFT");
+	InterfaceOptions.Author:SetJustifyV("TOP");
+
+	if(CoreFrame.__debug) then
+		InterfaceOptions.TitleDebug = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+			"GameFontNormalSmall");
+		InterfaceOptions.TitleDebug:SetText(L["Debug"] .. ":");
+		InterfaceOptions.TitleDebug:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 10, -110);
+		InterfaceOptions.TitleDebug:SetWidth(100);
+		InterfaceOptions.TitleDebug:SetJustifyH("RIGHT");
+		InterfaceOptions.TitleDebug:SetJustifyV("TOP");
+		InterfaceOptions.Debug = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+			"GameFontNormalSmall");
+		InterfaceOptions.Debug:SetText("|cFF00FF00Enabled|r");
+		InterfaceOptions.Debug:SetTextColor(1, 1, 1);
+		InterfaceOptions.Debug:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 115, -110);
+		InterfaceOptions.Debug:SetJustifyH("LEFT");
+		InterfaceOptions.Debug:SetJustifyV("TOP");
+	end
+
+	-- Now for the module switcher. Make a title...
+
+	InterfaceOptions.ModulesTitle = InterfaceOptions:CreateFontString(nil, "ARTWORK",
+		"GameFontNormal");
+	InterfaceOptions.ModulesTitle:SetText(L["Module Manager"]);
+	InterfaceOptions.ModulesTitle:SetPoint("TOP", InterfaceOptions, "TOP", 0, -130);
+	-- Make a scrolly area.
+	InterfaceOptions.Modules = CreateFrame("Frame", nil, InterfaceOptions);
+	InterfaceOptions.Modules:SetBackdrop({
+		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+		tile = true, tileSize = 16, edgeSize = 16,
+		insets = { left = 3, right = 3, top = 5, bottom = 3 }
+	});
+	InterfaceOptions.Modules:SetBackdropColor(0, 0, 0, 0.75);
+	InterfaceOptions.Modules:SetBackdropBorderColor(0.4, 0.4, 0.4);
+	InterfaceOptions.Modules:SetPoint("TOP", InterfaceOptions, "TOP", 0, -145);
+	InterfaceOptions.Modules:SetHeight(200);
+	InterfaceOptions.Modules:SetWidth(375);
+	-- List frame needs a scroll frame.
+	InterfaceOptions.Modules.Scroll = CreateFrame("ScrollFrame",
+		"PowerAurasButtons_ModuleScrollFrame", InterfaceOptions.Modules,
+		"UIPanelScrollFrameTemplate");
+	InterfaceOptions.Modules.Scroll:SetPoint("TOPLEFT", InterfaceOptions.Modules, "TOPLEFT", 5, -5);
+	InterfaceOptions.Modules.Scroll:SetPoint("BOTTOMRIGHT", InterfaceOptions.Modules,
+		"BOTTOMRIGHT", -26, 4);
+	-- Scroll frame needs something to actually scroll.
+	InterfaceOptions.Modules.List = CreateFrame("Frame", nil, InterfaceOptions.Modules.Scroll);
+	InterfaceOptions.Modules.List:SetPoint("TOPLEFT", InterfaceOptions.Modules.Scroll, "TOPLEFT");
+	-- Height needs to be set.
+	InterfaceOptions.Modules.List:SetHeight(0);
+	-- The height needs to match the content, but the width can be that of the box...
+	InterfaceOptions.Modules.List:SetWidth(350);
+	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
+	InterfaceOptions.Modules.Scroll:SetScrollChild(InterfaceOptions.Modules.List);
+	-- Store the row frames in this table - we'll reuse them as needed.
+	InterfaceOptions.Modules.List.Items = {};
+	InterfaceOptions.Modules.List.Rows = {};
+
+	-- Make a small function, hook it to OnShow. It'll scan the modules and update the list.
+	local scanModules;
+	scanModules = function()
+		-- Make a table of all modules that can be enabled/disabled.
+		wipe(InterfaceOptions.Modules.List.Items);
+		for module, frame in pairs(CoreFrame.Modules) do
+			if(frame.CanDisable) then tinsert(InterfaceOptions.Modules.List.Items, module); end
+		end
+		-- Hide existing rows.
+		for _, row in pairs(InterfaceOptions.Modules.List.Rows) do
+			row:Hide();
+		end
+		-- Using that, fill in the rows.
+		for i, module in pairs(InterfaceOptions.Modules.List.Items) do
+			-- Make rows dynamically and reuse existing ones.
+			if(not InterfaceOptions.Modules.List.Rows[i]) then
+				local row = CreateFrame("Frame", nil, InterfaceOptions.Modules.List);
+				-- Add textures.
+				row.Texture = row:CreateTexture(nil, "BACKGROUND");
+				row.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
+				row.Texture:SetAllPoints(row);
+				row.Texture:SetVertexColor(1, 1, 1, 0.15);
+				-- Height, anchor.
+				row:SetHeight(20);
+				row:SetPoint("TOPLEFT", InterfaceOptions.Modules.List, "TOPLEFT", 0, -((i-1)*20));
+				row:SetPoint("TOPRIGHT", InterfaceOptions.Modules.List, "TOPRIGHT", 0, -((i-1)*20));
+				-- Label.
+				row.Label = row:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+				row.Label:SetHeight(20);
+				row.Label:SetPoint("TOPLEFT", row, "TOPLEFT", 10, 0);
+				row.Label:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 10, 0);
+				-- And a delete button.
+				row.Button = CreateFrame("Button", nil, row);
+				row.Button:SetPoint("RIGHT", row, "RIGHT", -2, 0);
+				row.Button:SetWidth(16);
+				row.Button:SetHeight(16);
+				-- Register the row.
+				InterfaceOptions.Modules.List.Rows[i] = row;
+				-- And when you click, we toggle.
+				row.Button:SetScript("OnClick", function()
+					local module = row.Label:GetText();
+					if(CoreFrame:IsModuleEnabled(module)) then
+						-- Disable the module.
+						CoreFrame:SetModuleSetting(module, "Enabled", nil);
+					else
+						-- Enable the module.
+						CoreFrame:SetModuleSetting(module, "Enabled", true);
+					end
+					-- ReloadUI is needed :)
+					ModuleFrame:CreateGlowBoxWidget(InterfaceOptions);
+					-- Rescan.
+					scanModules();
+				end);
+				-- Tooltip.
+				ModuleFrame:RegisterConfigTooltip(row.Button, {
+					override = function()
+						-- Check module status.
+						if(CoreFrame:IsModuleEnabled(module)) then
+							GameTooltip:SetText(L["Disable Module"]);
+							GameTooltip:AddLine(L["Click to disable this module."], 1, 1, 1, 1);
+						else
+							GameTooltip:SetText(L["Enable Module"]);
+							GameTooltip:AddLine(L["Click to enable this module."], 1, 1, 1, 1);
+						end
+					end
+				});
+			end
+			-- Get row.
+			local row = InterfaceOptions.Modules.List.Rows[i];
+			-- Set stuff.
+			row.Label:SetText(module);
+			-- Is the module enabled?
+			if(CoreFrame:IsModuleEnabled(module)) then
+				-- Enabled, so show disable stuff and color the background greenish.
+				row.Button:SetNormalTexture("Interface\\FriendsFrame\\StatusIcon-DnD");
+				row.Button:SetHighlightTexture("Interface\\FriendsFrame\\StatusIcon-DnD", "BLEND");
+				row.Button:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
+				row.Button:GetHighlightTexture():SetVertexColor(1.0, 1.0, 1.0, 1.0);
+				row.Texture:SetVertexColor(0.3, 0.8, 0.3, 0.6);
+			else
+				-- Disabled. Show enable stuff and color BG red.
+				row.Button:SetNormalTexture("Interface\\FriendsFrame\\StatusIcon-Online");
+				row.Button:SetHighlightTexture("Interface\\FriendsFrame\\StatusIcon-Online",
+					"BLEND");
+				row.Button:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
+				row.Button:GetHighlightTexture():SetVertexColor(1.0, 1.0, 1.0, 1.0);
+				row.Texture:SetVertexColor(1.0, 0.5, 0.5, 1.0);
+			end
+			-- Add height to the list.
+			InterfaceOptions.Modules.List:SetHeight(i*20);
+			row:Show();
+		end
+	end
+	-- Set the script.
+	InterfaceOptions:SetScript("OnShow", scanModules);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateActionEditor
+
+Creates the action editing frame.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateActionEditor()
+	-- Make the editor frame.
+	ActionEditorBase = CreateFrame("Frame", nil, PowaBarConfigFrame, "TranslucentFrameTemplate");
+	ActionEditorBase:SetPoint("TOPLEFT", PowaBarConfigFrame, "TOPRIGHT", -13, 1);
+	ActionEditorBase:SetHeight(462);
+	ActionEditorBase:SetWidth(400);
+	ActionEditorBase:EnableMouse(true);
+	-- Make it look nice. Add a header.
+	ActionEditorBase.Header = ActionEditorBase:CreateTexture(nil, "ARTWORK");
+	ActionEditorBase.Header:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header");
+	ActionEditorBase.Header:SetPoint("TOP", ActionEditorBase, "TOP", 0, 13);
+	ActionEditorBase.Header:SetHeight(68);
+	ActionEditorBase.Header:SetWidth(300);
+	-- Shove a title in that too.
+	ActionEditorBase.Title = ActionEditorBase:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+	ActionEditorBase.Title:SetText(L["Action Editor"]);
+	ActionEditorBase.Title:SetPoint("TOP", ActionEditorBase.Header, "TOP", 0, -16);
+
+	-- Create the list frame.
+	ActionEditorList = CreateFrame("Frame", nil, ActionEditorBase);
+	ActionEditorList:SetBackdrop({
+		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+		tile = true, tileSize = 16, edgeSize = 16,
+		insets = { left = 3, right = 3, top = 5, bottom = 3 }
+	});
+	ActionEditorList:SetBackdropColor(0, 0, 0, 0.75);
+	ActionEditorList:SetBackdropBorderColor(0.4, 0.4, 0.4);
+	ActionEditorList:SetPoint("TOP", ActionEditorBase, "TOP", 0, -25);
+	ActionEditorList:SetHeight(200);
+	ActionEditorList:SetWidth(375);
+
+	-- List frame needs a scroll frame.
+	ActionEditorList.Scroll = CreateFrame("ScrollFrame", "PowerAurasButtons_ConfigScrollFrame",
+		ActionEditorList, "UIPanelScrollFrameTemplate");
+	ActionEditorList.Scroll:SetPoint("TOPLEFT", ActionEditorList, "TOPLEFT", 5, -5);
+	ActionEditorList.Scroll:SetPoint("BOTTOMRIGHT", ActionEditorList, "BOTTOMRIGHT", -26, 4);
+
+	-- Scroll frame needs something to actually scroll.
+	ActionEditorList.List = CreateFrame("Frame", nil, ActionEditorList.Scroll);
+	ActionEditorList.List:SetPoint("TOPLEFT", ActionEditorList.Scroll, "TOPLEFT");
+	-- Height needs to be set, we do this when an aura is selected.
+	ActionEditorList.List:SetHeight(0);
+	-- The height needs to match the content, but the width can be that of the box...
+	ActionEditorList.List:SetWidth(ActionEditorList.Scroll:GetWidth());
+	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
+	ActionEditorList.Scroll:SetScrollChild(ActionEditorList.List);
+	-- Store the row frames in this table - we'll reuse them as needed.
+	ActionEditorList.List.Items = {};
+
+	-- And finally, the editor frame.
+	ActionEditor = CreateFrame("Frame", nil, ActionEditorBase);
+	ActionEditor:SetBackdrop({
+		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+		tile = true, tileSize = 16, edgeSize = 16,
+		insets = { left = 3, right = 3, top = 5, bottom = 3 }
+	});
+	ActionEditor:SetBackdropColor(0, 0, 0, 0.75);
+	ActionEditor:SetBackdropBorderColor(0.4, 0.4, 0.4);
+	ActionEditor:SetPoint("TOP", ActionEditorList, "BOTTOM", 0, 0);
+	ActionEditor:SetHeight(225);
+	ActionEditor:SetWidth(375);
+	-- Helper functions for hiding/displaying elements.
+	ActionEditor.TogglePanel = function(self, show)
+		-- Check the show param.
+		if(show) then
+			-- Show then.
+			ActionEditor:Show();
+			ActionEditorBase:SetHeight(462);
+		else
+			-- Hide!
+			ActionEditor:Hide();
+			ActionEditorBase:SetHeight(237);
+		end
+	end
+	-- Need a scroll here too.
+	ActionEditor.Scroll = CreateFrame("ScrollFrame", "PowerAurasButtons_ActionScrollFrame",
+		ActionEditor, "UIPanelScrollFrameTemplate");
+	ActionEditor.Scroll:SetPoint("TOPLEFT", ActionEditor, "TOPLEFT", 5, -5);
+	ActionEditor.Scroll:SetPoint("BOTTOMRIGHT", ActionEditor, "BOTTOMRIGHT", -26, 4);
+
+	-- Scroll frame needs something to actually scroll.
+	ActionEditor.List = CreateFrame("Frame", nil, ActionEditor.Scroll);
+	ActionEditor.List:SetPoint("TOPLEFT", ActionEditor.Scroll, "TOPLEFT");
+	-- Height needs to be set, we do this when an aura is selected.
+	ActionEditor.List:SetHeight(0);
+	-- The height needs to match the content, but the width can be that of the box...
+	ActionEditor.List:SetWidth(ActionEditor.Scroll:GetWidth());
+	-- Add the list frame as a scroll child of our SUPER SCROLL FRAME.
+	ActionEditor.Scroll:SetScrollChild(ActionEditor.List);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateButtonWidget
+
+Creates a button widget for the CreateActionEditor function.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateButtonWidget(parent, text, icon, disable)
+	-- Make the button.
+	local button = CreateFrame("Button", nil, parent);
+	-- Style it.
+	button:SetHeight(26);
+	button:SetWidth(110);
+	button:SetBackdrop({
+		bgFile = "Interface\\QuestFrame\\UI-QuestLogTitleHighlight",
+		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+		tile = false, tileSize = 16, edgeSize = 16,
+		insets = { left = 3, right = 3, top = 3, bottom = 3 }
+	});
+	button:SetBackdropColor(1, 1, 1, 0.15);
+	button:SetBackdropBorderColor(0.4, 0.4, 0.4);
+	-- Disabled?
+	if(disable) then
+		button:SetAlpha(0.5);
+	else
+		-- Mouseover stuff.
+		button:SetScript("OnEnter", function()
+			button:SetBackdropColor(0.196, 0.388, 0.8, 1.0);
+		end);
+		button:SetScript("OnLeave", function()
+			if(not button.Selected) then button:SetBackdropColor(1, 1, 1, 0.15); end
+		end);
+	end
+
+	-- Label.
+	button.Label = button:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+	button.Label:SetHeight(26);
+	button.Label:SetPoint("CENTER", button, "CENTER", 0, 0);
+	button.Label:SetText(text);
+
+	-- Icon.
+	if(icon) then
+		button.Icon = button:CreateTexture(nil, "ARTWORK");
+		button.Icon:SetPoint("LEFT", button, "LEFT", 5, 0);
+		button.Icon:SetWidth(16);
+		button.Icon:SetHeight(16);
+		button.Icon:SetTexture(icon);
+	end
+
+	-- And add a couple of helpful functions to the button.
+	button.Select = function()
+		button.Selected = true;
+		button:SetBackdropColor(0.196, 0.388, 0.8, 1.0);
+	end;
+	button.Deselect = function()
+		button.Selected = nil;
+		button:SetBackdropColor(1, 1, 1, 0.15);
+	end;
+
+	-- Deselect by default..
+	button:Deselect();
+	-- Done.
+	return button;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateHeaderWidget
+
+Creates a header widget for the CreateActionEditor function.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateHeaderWidget(text, parent, y)
+	-- Make the label.
+	local label = parent:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+	label:SetHeight(20);
+	label:SetPoint("TOP", parent, "TOP", 0, y);
+	label:SetText(L[text]);
+	-- Header background stuff.
+	label.bg = parent:CreateTexture(nil, "ARTWORK");
+	label.bg:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
+	label.bg:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, y);
+	label.bg:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, y);
+	label.bg:SetHeight(20);
+	label.bg:SetVertexColor(1, 1, 1, 0.15);
+	-- Done.
+	return label;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateColorWidget
+
+Creates a color selection widget.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateColorWidget(parent)
+	-- Make.
+	frame = CreateFrame("Button", nil, parent);
+	frame:SetWidth(16);
+	frame:SetHeight(16);
+	frame.Swatch = frame:CreateTexture(nil, "OVERLAY");
+	frame.Swatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch");
+	frame.Swatch:SetAllPoints(frame);
+	frame.SwatchBG = frame:CreateTexture(nil, "BACKGROUND");
+	frame.SwatchBG:SetWidth(14);
+	frame.SwatchBG:SetHeight(14);
+	frame.SwatchBG:SetTexture(1, 1, 1, 1);
+	frame.SwatchBG:SetPoint("CENTER", frame.Swatch);
+	frame.SwatchTrans = frame:CreateTexture(nil, "BACKGROUND");
+	frame.SwatchTrans:SetWidth(12);
+	frame.SwatchTrans:SetHeight(12);
+	frame.SwatchTrans:SetTexture("Tileset\\Generic\\Checkers");
+	frame.SwatchTrans:SetTexCoord(.25, 0, 0.5, .25);
+	frame.SwatchTrans:SetDesaturated(true);
+	frame.SwatchTrans:SetVertexColor(1, 1, 1, 0.75);
+	frame.SwatchTrans:SetPoint("CENTER", frame.Swatch);
+	frame.SwatchTrans:Show();
+	-- Done.
+	return frame;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateGlowBoxWidget
+
+Creates a glowbox widget for the given frame. This by default shows a Reload Required message.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateGlowBoxWidget(parent)
+	-- Only make if needed.
+	if(not parent.GlowBox) then
+		-- Sort out the glowbox.
+		parent.GlowBox = CreateFrame("Frame", nil, parent, "GlowBoxTemplate");
+		parent.GlowBox:SetPoint("BOTTOMRIGHT", InterfaceOptionsFrameOkay, "TOPRIGHT", 0, 25);
+		parent.GlowBox:SetWidth(275);
+		parent.GlowBox:SetHeight(50);
+		parent.GlowBox.Arrow = CreateFrame("Frame", nil, parent.GlowBox, "GlowBoxArrowTemplate");
+		parent.GlowBox.Arrow:SetPoint("TOPRIGHT", parent.GlowBox, "BOTTOMRIGHT");
+		-- Glowbox titles.
+		parent.GlowBox.Title = parent.GlowBox:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+		parent.GlowBox.Title:SetText(L["Reload Required"]);
+		parent.GlowBox.Title:SetPoint("TOPLEFT", parent.GlowBox, "TOPLEFT", 10, -5);
+		parent.GlowBox.Title:SetPoint("TOPRIGHT", parent.GlowBox, "TOPRIGHT", -10, -5);
+		parent.GlowBox.Title:SetJustifyH("CENTER");
+		parent.GlowBox.Title:SetJustifyV("TOP");
+		-- And now text.
+		parent.GlowBox.Text = parent.GlowBox:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+		parent.GlowBox.Text:SetText(
+			L["You have altered settings which require an interface reload to take effect."]);
+		parent.GlowBox.Text:SetPoint("TOPLEFT", parent.GlowBox, "TOPLEFT", 10, -20);
+		parent.GlowBox.Text:SetPoint("BOTTOMRIGHT", parent.GlowBox, "BOTTOMRIGHT", -10, 5);
+		parent.GlowBox.Text:SetJustifyH("LEFT");
+		parent.GlowBox.Text:SetJustifyV("TOP");
+		parent.GlowBox.Text:SetTextColor(1, 1, 1);
+		-- Make the okay function on the parent reload the UI.
+		parent.okay = function()
+			-- Reload.
+			ReloadUI();
+		end
+	end
+	-- Show the glowbox.
+	parent.GlowBox:Show();
+end
+--[[
+----------------------------------------------------------------------------------------------------
+UpdateSelectedAura
+
+Updates the opened aura in the power auras config frame.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:UpdateSelectedAura(auraID, actionID)
+	-- Set aura.
+	Aura = auraID;
+	-- Get all actions for this aura.
+	local actions = Modules.Auras:GetAuraActions(auraID);
+	-- Hide all rows.
+	for _, row in pairs(ActionEditorList.List.Items) do
+		row:Hide();
+		row:Deselect();
+	end
+	-- Do we have actions?
+	if(actions and #(actions) > 0) then
+		-- It has actions. Go over them.
+		for actionID, actionData in pairs(actions) do
+			-- Fetch the item row.
+			local row = ModuleFrame:FetchActionRow(actionID);
+			-- Set the icon and text.
+			if(actionData["type"] == "spell" and actionData["id"]) then
+				row.Icon:SetTexture("Interface\\GossipFrame\\TrainerGossipIcon");
+				row.Label:SetText(GetSpellLink(actionData["id"]), L["Invalid spell ID"]);
+			elseif(actionData["type"] == "macro" and actionData["id"]) then
+				row.Icon:SetTexture("Interface\\GossipFrame\\BinderGossipIcon");
+				row.Label:SetText(GetMacroInfo(actionData["id"]) or L["Invalid macro ID"]);
+			elseif(actionData["type"] == "item" and actionData["id"]) then
+				row.Icon:SetTexture("Interface\\GossipFrame\\VendorGossipIcon");
+				row.Label:SetText(select(2, GetItemInfo(actionData["id"])), L["Invalid item ID"]);
+			else
+				row.Icon:SetTexture("Interface\\GossipFrame\\ActiveQuestIcon");
+				row.Label:SetText(L["No action set"]);
+			end
+			-- Show it.
+			row:Show();
+		end
+	elseif(not actions) then
+		-- See if actions is nil - if so, make some.
+		Modules.Auras:SetAuraActions(auraID, {});
+		actions = {};
+	end
+	-- Add the "add new item..." row.
+	local addRow = ModuleFrame:FetchActionAddRow();
+	addRow:SetPoint("TOPLEFT", ActionEditorList.List, "TOPLEFT", 0, -(#(actions)*20));
+	addRow:SetPoint("TOPRIGHT", ActionEditorList.List, "TOPRIGHT", 0, -(#(actions)*20));
+	-- Update the list frame height.
+	ActionEditorList.List:SetHeight((#(actions) + 1)*20);
+	-- Show frame.
+	ActionEditorBase:Show();
+	-- Reset selected action.
+	ModuleFrame:UpdateSelectedAction(actionID);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+UpdateSelectedAction
+
+Updates the selected action in the action editor frame.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:UpdateSelectedAction(actionID)
+	-- Update vars.
+	Action = actionID;
+	ActionData = actionID and Modules.Auras:GetAuraAction(Aura, actionID);
+	-- Make sure no other row is classed as 'selected'.
+	for id, row in pairs(ActionEditorList.List.Items) do
+		if(actionID and actionID == id) then row:Select(); else row:Deselect(); end
+	end
+	-- Right, was an action passed?
+	if(not actionID) then
+		-- Hide the actual editor frame.
+		ActionEditor:TogglePanel();
+	else
+		-- Show editor frame.
+		ActionEditor:TogglePanel(true);
+		-- Go over the editor frames and trigger an UpdateAction.
+		for _, frame in pairs(EditorFrames) do
+			frame:UpdateAction(ActionData);
+			frame:Show();
+		end
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+UpdateActionData
+
+Updates the action data for the selected action.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:UpdateActionData(index, value)
+	-- Set.
+	ActionData[index] = value;
+	-- Save.
+	Modules.Auras:SetAuraAction(Aura, Action, ActionData);
+	-- Reload.
+	ModuleFrame:UpdateSelectedAura(Aura, Action);
+	if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FetchActionAddRow
+
+Creates and returns the "Add new item..." row for the action list.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FetchActionAddRow()
+	-- Make if not exists.
+	if(not ActionEditorList.AddRow) then
+		local addRow = CreateFrame("Frame", nil, ActionEditorList.List);
+		addRow:EnableMouse(true);
+		-- Add textures.
+		addRow.Texture = addRow:CreateTexture(nil, "BACKGROUND");
+		addRow.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
+		addRow.Texture:SetAllPoints(addRow);
+		addRow.Texture:SetVertexColor(1, 1, 1, 0.15);
+		-- Add an onenter/onleave script for the highlight toggle.
+		addRow:SetScript("OnEnter", function()
+			addRow.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
+		end);
+		addRow:SetScript("OnLeave", function()
+			addRow.Texture:SetVertexColor(1, 1, 1, 0.15);
+		end);
+		-- Height, anchor.
+		addRow:SetHeight(20);
+		-- Label.
+		addRow.Label = addRow:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+		addRow.Label:SetHeight(20);
+		addRow.Label:SetPoint("TOPLEFT", addRow, "TOPLEFT", 24, 0);
+		addRow.Label:SetPoint("BOTTOMLEFT", addRow, "BOTTOMLEFT", 24, 0);
+		addRow.Label:SetText(L["Add new action..."]);
+		-- Event handler for clicking the row.
+		addRow:SetScript("OnMouseUp", function()
+			-- Pass the action creation call to the Auras module and reload.
+			ModuleFrame:UpdateSelectedAura(Aura, Modules.Auras:CreateAuraAction(Aura));
+		end);
+		-- Save.
+		ActionEditorList.AddRow = addRow;
+	end
+	-- Done.
+	return ActionEditorList.AddRow;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FetchActionRow
+
+Creates and returns an action editor row for the editor list. Reuses rows if they exist.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FetchActionRow(actionID)
+	-- Row exist or not?
+	if(not ActionEditorList.List.Items[actionID]) then
+		-- Make it.
+		local row = CreateFrame("Frame", nil, ActionEditorList.List);
+		row:EnableMouse(true);
+		-- Add textures.
+		row.Texture = row:CreateTexture(nil, "BACKGROUND");
+		row.Texture:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight");
+		row.Texture:SetAllPoints(row);
+		row.Texture:SetVertexColor(1, 1, 1, 0.15);
+		-- Add an onenter/onleave script for the highlight toggle.
+		row:SetScript("OnEnter", function()
+			row.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
+		end);
+		row:SetScript("OnLeave", function()
+			if(not row.Selected) then row.Texture:SetVertexColor(1, 1, 1, 0.15); end
+		end);
+		-- Height, anchor.
+		row:SetHeight(20);
+		row:SetPoint("TOPLEFT", ActionEditorList.List, "TOPLEFT", 0, -((actionID-1)*20));
+		row:SetPoint("TOPRIGHT", ActionEditorList.List, "TOPRIGHT", 0, -((actionID-1)*20));
+		-- Add an icon texture and a label.
+		row.Icon = row:CreateTexture(nil, "ARTWORK");
+		row.Icon:SetPoint("TOPLEFT", row, "TOPLEFT", 2, -2);
+		row.Icon:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 2, 2);
+		row.Icon:SetWidth(16);
+		-- Label.
+		row.Label = row:CreateFontString(nil, "ARTWORK", "GameFontNormal");
+		row.Label:SetHeight(20);
+		row.Label:SetPoint("TOPLEFT", row, "TOPLEFT", 24, 0);
+		row.Label:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 24, 0);
+		-- And a delete button.
+		row.Delete = CreateFrame("Button", nil, row);
+		row.Delete:SetNormalTexture("Interface\\FriendsFrame\\ClearBroadcastIcon");
+		row.Delete:SetHighlightTexture("Interface\\FriendsFrame\\ClearBroadcastIcon", "BLEND");
+		row.Delete:SetPoint("RIGHT", row, "RIGHT", -2, 0);
+		row.Delete:SetWidth(16);
+		row.Delete:SetHeight(16);
+		-- Put a tooltip onto the delete button.
+		ModuleFrame:RegisterConfigTooltip(row.Delete, {
+			title = "Delete Action",
+			text = "Click to delete this action."
+		});
+		-- Sort out the texture colours.
+		row.Delete:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.25);
+		row.Delete:GetHighlightTexture():SetVertexColor(0.75, 0.0, 0.0, 1.0);
+		-- When you click the delete button...Delete.
+		row.Delete:SetScript("OnClick", function()
+			-- Remove.
+			Modules.Auras:RemoveAuraAction(Aura, actionID);
+			-- Reload the aura.
+			ModuleFrame:UpdateSelectedAura(Aura);
+		end);
+		-- And when we click, trigger a chosen action update.
+		row:SetScript("OnMouseUp", function()
+			ModuleFrame:UpdateSelectedAction(actionID);
+		end);
+		-- And add a couple of helpful functions to the row.
+		row.Select = function()
+			row.Selected = true;
+			row.Texture:SetVertexColor(0.196, 0.388, 0.8, 1.0);
+		end;
+		row.Deselect = function()
+			row.Selected = nil;
+			row.Texture:SetVertexColor(1, 1, 1, 0.15);
+		end;
+		-- Save.
+		row:Deselect();
+		ActionEditorList.List.Items[actionID] = row;
+		-- Make sure it's hidden.
+		row:Hide();
+	end
+	-- Return it.
+	return ActionEditorList.List.Items[actionID];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterActionConfigFrame
+
+Appends an additional frame to the action editor window.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:RegisterActionConfigFrame(frame, position)
+	-- Was a position set?
+	if(position and EditorFramesCount >= position) then
+		-- Reparent the frame.
+		frame:SetParent(ActionEditor.List);
+		-- We're going to need to inject this frame into the position and move things as needed.
+		-- Thankfully, each frame is anchored to another so we just need to move the one we're
+		-- moving down.
+		local oldFrame = EditorFrames[position];
+		oldFrame:ClearAllPoints();
+		oldFrame:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -5);
+		oldFrame:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", 0, -5);
+		-- And position the new frame...
+		frame:SetPoint("TOPLEFT",
+			EditorFrames[(position-1)] or ActionEditor.List,
+			EditorFrames[(position-1)] and "BOTTOMLEFT" or "TOPLEFT",
+			0,
+			EditorFrames[(position-1)] and -5 or 0
+		);
+		frame:SetPoint("TOPRIGHT",
+			EditorFrames[(position-1)] or ActionEditor.List,
+			EditorFrames[(position-1)] and "BOTTOMRIGHT" or "TOPRIGHT",
+			0,
+			EditorFrames[(position-1)] and -5 or 0
+		);
+		-- Inject.
+		tinsert(EditorFrames, position, frame);
+		EditorFramesCount = EditorFramesCount+1;
+	else
+		-- Re-parent and re-position the frame as if no position was set.
+		frame:SetParent(ActionEditor.List);
+		frame:SetPoint("TOPLEFT",
+			EditorFrames[EditorFramesCount] or ActionEditor.List,
+			EditorFrames[EditorFramesCount] and "BOTTOMLEFT" or "TOPLEFT",
+			0,
+			EditorFrames[EditorFramesCount] and -5 or 0
+		);
+		frame:SetPoint("TOPRIGHT",
+			EditorFrames[EditorFramesCount] or ActionEditor.List,
+			EditorFrames[EditorFramesCount] and "BOTTOMRIGHT" or "TOPRIGHT",
+			0,
+			EditorFrames[EditorFramesCount] and -5 or 0
+		);
+		-- Add to the table.
+		tinsert(EditorFrames, frame);
+		EditorFramesCount = EditorFramesCount+1;
+	end
+	-- Alter the height of the scroll frame.
+	ActionEditor.List:SetHeight(ActionEditor.List:GetHeight() + frame:GetHeight() + 5);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterInterfaceOptionsFrame
+
+Appends an additional frame to the Interface Options panel.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:RegisterInterfaceOptionsFrame(name)
+	-- Make a child frame.
+	local childFrame = CreateFrame("Frame", nil, InterfaceOptions);
+	-- Set name and parent.
+	childFrame.name = name;
+	childFrame.parent = "Power Auras Classic: Buttons";
+	-- Add the child to the Interface Options panel.
+	InterfaceOptions_AddCategory(childFrame);
+	-- Make the frame a bit more snazzy with titles and crap.
+	childFrame.Title = childFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge");
+	childFrame.Title:SetText("Power Auras Classic: Buttons");
+	childFrame.Title:SetPoint("TOPLEFT", childFrame, "TOPLEFT", 10, -15);
+	-- Subtitle too.
+	childFrame.SubTitle = childFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall");
+	childFrame.SubTitle:SetText(L[name]);
+	childFrame.SubTitle:SetTextColor(1, 1, 1);
+	childFrame.SubTitle:SetPoint("TOPLEFT", childFrame, "TOPLEFT", 10, -40);
+	childFrame.SubTitle:SetPoint("TOPRIGHT", childFrame, "TOPRIGHT", -10, -40);
+	childFrame.SubTitle:SetHeight(30);
+	childFrame.SubTitle:SetJustifyH("LEFT");
+	childFrame.SubTitle:SetJustifyV("TOP");
+	-- And return it.
+	return childFrame;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+RegisterConfigTooltip
+
+Adds a tooltip to the given frame.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:RegisterConfigTooltip(frame, options)
+	-- Fill in anchor/offsets if blank.
+	if(not options) then options = {}; end
+	if(not options.anchor) then options.anchor = "ANCHOR_RIGHT"; end
+	if(not options.offsetX) then options.offsetX = 0; end
+	if(not options.offsetY) then options.offsetY = 0; end
+	if(not options.title) then options.title = ""; end
+	if(not options.text) then options.text = ""; end
+	-- Allow a tip refresh.
+	frame.RefreshTooltip = function()
+		-- Hide tip.
+		GameTooltip:Hide();
+		-- Reparent.
+		GameTooltip:SetOwner(frame, options.anchor, options.offsetX, options.offsetY);
+		-- Set back up.
+		if(not options.override) then
+			-- Go nuts brah.
+			GameTooltip:SetText(L[options.title]);
+			-- Enable line wrapping. I totally did NOT just find out that existed.
+			GameTooltip:AddLine(L[options.text], 1, 1, 1, 1);
+		else
+			-- Run the override func.
+			options.override();
+		end
+		-- Show tip.
+		GameTooltip:Show();
+	end
+	-- Use the RefreshTooltip function as a display method.
+	frame:SetScript("OnEnter", frame.RefreshTooltip);
+	-- Hide on leave.
+	frame:SetScript("OnLeave", function() GameTooltip:Hide(); end);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnModuleLoaded
+
+Fired by the module handler, contains the name of the loaded module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnModuleLoaded(module)
+	-- Bounce it to our events.
+	CoreFrame:FireModuleEvent("OnCreateConfigurationFrame", module);
+	CoreFrame:FireModuleEvent("OnCreateInterfaceOptionsFrame", module);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsEnabled
+
+Checks to see if the module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsEnabled()
+	return CoreFrame:GetModuleSetting("Config", "Enabled");
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FixSettings
+
+Fixes all saved variables and migrates older ones across.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FixSettings(force)
+	-- Do the module settings exist?
+	if(not CoreFrame:GetSetting("Config") or force) then
+		-- We'd best fix that then.
+		PowerAurasButtons_SettingsDB["Config"] = {
+			["Enabled"] = true
+		};
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Fix settings first.
+	ModuleFrame:FixSettings();
+	-- Make sure enabled.
+	if(not ModuleFrame:IsEnabled()) then
+		-- Disabling the config module is...Different. It still counts as a failure, dependency
+		-- wise, but it will allow you to still turn modules on and off.
+		ModuleFrame:CreateInterfaceOptions();
+		-- Done.
+		return nil;
+	end
+	-- Create the action editor frame.
+	ModuleFrame:CreateActionEditor();
+	-- Create the interface options pane.
+	ModuleFrame:CreateInterfaceOptions();
+	-- Create some events for modules to hook on to.
+	CoreFrame:RegisterModuleEvent("OnCreateConfigurationFrame");
+	CoreFrame:RegisterModuleEvent("OnCreateInterfaceOptionsFrame");
+	-- Fire those events for already loaded modules (passing nil as the module name).
+	CoreFrame:FireModuleEvent("OnCreateConfigurationFrame", nil);
+	CoreFrame:FireModuleEvent("OnCreateInterfaceOptionsFrame", nil);
+	-- Listen to the OnModuleLoaded event.
+	CoreFrame:RegisterModuleEventListener("OnModuleLoaded", ModuleFrame);
+	-- This function runs when the PA options pane opens.
+	local script = function()
+		-- Update the aura if it's valid and show the config frame if it's not up.
+		if(PowaAuras.Auras[PowaAuras.CurrentAuraId] and PowaBarConfigFrame:IsShown()) then
+			-- Update aura.
+			ModuleFrame:UpdateSelectedAura(PowaAuras.CurrentAuraId);
+		else
+			-- Hide if it's not valid or not open.
+			ActionEditorBase:Hide();
+		end
+	end
+	-- Add needed hooks.
+	PowaBarConfigFrame:HookScript("OnShow", script);
+	PowaBarConfigFrame:HookScript("OnHide", script);
+	hooksecurefunc(PowaAuras, "InitPage", script);
+	hooksecurefunc(PowaAuras, "UpdateMainOption", script);
+	-- Also hook copying/moving. We can move aura sets like that.
+	hooksecurefunc(PowaAuras, "DoCopyEffect", function(_, idFrom, idTo, isMove)
+		-- Figure out the config tables for each.
+		local oldConfig = PowerAurasButtons_CharacterAurasDB;
+		local newConfig = PowerAurasButtons_CharacterAurasDB;
+		if(idFrom > 120) then oldConfig = PowerAurasButtons_AurasDB; end
+		if(idTo > 120) then newConfig = PowerAurasButtons_AurasDB; end
+		-- See if we had any auras in these spots.
+		if(oldConfig[idFrom]) then
+			-- Right, place these at the new location.
+			newConfig[idTo] = ModuleFrame:tcopy(oldConfig[idFrom]);
+			-- Was it a move?
+			if(isMove) then
+				-- Remove the old config.
+				wipe(oldConfig[idFrom]);
+			end
+		end
+		-- Button update.
+		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
+	end);
+	-- And aura deleting (we would hook DeleteAura but it messes up with moving effects).
+	hooksecurefunc(PowaAuras, "OptionDeleteEffect", function(_, auraID)
+		-- Determine the config table this one belonged to.
+		local config = PowerAurasButtons_CharacterAurasDB;
+		if(auraID > 120) then config = PowerAurasButtons_AurasDB; end
+		-- Did it exist?
+		if(config[auraID] and not tContains(ReindexedAuras, auraID)) then
+			-- Remove it.
+			wipe(config[auraID]);
+		end
+		-- Clear the reindex table.
+		wipe(ReindexedAuras);
+		-- Button update.
+		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
+	end);
+	-- If you delete an aura, it'll cause a re-indexing of ones after (delete #1 and #2 moves).
+	hooksecurefunc(PowaAuras, "ReindexAura", function(_, idFrom, idTo)
+		-- Figure out the config tables for each.
+		local oldConfig = PowerAurasButtons_CharacterAurasDB;
+		local newConfig = PowerAurasButtons_CharacterAurasDB;
+		if(idFrom > 120) then oldConfig = PowerAurasButtons_AurasDB; end
+		if(idTo > 120) then newConfig = PowerAurasButtons_AurasDB; end
+		-- Move old to new.
+		if(oldConfig[idFrom]) then
+			-- Right, place these at the new location.
+			newConfig[idTo] = ModuleFrame:tcopy(oldConfig[idFrom]);
+			-- Reindexing does NOT cause DeleteAura to fire.
+			wipe(oldConfig[idFrom]);
+			-- Add this to the table of reindexed auras.
+			tinsert(ReindexedAuras, idTo);
+		end
+		-- Button update.
+		if(CoreFrame:IsModuleEnabled("Auras")) then Modules.Auras:ResetAuras(); end
+	end);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/TimerStacks.lua b/Modules/TimerStacks.lua
index c28e953..90431d7 100644
--- a/Modules/TimerStacks.lua
+++ b/Modules/TimerStacks.lua
@@ -1,466 +1,466 @@
---[[
-	PowerAurasButtons
-
-	Module: Timer/Stacks
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("TimerStacks", { "Buttons" }, true);
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-Variables
-	ButtonAuras        Stores a table of all buttons and auras which have timers or stack displays.
-	IsUpdating         Set to true when the OnUpdate script is activated, nil otherwise.
-	StackFrames        Stores a list of all stack frames on buttons.
-	ThrottleTimer      Stores the current throttle progression.
-	TimerFrames        Stores a list of all timer frames on buttons.
-----------------------------------------------------------------------------------------------------
---]]
-local ButtonAuras      = {};
-local IsUpdating       = nil;
-local StackFrames      = {};
-local ThrottleTimer    = 0;
-local TimerFrames      = {};
---[[
-----------------------------------------------------------------------------------------------------
-GetAuraTimer
-
-Returns the timer values for an aura.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetAuraTimer(aura)
-	-- Get the timer frame. Make sure aura exists too :)
-	if(not aura or not aura.Timer) then return; end
-	local timer = aura.Timer;
-	-- Most of this is copy paste to determine the timer.
-	if(timer.enabled==false and timer.InvertAuraBelow==0) then return; end
-	local newvalue = 0;
-	--- Determine the value to display in the timer
-	if (PowaAuras.ModTest) then
-		newvalue = random(0,99) + (random(0, 99) / 100);
-	elseif (timer.ShowActivation and timer.Start~=nil) then
-		newvalue = math.max(GetTime() - timer.Start, 0);
-	elseif (aura.timerduration > 0) then--- if a user defined timer is active for the aura override.
-		if (((aura.target or aura.targetfriend) and (PowaAuras.ResetTargetTimers == true))
-		or not timer.CustomDuration) then
-			timer.CustomDuration = aura.timerduration;
-		end
-		-- Was causing the timers to be cut in half.
-		-- else
-			-- timer.CustomDuration = math.max(timer.CustomDuration - elapsed, 0);
-		-- end
-		newvalue = timer.CustomDuration;
-	elseif (timer.DurationInfo and timer.DurationInfo > 0) then
-		newvalue = math.max(timer.DurationInfo - GetTime(), 0);
-	end
-	-- Righto, moving on. Record it.
-	return newvalue;
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetAuraStacks
-
-Returns the stacks display on an aura.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetAuraStacks(aura)
-	-- Make sure aura exists.
-	if(not aura or not aura.Stacks or not aura.Stacks.enabled) then return; end
-	-- Right then, record it.
-	return aura.Stacks.UpdateValueTo or aura.Stacks.lastShownValue;
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnAuraShow
-
-Adds the newly shown aura to the list of active timers.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnAuraShow(auraID)
-	-- Make sure the update script hasn't fallen off.
-	if(not IsUpdating) then
-		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
-		IsUpdating = true;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnAuraHide
-
-Removes the now hidden aura from any of the timer or stack frames.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnAuraHide(auraID)
-	-- Make sure the update script hasn't fallen off.
-	if(not IsUpdating) then
-		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
-		IsUpdating = true;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonProcess
-
-Resets the displayed auras for a specific button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonProcess(buttonID)
-	-- Wipe.
-	if(ButtonAuras[buttonID]) then wipe(ButtonAuras[buttonID]); end
-	-- Make sure the update script hasn't fallen off.
-	if(not IsUpdating) then
-		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
-		IsUpdating = true;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnButtonDisplayAura
-
-Adds the displayed aura to the list of active auras for the given button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnButtonDisplayAura(buttonID, auraID, actionData, actionID)
-	-- Add this aura if we need to.
-	if(not actionData["timer"] and not actionData["stacks"]) then return; end
-	if(not ButtonAuras[buttonID]) then ButtonAuras[buttonID] = {}; end
-	-- Store the action ID.
-	ButtonAuras[buttonID][auraID] = actionID;
-	-- Make sure the update script hasn't fallen off.
-	if(not IsUpdating) then
-		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
-		IsUpdating = true;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-GetCountdownText
-
-Converts time remaining to a nice value to display.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:GetCountdownText(timeLeft)
-	-- 5 types, depending on the time (seconds).
-	if(timeLeft >= 3600) then
-		-- Hour.
-		return format("%dh", floor(timeLeft/3600));
-	elseif(timeLeft >= 600) then
-		-- 10 minutes.
-		return format("%dm", floor(timeLeft/60));
-	elseif(timeLeft >= 60) then
-		-- 1 minute.
-		return format("%d:%02d", floor(timeLeft/60), floor(timeLeft%60));
-	elseif(timeLeft >= 10) then
-		-- Displays pure seconds while over the threshold (or 10).
-		return floor(timeLeft);
-	elseif(timeLeft >= 0) then
-		-- Displays milliseconds too.
-		return format("%.1f", floor(timeLeft*10)/10);
-	else
-		-- If something odd happened, do a 0.
-		return 0;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-FetchTimerFrame
-
-Fetches/creates the timer frame for the button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FetchTimerFrame(button, key)
-	-- Get the settings.
-	local settings = CoreFrame:GetSetting("TimerStacks");
-	-- So, does it need one?
-	if(not TimerFrames[key]) then
-		-- Overlay frame check.
-		local overlay = ModuleFrame:FetchOverlayFrame(button);
-		-- Make it.
-		TimerFrames[key] = overlay:CreateFontString(nil, "OVERLAY");
-		-- Extract anchor data, replace parent.
-		local to, parent, from, x, y = unpack(settings.TimerAnchors);
-		parent = overlay;
-		-- Anchor.
-		TimerFrames[key]:SetPoint(to, parent, from, x, y);
-		-- Prettify it.
-		TimerFrames[key]:SetTextColor(unpack(settings.TimerColours));
-		local isValid = TimerFrames[key]:SetFont(unpack(settings.TimerFont));
-		if(not isValid) then
-			-- Font not valid, replace with default.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = "Fonts\\FRIZQT__.TTF";
-			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = "Friz Quadrata TT";
-			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"]));
-		end
-	end
-	-- Done.
-	return TimerFrames[key];
-end
---[[
-----------------------------------------------------------------------------------------------------
-FetchStacksFrame
-
-Fetches/creates the stacks frame for the button.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FetchStacksFrame(button, key)
-	-- Get the settings.
-	local settings = CoreFrame:GetSetting("TimerStacks");
-	-- So, does it need one?
-	if(not StackFrames[key]) then
-		-- Overlay frame check.
-		local overlay = ModuleFrame:FetchOverlayFrame(button);
-		-- Make it.
-		StackFrames[key] = overlay:CreateFontString(nil, "OVERLAY");
-		-- Extract anchor data, replace parent.
-		local to, parent, from, x, y = unpack(settings.StacksAnchors);
-		parent = overlay;
-		-- Anchor.
-		StackFrames[key]:SetPoint(to, parent, from, x, y);
-		-- Prettify it.
-		StackFrames[key]:SetTextColor(unpack(settings.StacksColours));
-		local isValid = StackFrames[key]:SetFont(unpack(settings.StacksFont));
-		if(not isValid) then
-			-- Font not valid, replace with default.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = "Fonts\\FRIZQT__.TTF";
-			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = "Friz Quadrata TT";
-			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"]));
-		end
-	end
-	-- Done.
-	return StackFrames[key];
-end
---[[
-----------------------------------------------------------------------------------------------------
-UpdateButtonFrames
-
-Updates all of the timer and stack frames when the configuration changes.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:UpdateButtonFrames()
-	-- Get the settings.
-	local settings = CoreFrame:GetSetting("TimerStacks");
-	-- Loop timers first.
-	for key, frame in pairs(TimerFrames) do
-		-- Extract anchor data, replace parent.
-		local to, parent, from, x, y = unpack(settings.TimerAnchors);
-		parent = frame:GetParent();
-		-- Anchor.
-		frame:ClearAllPoints();
-		frame:SetPoint(to, parent, from, x, y);
-		-- Prettify it.
-		frame:SetTextColor(unpack(settings.TimerColours));
-		local isValid = frame:SetFont(unpack(settings.TimerFont));
-		if(not isValid) then
-			-- Font not valid, replace with default.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = "Fonts\\FRIZQT__.TTF";
-			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = "Friz Quadrata TT";
-			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"]));
-		end
-	end
-	-- Now loop stacks.
-	for key, frame in pairs(StackFrames) do
-		-- Extract anchor data, replace parent.
-		local to, parent, from, x, y = unpack(settings.StacksAnchors);
-		parent = frame:GetParent();
-		-- Anchor.
-		frame:ClearAllPoints();
-		frame:SetPoint(to, parent, from, x, y);
-		-- Prettify it.
-		frame:SetTextColor(unpack(settings.StacksColours));
-		local isValid = frame:SetFont(unpack(settings.StacksFont));
-		if(not isValid) then
-			-- Font not valid, replace with default.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = "Fonts\\FRIZQT__.TTF";
-			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = "Friz Quadrata TT";
-			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"]));
-		end
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-FetchOverlayFrame
-
-Creates a small frame on top of a button, so the text for stacks/timers correctly overlays glows.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FetchOverlayFrame(button)
-	-- Get the button ID.
-	local buttonID = button:GetName();
-	if(not _G[buttonID .. "_PowerAurasOverlay"]) then
-		local frame = CreateFrame("Frame", buttonID .. "_PowerAurasOverlay", button);
-		frame:SetAllPoints(button);
-		frame:SetFrameStrata("HIGH");
-		frame:Show();
-	end
-	-- Return it.
-	return _G[buttonID .. "_PowerAurasOverlay"];
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnUpdate
-
-Update loop. Updates the contents of the text displays on the buttons. Will detatch itself if
-there's no updates being performed. Throttled to 0.1s.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnUpdate(elapsed)
-	-- It's updating.
-	IsUpdating = true;
-	-- Throttle check.
-	ThrottleTimer = ThrottleTimer + elapsed;
-	-- Fix any huge and odd throttle jumps.
-	if(ThrottleTimer > 0.5) then ThrottleTimer = 0.1; end
-	-- Cap is moving depending on our requirements.
-	if(ThrottleTimer < 0.1) then return; end
-	-- Track total updates done.
-	local hasUpdated = nil;
-	-- Iterate over buttons.
-	for buttonID, auras in pairs(ButtonAuras) do
-		-- Figure out if this button is displaying stacks and timers.
-		local timersDisplay = Modules.Buttons:GetButtonData(buttonID)["timer"];
-		local stacksDisplay = Modules.Buttons:GetButtonData(buttonID)["stacks"];
-		-- Calculate the longest of the auras for each.
-		local timerDuration, stackCount, timerText = 0, 0, "";
-		-- Get the appropriate frames.
-		local timerFrame, stackFrame;
-		timerFrame = ModuleFrame:FetchTimerFrame(_G[buttonID], buttonID);
-		stackFrame = ModuleFrame:FetchStacksFrame(_G[buttonID], buttonID);
-		-- Only calculate for updates if we are going to update.
-		if(timersDisplay or stacksDisplay) then
-			-- Iterate over auras.
-			for auraID, actionID in pairs(auras) do
-				-- Update the timers and stacks for this aura.
-				local timer = ModuleFrame:GetAuraTimer(PowaAuras.Auras[auraID]);
-				local stacks = ModuleFrame:GetAuraStacks(PowaAuras.Auras[auraID]);
-				local auraDisplays = Modules.Auras:GetAuraAction(auraID, actionID);
-				if(auraDisplays) then
-					-- Calculate the longest.
-					if(auraDisplays["timer"] and timerDuration < (timer or 0)) then
-						timerDuration = timer;
-					end
-					if(auraDisplays["stacks"] and stackCount < (stacks or 0)) then
-						stackCount = stacks;
-					end
-				end
-			end
-			-- If timer/stacks are nil, no update performed.
-			if(timerDuration > 0 and timersDisplay) then
-				-- Update done.
-				hasUpdated = true;
-				-- Make frames if needed, update text. Done.
-				timerText = ModuleFrame:GetCountdownText(timerDuration);
-				-- Save update calls.
-				if(timerFrame:GetText() ~= timerText) then
-					timerFrame:SetText(timerText);
-				end
-				-- Show.
-				if(not timerFrame:IsShown()) then
-					timerFrame:Show();
-				end
-			end
-			if(stackCount > 0 and stacksDisplay) then
-				-- Update done.
-				hasUpdated = true;
-				-- Make frames if needed, update text. Done.
-				if(tonumber(stackFrame:GetText(), 10) ~= stackCount) then
-					stackFrame:SetText(stackCount);
-				end
-				-- Show.
-				if(not stackFrame:IsShown()) then
-					stackFrame:Show();
-				end
-			end
-		end
-		-- Hide unused timer frames.
-		if((timerDuration == 0 or not timersDisplay) and timerFrame:IsShown()) then
-			timerFrame:Hide();
-		end
-		-- Hide unused stack frames.
-		if((stackCount == 0 or not stacksDisplay) and stackFrame:IsShown()) then
-			stackFrame:Hide();
-		end
-	end
-	-- Did we update at all?
-	if(not hasUpdated) then
-		-- No updates, so skip further ones.
-		ModuleFrame:SetScript("OnUpdate", nil);
-		IsUpdating = nil;
-	end
-	-- Reset throttle.
-	while(ThrottleTimer > 0.1) do
-		ThrottleTimer = ThrottleTimer - 0.1;
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnActionCreate
-
-Fired when an action is created. Used to set defaults in the newly made action ID.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnActionCreate(auraID, actionID)
-	-- Get action.
-	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
-	-- Write.
-	actionData["timer"] = nil;
-	actionData["stacks"] = nil;
-	-- Save.
-	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
-end
---[[
-----------------------------------------------------------------------------------------------------
-IsEnabled
-
-Checks to see if the module is enabled.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:IsEnabled()
-	return CoreFrame:GetModuleSetting("TimerStacks", "Enabled");
-end
---[[
-----------------------------------------------------------------------------------------------------
-FixSettings
-
-Fixes all saved variables and migrates older ones across.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:FixSettings(force)
-	-- Do the module settings exist?
-	if(not CoreFrame:GetSetting("TimerStacks") or force) then
-		-- We'd best fix that then.
-		PowerAurasButtons_SettingsDB["TimerStacks"] = {
-			["Enabled"] = true,
-			["TimerAnchors"] = { "BOTTOMLEFT", nil, "BOTTOMLEFT", 7, 5 },
-			["TimerColours"] = { 1, 1, 1, 1 },
-			["TimerFont"] = { "Fonts\\FRIZQT__.TTF", 11, "OUTLINE", "Friz Quadrata TT" },
-			["StacksAnchors"] = { "TOPRIGHT", nil, "TOPRIGHT", -7, -5 },
-			["StacksColours"] = { 1, 1, 1, 1 },
-			["StacksFont"] = { "Fonts\\FRIZQT__.TTF", 11, "OUTLINE", "Friz Quadrata TT" }
-		};
-	end
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Fix settings first.
-	ModuleFrame:FixSettings();
-	-- This module will not load if disabled.
-	if(not ModuleFrame:IsEnabled()) then
-		-- Count as an unsuccessful module load.
-		return nil;
-	end
-	-- Register module events for aura showing/hiding and button updates.
-	CoreFrame:RegisterModuleEventListener("OnButtonProcess", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnButtonDisplayAura", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnAuraShow", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnAuraHide", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: Timer/Stacks
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("TimerStacks", { "Buttons" }, true);
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+Variables
+	ButtonAuras        Stores a table of all buttons and auras which have timers or stack displays.
+	IsUpdating         Set to true when the OnUpdate script is activated, nil otherwise.
+	StackFrames        Stores a list of all stack frames on buttons.
+	ThrottleTimer      Stores the current throttle progression.
+	TimerFrames        Stores a list of all timer frames on buttons.
+----------------------------------------------------------------------------------------------------
+--]]
+local ButtonAuras      = {};
+local IsUpdating       = nil;
+local StackFrames      = {};
+local ThrottleTimer    = 0;
+local TimerFrames      = {};
+--[[
+----------------------------------------------------------------------------------------------------
+GetAuraTimer
+
+Returns the timer values for an aura.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetAuraTimer(aura)
+	-- Get the timer frame. Make sure aura exists too :)
+	if(not aura or not aura.Timer) then return; end
+	local timer = aura.Timer;
+	-- Most of this is copy paste to determine the timer.
+	if(timer.enabled==false and timer.InvertAuraBelow==0) then return; end
+	local newvalue = 0;
+	--- Determine the value to display in the timer
+	if (PowaAuras.ModTest) then
+		newvalue = random(0,99) + (random(0, 99) / 100);
+	elseif (timer.ShowActivation and timer.Start~=nil) then
+		newvalue = math.max(GetTime() - timer.Start, 0);
+	elseif (aura.timerduration > 0) then--- if a user defined timer is active for the aura override.
+		if (((aura.target or aura.targetfriend) and (PowaAuras.ResetTargetTimers == true))
+		or not timer.CustomDuration) then
+			timer.CustomDuration = aura.timerduration;
+		end
+		-- Was causing the timers to be cut in half.
+		-- else
+			-- timer.CustomDuration = math.max(timer.CustomDuration - elapsed, 0);
+		-- end
+		newvalue = timer.CustomDuration;
+	elseif (timer.DurationInfo and timer.DurationInfo > 0) then
+		newvalue = math.max(timer.DurationInfo - GetTime(), 0);
+	end
+	-- Righto, moving on. Record it.
+	return newvalue;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetAuraStacks
+
+Returns the stacks display on an aura.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetAuraStacks(aura)
+	-- Make sure aura exists.
+	if(not aura or not aura.Stacks or not aura.Stacks.enabled) then return; end
+	-- Right then, record it.
+	return aura.Stacks.UpdateValueTo or aura.Stacks.lastShownValue;
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnAuraShow
+
+Adds the newly shown aura to the list of active timers.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnAuraShow(auraID)
+	-- Make sure the update script hasn't fallen off.
+	if(not IsUpdating) then
+		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
+		IsUpdating = true;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnAuraHide
+
+Removes the now hidden aura from any of the timer or stack frames.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnAuraHide(auraID)
+	-- Make sure the update script hasn't fallen off.
+	if(not IsUpdating) then
+		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
+		IsUpdating = true;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonProcess
+
+Resets the displayed auras for a specific button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonProcess(buttonID)
+	-- Wipe.
+	if(ButtonAuras[buttonID]) then wipe(ButtonAuras[buttonID]); end
+	-- Make sure the update script hasn't fallen off.
+	if(not IsUpdating) then
+		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
+		IsUpdating = true;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnButtonDisplayAura
+
+Adds the displayed aura to the list of active auras for the given button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnButtonDisplayAura(buttonID, auraID, actionData, actionID)
+	-- Add this aura if we need to.
+	if(not actionData["timer"] and not actionData["stacks"]) then return; end
+	if(not ButtonAuras[buttonID]) then ButtonAuras[buttonID] = {}; end
+	-- Store the action ID.
+	ButtonAuras[buttonID][auraID] = actionID;
+	-- Make sure the update script hasn't fallen off.
+	if(not IsUpdating) then
+		ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate);
+		IsUpdating = true;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+GetCountdownText
+
+Converts time remaining to a nice value to display.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:GetCountdownText(timeLeft)
+	-- 5 types, depending on the time (seconds).
+	if(timeLeft >= 3600) then
+		-- Hour.
+		return format("%dh", floor(timeLeft/3600));
+	elseif(timeLeft >= 600) then
+		-- 10 minutes.
+		return format("%dm", floor(timeLeft/60));
+	elseif(timeLeft >= 60) then
+		-- 1 minute.
+		return format("%d:%02d", floor(timeLeft/60), floor(timeLeft%60));
+	elseif(timeLeft >= 10) then
+		-- Displays pure seconds while over the threshold (or 10).
+		return floor(timeLeft);
+	elseif(timeLeft >= 0) then
+		-- Displays milliseconds too.
+		return format("%.1f", floor(timeLeft*10)/10);
+	else
+		-- If something odd happened, do a 0.
+		return 0;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FetchTimerFrame
+
+Fetches/creates the timer frame for the button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FetchTimerFrame(button, key)
+	-- Get the settings.
+	local settings = CoreFrame:GetSetting("TimerStacks");
+	-- So, does it need one?
+	if(not TimerFrames[key]) then
+		-- Overlay frame check.
+		local overlay = ModuleFrame:FetchOverlayFrame(button);
+		-- Make it.
+		TimerFrames[key] = overlay:CreateFontString(nil, "OVERLAY");
+		-- Extract anchor data, replace parent.
+		local to, parent, from, x, y = unpack(settings.TimerAnchors);
+		parent = overlay;
+		-- Anchor.
+		TimerFrames[key]:SetPoint(to, parent, from, x, y);
+		-- Prettify it.
+		TimerFrames[key]:SetTextColor(unpack(settings.TimerColours));
+		local isValid = TimerFrames[key]:SetFont(unpack(settings.TimerFont));
+		if(not isValid) then
+			-- Font not valid, replace with default.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = "Fonts\\FRIZQT__.TTF";
+			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = "Friz Quadrata TT";
+			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"]));
+		end
+	end
+	-- Done.
+	return TimerFrames[key];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FetchStacksFrame
+
+Fetches/creates the stacks frame for the button.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FetchStacksFrame(button, key)
+	-- Get the settings.
+	local settings = CoreFrame:GetSetting("TimerStacks");
+	-- So, does it need one?
+	if(not StackFrames[key]) then
+		-- Overlay frame check.
+		local overlay = ModuleFrame:FetchOverlayFrame(button);
+		-- Make it.
+		StackFrames[key] = overlay:CreateFontString(nil, "OVERLAY");
+		-- Extract anchor data, replace parent.
+		local to, parent, from, x, y = unpack(settings.StacksAnchors);
+		parent = overlay;
+		-- Anchor.
+		StackFrames[key]:SetPoint(to, parent, from, x, y);
+		-- Prettify it.
+		StackFrames[key]:SetTextColor(unpack(settings.StacksColours));
+		local isValid = StackFrames[key]:SetFont(unpack(settings.StacksFont));
+		if(not isValid) then
+			-- Font not valid, replace with default.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = "Fonts\\FRIZQT__.TTF";
+			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = "Friz Quadrata TT";
+			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"]));
+		end
+	end
+	-- Done.
+	return StackFrames[key];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+UpdateButtonFrames
+
+Updates all of the timer and stack frames when the configuration changes.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:UpdateButtonFrames()
+	-- Get the settings.
+	local settings = CoreFrame:GetSetting("TimerStacks");
+	-- Loop timers first.
+	for key, frame in pairs(TimerFrames) do
+		-- Extract anchor data, replace parent.
+		local to, parent, from, x, y = unpack(settings.TimerAnchors);
+		parent = frame:GetParent();
+		-- Anchor.
+		frame:ClearAllPoints();
+		frame:SetPoint(to, parent, from, x, y);
+		-- Prettify it.
+		frame:SetTextColor(unpack(settings.TimerColours));
+		local isValid = frame:SetFont(unpack(settings.TimerFont));
+		if(not isValid) then
+			-- Font not valid, replace with default.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = "Fonts\\FRIZQT__.TTF";
+			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = "Friz Quadrata TT";
+			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"]));
+		end
+	end
+	-- Now loop stacks.
+	for key, frame in pairs(StackFrames) do
+		-- Extract anchor data, replace parent.
+		local to, parent, from, x, y = unpack(settings.StacksAnchors);
+		parent = frame:GetParent();
+		-- Anchor.
+		frame:ClearAllPoints();
+		frame:SetPoint(to, parent, from, x, y);
+		-- Prettify it.
+		frame:SetTextColor(unpack(settings.StacksColours));
+		local isValid = frame:SetFont(unpack(settings.StacksFont));
+		if(not isValid) then
+			-- Font not valid, replace with default.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = "Fonts\\FRIZQT__.TTF";
+			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = "Friz Quadrata TT";
+			frame:SetFont(unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"]));
+		end
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FetchOverlayFrame
+
+Creates a small frame on top of a button, so the text for stacks/timers correctly overlays glows.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FetchOverlayFrame(button)
+	-- Get the button ID.
+	local buttonID = button:GetName();
+	if(not _G[buttonID .. "_PowerAurasOverlay"]) then
+		local frame = CreateFrame("Frame", buttonID .. "_PowerAurasOverlay", button);
+		frame:SetAllPoints(button);
+		frame:SetFrameStrata("HIGH");
+		frame:Show();
+	end
+	-- Return it.
+	return _G[buttonID .. "_PowerAurasOverlay"];
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnUpdate
+
+Update loop. Updates the contents of the text displays on the buttons. Will detatch itself if
+there's no updates being performed. Throttled to 0.1s.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnUpdate(elapsed)
+	-- It's updating.
+	IsUpdating = true;
+	-- Throttle check.
+	ThrottleTimer = ThrottleTimer + elapsed;
+	-- Fix any huge and odd throttle jumps.
+	if(ThrottleTimer > 0.5) then ThrottleTimer = 0.1; end
+	-- Cap is moving depending on our requirements.
+	if(ThrottleTimer < 0.1) then return; end
+	-- Track total updates done.
+	local hasUpdated = nil;
+	-- Iterate over buttons.
+	for buttonID, auras in pairs(ButtonAuras) do
+		-- Figure out if this button is displaying stacks and timers.
+		local timersDisplay = Modules.Buttons:GetButtonData(buttonID)["timer"];
+		local stacksDisplay = Modules.Buttons:GetButtonData(buttonID)["stacks"];
+		-- Calculate the longest of the auras for each.
+		local timerDuration, stackCount, timerText = 0, 0, "";
+		-- Get the appropriate frames.
+		local timerFrame, stackFrame;
+		timerFrame = ModuleFrame:FetchTimerFrame(_G[buttonID], buttonID);
+		stackFrame = ModuleFrame:FetchStacksFrame(_G[buttonID], buttonID);
+		-- Only calculate for updates if we are going to update.
+		if(timersDisplay or stacksDisplay) then
+			-- Iterate over auras.
+			for auraID, actionID in pairs(auras) do
+				-- Update the timers and stacks for this aura.
+				local timer = ModuleFrame:GetAuraTimer(PowaAuras.Auras[auraID]);
+				local stacks = ModuleFrame:GetAuraStacks(PowaAuras.Auras[auraID]);
+				local auraDisplays = Modules.Auras:GetAuraAction(auraID, actionID);
+				if(auraDisplays) then
+					-- Calculate the longest.
+					if(auraDisplays["timer"] and timerDuration < (timer or 0)) then
+						timerDuration = timer;
+					end
+					if(auraDisplays["stacks"] and stackCount < (stacks or 0)) then
+						stackCount = stacks;
+					end
+				end
+			end
+			-- If timer/stacks are nil, no update performed.
+			if(timerDuration > 0 and timersDisplay) then
+				-- Update done.
+				hasUpdated = true;
+				-- Make frames if needed, update text. Done.
+				timerText = ModuleFrame:GetCountdownText(timerDuration);
+				-- Save update calls.
+				if(timerFrame:GetText() ~= timerText) then
+					timerFrame:SetText(timerText);
+				end
+				-- Show.
+				if(not timerFrame:IsShown()) then
+					timerFrame:Show();
+				end
+			end
+			if(stackCount > 0 and stacksDisplay) then
+				-- Update done.
+				hasUpdated = true;
+				-- Make frames if needed, update text. Done.
+				if(tonumber(stackFrame:GetText(), 10) ~= stackCount) then
+					stackFrame:SetText(stackCount);
+				end
+				-- Show.
+				if(not stackFrame:IsShown()) then
+					stackFrame:Show();
+				end
+			end
+		end
+		-- Hide unused timer frames.
+		if((timerDuration == 0 or not timersDisplay) and timerFrame:IsShown()) then
+			timerFrame:Hide();
+		end
+		-- Hide unused stack frames.
+		if((stackCount == 0 or not stacksDisplay) and stackFrame:IsShown()) then
+			stackFrame:Hide();
+		end
+	end
+	-- Did we update at all?
+	if(not hasUpdated) then
+		-- No updates, so skip further ones.
+		ModuleFrame:SetScript("OnUpdate", nil);
+		IsUpdating = nil;
+	end
+	-- Reset throttle.
+	while(ThrottleTimer > 0.1) do
+		ThrottleTimer = ThrottleTimer - 0.1;
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnActionCreate
+
+Fired when an action is created. Used to set defaults in the newly made action ID.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnActionCreate(auraID, actionID)
+	-- Get action.
+	local actionData = Modules.Auras:GetAuraAction(auraID, actionID);
+	-- Write.
+	actionData["timer"] = nil;
+	actionData["stacks"] = nil;
+	-- Save.
+	Modules.Auras:SetAuraAction(auraID, actionID, actionData);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+IsEnabled
+
+Checks to see if the module is enabled.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:IsEnabled()
+	return CoreFrame:GetModuleSetting("TimerStacks", "Enabled");
+end
+--[[
+----------------------------------------------------------------------------------------------------
+FixSettings
+
+Fixes all saved variables and migrates older ones across.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:FixSettings(force)
+	-- Do the module settings exist?
+	if(not CoreFrame:GetSetting("TimerStacks") or force) then
+		-- We'd best fix that then.
+		PowerAurasButtons_SettingsDB["TimerStacks"] = {
+			["Enabled"] = true,
+			["TimerAnchors"] = { "BOTTOMLEFT", nil, "BOTTOMLEFT", 7, 5 },
+			["TimerColours"] = { 1, 1, 1, 1 },
+			["TimerFont"] = { "Fonts\\FRIZQT__.TTF", 11, "OUTLINE", "Friz Quadrata TT" },
+			["StacksAnchors"] = { "TOPRIGHT", nil, "TOPRIGHT", -7, -5 },
+			["StacksColours"] = { 1, 1, 1, 1 },
+			["StacksFont"] = { "Fonts\\FRIZQT__.TTF", 11, "OUTLINE", "Friz Quadrata TT" }
+		};
+	end
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Fix settings first.
+	ModuleFrame:FixSettings();
+	-- This module will not load if disabled.
+	if(not ModuleFrame:IsEnabled()) then
+		-- Count as an unsuccessful module load.
+		return nil;
+	end
+	-- Register module events for aura showing/hiding and button updates.
+	CoreFrame:RegisterModuleEventListener("OnButtonProcess", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnButtonDisplayAura", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnAuraShow", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnAuraHide", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/Modules/TimerStacksConfig.lua b/Modules/TimerStacksConfig.lua
index 90e073e..b01a312 100644
--- a/Modules/TimerStacksConfig.lua
+++ b/Modules/TimerStacksConfig.lua
@@ -1,692 +1,692 @@
---[[
-	PowerAurasButtons
-
-	Module: TimerStacksConfig
---]]
--- Create module frames.
-local CoreFrame        = PowerAurasButtons;
-local ModuleFrame      = CoreFrame:RegisterModule("TimerStacksConfig", { "TimerStacks", "Config" });
-local Modules          = CoreFrame.Modules;
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateConfigurationFrame
-
-Creates the configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateConfigurationFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Make the parent frame.
-	local ActionEditor = CreateFrame("Frame", nil, UIParent);
-	ActionEditor:SetHeight(51);
-	-- Label.
-	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Timer/Stacks",
-		ActionEditor, 0);
-	-- Display timers?
-	ActionEditor.DisplayTimer = Modules.Config:CreateButtonWidget(ActionEditor, "Display Timer");
-	ActionEditor.DisplayTimer:SetPoint("TOP", ActionEditor, "TOP", -60, -25);
-	ActionEditor.DisplayTimer:SetScript("OnClick", function(self)
-		-- Toggle self.
-		if(self.Selected) then
-			self:Deselect();
-			Modules.Config:UpdateActionData("timer", nil);
-		else
-			self:Select();
-			Modules.Config:UpdateActionData("timer", true);
-		end
-	end);
-	-- Display stacks?
-	ActionEditor.DisplayStacks = Modules.Config:CreateButtonWidget(ActionEditor, "Display Stacks");
-	ActionEditor.DisplayStacks:SetPoint("TOP", ActionEditor, "TOP", 60, -25);
-	ActionEditor.DisplayStacks:SetScript("OnClick", function(self)
-		-- Toggle self.
-		if(self.Selected) then
-			self:Deselect();
-			Modules.Config:UpdateActionData("stacks", nil);
-		else
-			self:Select();
-			Modules.Config:UpdateActionData("stacks", true);
-		end
-	end);
-	-- Tooltips (localization handled by the config module)
-	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayTimer, {
-		title = "Display Timer",
-		text = "Allows this button to display any enabled timers this aura has."
-	});
-	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayStacks, {
-		title = "Display Stacks",
-		text = "Allows this button to display any enabled stacks this aura has."
-	});
-	-- Add the necessary functions.
-	ActionEditor.UpdateAction = function(self, actionData)
-		if(actionData["timer"]) then
-			ActionEditor.DisplayTimer:Select();
-		else
-			ActionEditor.DisplayTimer:Deselect();
-		end
-		if(actionData["stacks"]) then
-			ActionEditor.DisplayStacks:Select();
-		else
-			ActionEditor.DisplayStacks:Deselect();
-		end
-	end;
-	-- Done.
-	Modules.Config:RegisterActionConfigFrame(ActionEditor, 3);
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnCreateInterfaceOptionsFrame
-
-Creates the interface options configuration frame for the Config module.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnCreateInterfaceOptionsFrame(name)
-	-- Only do this if the name matches the module name.
-	if(name ~= ModuleFrame.Name and name) then return; end
-	-- Split into two functions so I don't kill myself.
-	ModuleFrame:CreateInterfaceOptionsTimerFrame();
-	ModuleFrame:CreateInterfaceOptionsStacksFrame();
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateInterfaceOptionsTimerFrame
-
-Creates the timers configuration editor.
-
-WARNING: This function will drive you insane. I'm not optimizing it, I NEVER WANT TO SEE IT AGAIN.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateInterfaceOptionsTimerFrame()
-	-- Register the timers part.
-	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Timers");
-	-- Add some header(s).
-	InterfaceOptions.AnchorHeader = Modules.Config:CreateHeaderWidget("Timer Anchors",
-		InterfaceOptions, -60);
-	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -60);
-	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -60);
-	-- Timer anchoring first.
-	InterfaceOptions.TimerAnchor = CreateFrame("Frame", "PowerAurasButtons_TimerAnchor",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.TimerAnchor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -85);
-	-- Menu.
-	local menuList = {
-		"TOPLEFT",
-		"TOP",
-		"TOPRIGHT",
-		"LEFT",
-		"CENTER",
-		"RIGHT",
-		"BOTTOMLEFT",
-		"BOTTOM",
-		"BOTTOMRIGHT",
-	};
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.TimerAnchor, function(frame, level)
-		-- Go over those items.
-		for _, v in pairs(menuList) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = CoreFrame.L[v];
-			item.arg1 = v;
-			item.func = function(self, arg1)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in indexes 1 and 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][1] = arg1;
-				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][3] = arg1;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.TimerAnchor, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerAnchor, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerAnchor,
-		CoreFrame.L[CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[1]]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.TimerAnchor, "LEFT");
-
-	-- Now X/Y offsets. Two sliders.
-	InterfaceOptions.TimerOffsetX = CreateFrame("Slider", "PowerAurasButtons_TimerOffsetX",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.TimerOffsetX:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -130);
-	InterfaceOptions.TimerOffsetX:SetMinMaxValues(-32, 32);
-	InterfaceOptions.TimerOffsetX:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[4]);
-	InterfaceOptions.TimerOffsetX:SetValueStep(1);
-	InterfaceOptions.TimerOffsetX:SetWidth(125);
-
-	PowerAurasButtons_TimerOffsetXLow:SetText("-32");
-	PowerAurasButtons_TimerOffsetXHigh:SetText("32");
-	PowerAurasButtons_TimerOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[4] .. ")");
-	-- Update on value change.
-	InterfaceOptions.TimerOffsetX:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][4] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_TimerOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-
-	InterfaceOptions.TimerOffsetY = CreateFrame("Slider", "PowerAurasButtons_TimerOffsetY",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.TimerOffsetY:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 165, -130);
-	InterfaceOptions.TimerOffsetY:SetMinMaxValues(-32, 32);
-	InterfaceOptions.TimerOffsetY:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[5]);
-	InterfaceOptions.TimerOffsetY:SetValueStep(1);
-	InterfaceOptions.TimerOffsetY:SetWidth(125);
-
-	PowerAurasButtons_TimerOffsetYLow:SetText("-32");
-	PowerAurasButtons_TimerOffsetYHigh:SetText("32");
-	PowerAurasButtons_TimerOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[5] .. ")");
-	-- Update on value change.
-	InterfaceOptions.TimerOffsetY:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][5] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_TimerOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-	-- Add some header(s).
-	InterfaceOptions.FontHeader = Modules.Config:CreateHeaderWidget("Timer Font",
-		InterfaceOptions, -165);
-	InterfaceOptions.FontHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -165);
-	InterfaceOptions.FontHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -165);
-
-	-- Font selection.
-	InterfaceOptions.TimerFont = CreateFrame("Frame", "PowerAurasButtons_TimerFont",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.TimerFont:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -200);
-	-- Menu.
-	local fonts = {
-		["Arial Narrow"] = "Fonts\\ARIALN.ttf",
-		["Friz Quadrata TT"] = "Fonts\\FRIZQT_.ttf",
-		["Morpheus"] = "Fonts\\MORPHEUS.ttf",
-		["Skurri"] = "Fonts\\skurri.ttf",
-	};
-	-- Figure out if we're using default fonts or LSM.
-	local LSMFonts;
-	if(LibStub) then
-		-- Try LSM.
-		local LSM = LibStub("LibSharedMedia-3.0", true);
-		if(LSM) then
-			-- Get all fonts.
-			LSMFonts = LSM:HashTable(LSM.MediaType.FONT);
-		end
-	end
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.TimerFont, function(frame, level)
-		-- Go over those items.
-		for k, v in pairs(LSMFonts or fonts) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = k;
-			item.arg1 = v;
-			item.arg2 = k;
-			item.func = function(self, arg1, arg2)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in indexes 1 and 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = arg1;
-				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = arg2;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.TimerFont, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerFont, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerFont,
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.TimerFont, "LEFT");
-
-	-- Font size slider.
-	InterfaceOptions.TimerFontSize = CreateFrame("Slider", "PowerAurasButtons_TimerFontSize",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.TimerFontSize:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 210, -205);
-	InterfaceOptions.TimerFontSize:SetMinMaxValues(1, 24);
-	InterfaceOptions.TimerFontSize:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerFont")[2]);
-	InterfaceOptions.TimerFontSize:SetValueStep(1);
-	InterfaceOptions.TimerFontSize:SetWidth(125);
-	PowerAurasButtons_TimerFontSizeLow:SetText("-32");
-	PowerAurasButtons_TimerFontSizeHigh:SetText("32");
-	PowerAurasButtons_TimerFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "TimerFont")[2] .. ")");
-	-- Update on value change.
-	InterfaceOptions.TimerFontSize:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][2] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_TimerFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-
-	-- Outline selector.
-	InterfaceOptions.TimerOutline = CreateFrame("Frame", "PowerAurasButtons_TimerOutline",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.TimerOutline:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -230);
-	-- Menu.
-	local menuList = {
-		"OUTLINE",
-		"THICKOUTLINE",
-		"MONOCHROME",
-		"OUTLINE, MONOCHROME",
-		"THICKOUTLINE, MONOCHROME"
-	};
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.TimerOutline, function(frame, level)
-		-- Go over those items.
-		for _, v in pairs(menuList) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = v;
-			item.arg1 = v;
-			item.func = function(self, arg1, arg2)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in index 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][3] = arg1;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.TimerOutline, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerOutline, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerOutline,
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][3]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.TimerOutline, "LEFT");
-
-	-- Font color. WE'RE ALMOST DONE.
-	InterfaceOptions.TimerColor = Modules.Config:CreateColorWidget(InterfaceOptions);
-	InterfaceOptions.TimerColor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 205, -236);
-	InterfaceOptions.TimerColor:SetScript("OnClick", function()
-		-- Display the color picker.
-		ColorPickerFrame:SetColorRGB(InterfaceOptions.TimerColor.Swatch:GetVertexColor());
-		-- Allow transparency.
-		ColorPickerFrame.hasOpacity = nil;
-		ColorPickerFrame.opacity = 1;
-		ColorPickerFrame.previousValues = InterfaceOptions.TimerColor.Swatch.Backup;
-		-- Save functions.
-		local saveFunc = function(restore)
-			-- Locals.
-			local r, g, b, a = nil, nil, nil, 1;
-			-- Get values.
-			if(not restore) then
-				r, g, b = ColorPickerFrame:GetColorRGB();
-			else
-				-- Restoring from restore table.
-				r, g, b, a = unpack(restore);
-			end
-			-- Save.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"] = { r, g, b, a };
-			InterfaceOptions.TimerColor.Swatch:SetVertexColor(r, g, b, a);
-			InterfaceOptions.TimerColor.Swatch.Backup = { r, g, b, a };
-			-- Trigger update.
-			Modules.TimerStacks:UpdateButtonFrames();
-		end;
-		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
-		-- Go.
-		ColorPickerFrame:Hide();
-		ColorPickerFrame:Show();
-	end);
-	-- Final bits.
-	InterfaceOptions.TimerColor.Swatch:SetVertexColor(
-		unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"]));
-	InterfaceOptions.TimerColor.Swatch.Backup =
-		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"];
-
-	-- Tooltips.
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerAnchor, {
-		title = "Anchor",
-		text = "Controls the anchor point of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOffsetX, {
-		title = "X Offset",
-		text = "Controls the X co-ordinate position of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOffsetY, {
-		title = "Y Offset",
-		text = "Controls the Y co-ordinate position of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerFont, {
-		title = "Font",
-		text = "Controls the name of the font to display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerFontSize, {
-		title = "Font Size",
-		text = "Controls the font size."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOutline, {
-		title = "Font Outline",
-		text = "Controls the outline of the font."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerColor, {
-		title = "Font Color",
-		text = "Controls color of the font."
-	});
-end
---[[
-----------------------------------------------------------------------------------------------------
-CreateInterfaceOptionsStacksFrame
-
-Creates the stacks configuration editor.
-
-WARNING: This function will drive you insane. I'm not optimizing it, I NEVER WANT TO SEE IT AGAIN.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:CreateInterfaceOptionsStacksFrame()
-	-- Register the Stacks part.
-	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Stacks");
-	-- Add some header(s).
-	InterfaceOptions.AnchorHeader = Modules.Config:CreateHeaderWidget("Stacks Anchors",
-		InterfaceOptions, -60);
-	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -60);
-	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -60);
-	-- Stacks anchoring first.
-	InterfaceOptions.StacksAnchor = CreateFrame("Frame", "PowerAurasButtons_StacksAnchor",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.StacksAnchor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -85);
-	-- Menu.
-	local menuList = {
-		"TOPLEFT",
-		"TOP",
-		"TOPRIGHT",
-		"LEFT",
-		"CENTER",
-		"RIGHT",
-		"BOTTOMLEFT",
-		"BOTTOM",
-		"BOTTOMRIGHT",
-	};
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.StacksAnchor, function(frame, level)
-		-- Go over those items.
-		for _, v in pairs(menuList) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = CoreFrame.L[v];
-			item.arg1 = v;
-			item.func = function(self, arg1)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in indexes 1 and 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][1] = arg1;
-				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][3] = arg1;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.StacksAnchor, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksAnchor, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksAnchor,
-		CoreFrame.L[CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[1]]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.StacksAnchor, "LEFT");
-
-	-- Now X/Y offsets. Two sliders.
-	InterfaceOptions.StacksOffsetX = CreateFrame("Slider", "PowerAurasButtons_StacksOffsetX",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.StacksOffsetX:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -130);
-	InterfaceOptions.StacksOffsetX:SetMinMaxValues(-32, 32);
-	InterfaceOptions.StacksOffsetX:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[4]);
-	InterfaceOptions.StacksOffsetX:SetValueStep(1);
-	InterfaceOptions.StacksOffsetX:SetWidth(125);
-
-	PowerAurasButtons_StacksOffsetXLow:SetText("-32");
-	PowerAurasButtons_StacksOffsetXHigh:SetText("32");
-	PowerAurasButtons_StacksOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[4] .. ")");
-	-- Update on value change.
-	InterfaceOptions.StacksOffsetX:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][4] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_StacksOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-
-	InterfaceOptions.StacksOffsetY = CreateFrame("Slider", "PowerAurasButtons_StacksOffsetY",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.StacksOffsetY:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 165, -130);
-	InterfaceOptions.StacksOffsetY:SetMinMaxValues(-32, 32);
-	InterfaceOptions.StacksOffsetY:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[5]);
-	InterfaceOptions.StacksOffsetY:SetValueStep(1);
-	InterfaceOptions.StacksOffsetY:SetWidth(125);
-
-	PowerAurasButtons_StacksOffsetYLow:SetText("-32");
-	PowerAurasButtons_StacksOffsetYHigh:SetText("32");
-	PowerAurasButtons_StacksOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[5] .. ")");
-	-- Update on value change.
-	InterfaceOptions.StacksOffsetY:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][5] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_StacksOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-	-- Add some header(s).
-	InterfaceOptions.FontHeader = Modules.Config:CreateHeaderWidget("Stacks Font",
-		InterfaceOptions, -165);
-	InterfaceOptions.FontHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -165);
-	InterfaceOptions.FontHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -165);
-
-	-- Font selection.
-	InterfaceOptions.StacksFont = CreateFrame("Frame", "PowerAurasButtons_StacksFont",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.StacksFont:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -200);
-	-- Menu.
-	local fonts = {
-		["Arial Narrow"] = "Fonts\\ARIALN.ttf",
-		["Friz Quadrata TT"] = "Fonts\\FRIZQT_.ttf",
-		["Morpheus"] = "Fonts\\MORPHEUS.ttf",
-		["Skurri"] = "Fonts\\skurri.ttf",
-	};
-	-- Figure out if we're using default fonts or LSM.
-	local LSMFonts;
-	if(LibStub) then
-		-- Try LSM.
-		local LSM = LibStub("LibSharedMedia-3.0", true);
-		if(LSM) then
-			-- Get all fonts.
-			LSMFonts = LSM:HashTable(LSM.MediaType.FONT);
-		end
-	end
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.StacksFont, function(frame, level)
-		-- Go over those items.
-		for k, v in pairs(LSMFonts or fonts) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = k;
-			item.arg1 = v;
-			item.arg2 = k;
-			item.func = function(self, arg1, arg2)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in indexes 1 and 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = arg1;
-				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = arg2;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.StacksFont, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksFont, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksFont,
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.StacksFont, "LEFT");
-
-	-- Font size slider.
-	InterfaceOptions.StacksFontSize = CreateFrame("Slider", "PowerAurasButtons_StacksFontSize",
-		InterfaceOptions, "OptionsSliderTemplate");
-	InterfaceOptions.StacksFontSize:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 210, -205);
-	InterfaceOptions.StacksFontSize:SetMinMaxValues(1, 24);
-	InterfaceOptions.StacksFontSize:SetValue(
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksFont")[2]);
-	InterfaceOptions.StacksFontSize:SetValueStep(1);
-	InterfaceOptions.StacksFontSize:SetWidth(125);
-	PowerAurasButtons_StacksFontSizeLow:SetText("-32");
-	PowerAurasButtons_StacksFontSizeHigh:SetText("32");
-	PowerAurasButtons_StacksFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
-		CoreFrame:GetModuleSetting("TimerStacks", "StacksFont")[2] .. ")");
-	-- Update on value change.
-	InterfaceOptions.StacksFontSize:SetScript("OnValueChanged", function(self)
-		-- Set it.
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][2] = self:GetValue();
-		-- Update label too.
-		PowerAurasButtons_StacksFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
-			self:GetValue() .. ")");
-		-- Trigger update.
-		Modules.TimerStacks:UpdateButtonFrames();
-	end);
-
-	-- Outline selector.
-	InterfaceOptions.StacksOutline = CreateFrame("Frame", "PowerAurasButtons_StacksOutline",
-		InterfaceOptions, "UIDropDownMenuTemplate");
-	InterfaceOptions.StacksOutline:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -230);
-	-- Menu.
-	local menuList = {
-		"OUTLINE",
-		"THICKOUTLINE",
-		"MONOCHROME",
-		"OUTLINE, MONOCHROME",
-		"THICKOUTLINE, MONOCHROME"
-	};
-	-- Sort out the menu.
-	UIDropDownMenu_Initialize(InterfaceOptions.StacksOutline, function(frame, level)
-		-- Go over those items.
-		for _, v in pairs(menuList) do
-			-- Make an item.
-			item = UIDropDownMenu_CreateInfo();
-			item.text = v;
-			item.arg1 = v;
-			item.func = function(self, arg1, arg2)
-				-- Item clicked, change selection and save.
-				UIDropDownMenu_SetSelectedID(frame, self:GetID());
-				-- Store in index 3.
-				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][3] = arg1;
-				-- Trigger update.
-				Modules.TimerStacks:UpdateButtonFrames();
-			end;
-			-- Add to list.
-			UIDropDownMenu_AddButton(item, level);
-		end
-	end);
-	UIDropDownMenu_SetWidth(InterfaceOptions.StacksOutline, 150);
-	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksOutline, 165);
-	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksOutline,
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][3]);
-	UIDropDownMenu_JustifyText(InterfaceOptions.StacksOutline, "LEFT");
-
-	-- Font color. WE'RE ALMOST DONE.
-	InterfaceOptions.StacksColor = Modules.Config:CreateColorWidget(InterfaceOptions);
-	InterfaceOptions.StacksColor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 205, -236);
-	InterfaceOptions.StacksColor:SetScript("OnClick", function()
-		-- Display the color picker.
-		ColorPickerFrame:SetColorRGB(InterfaceOptions.StacksColor.Swatch:GetVertexColor());
-		-- Allow transparency.
-		ColorPickerFrame.hasOpacity = nil;
-		ColorPickerFrame.opacity = 1;
-		ColorPickerFrame.previousValues = InterfaceOptions.StacksColor.Swatch.Backup;
-		-- Save functions.
-		local saveFunc = function(restore)
-			-- Locals.
-			local r, g, b, a = nil, nil, nil, 1;
-			-- Get values.
-			if(not restore) then
-				r, g, b = ColorPickerFrame:GetColorRGB();
-			else
-				-- Restoring from restore table.
-				r, g, b, a = unpack(restore);
-			end
-			-- Save.
-			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"] = { r, g, b, a };
-			InterfaceOptions.StacksColor.Swatch:SetVertexColor(r, g, b, a);
-			InterfaceOptions.StacksColor.Swatch.Backup = { r, g, b, a };
-			-- Trigger update.
-			Modules.TimerStacks:UpdateButtonFrames();
-		end;
-		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
-		-- Go.
-		ColorPickerFrame:Hide();
-		ColorPickerFrame:Show();
-	end);
-	-- Final bits.
-	InterfaceOptions.StacksColor.Swatch:SetVertexColor(
-		unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"]));
-	InterfaceOptions.StacksColor.Swatch.Backup =
-		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"];
-
-	-- Tooltips.
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksAnchor, {
-		title = "Anchor",
-		text = "Controls the anchor point of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOffsetX, {
-		title = "X Offset",
-		text = "Controls the X co-ordinate position of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOffsetY, {
-		title = "Y Offset",
-		text = "Controls the Y co-ordinate position of the display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksFont, {
-		title = "Font",
-		text = "Controls the name of the font to display."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksFontSize, {
-		title = "Font Size",
-		text = "Controls the font size."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOutline, {
-		title = "Font Outline",
-		text = "Controls the outline of the font."
-	});
-	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksColor, {
-		title = "Font Color",
-		text = "Controls color of the font."
-	});
-end
---[[
-----------------------------------------------------------------------------------------------------
-OnInitialize
-
-Fired by the module handler. Put all the loading code into here.
-----------------------------------------------------------------------------------------------------
---]]
-function ModuleFrame:OnInitialize()
-	-- Register module events for config frames.
-	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
-	CoreFrame:RegisterModuleEventListener("OnCreateInterfaceOptionsFrame", ModuleFrame);
-	-- Done.
-	return true;
+--[[
+	PowerAurasButtons
+
+	Module: TimerStacksConfig
+--]]
+-- Create module frames.
+local CoreFrame        = PowerAurasButtons;
+local ModuleFrame      = CoreFrame:RegisterModule("TimerStacksConfig", { "TimerStacks", "Config" });
+local Modules          = CoreFrame.Modules;
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateConfigurationFrame
+
+Creates the configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateConfigurationFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Make the parent frame.
+	local ActionEditor = CreateFrame("Frame", nil, UIParent);
+	ActionEditor:SetHeight(51);
+	-- Label.
+	ActionEditor.DisplayLabel = Modules.Config:CreateHeaderWidget("Module: Timer/Stacks",
+		ActionEditor, 0);
+	-- Display timers?
+	ActionEditor.DisplayTimer = Modules.Config:CreateButtonWidget(ActionEditor, "Display Timer");
+	ActionEditor.DisplayTimer:SetPoint("TOP", ActionEditor, "TOP", -60, -25);
+	ActionEditor.DisplayTimer:SetScript("OnClick", function(self)
+		-- Toggle self.
+		if(self.Selected) then
+			self:Deselect();
+			Modules.Config:UpdateActionData("timer", nil);
+		else
+			self:Select();
+			Modules.Config:UpdateActionData("timer", true);
+		end
+	end);
+	-- Display stacks?
+	ActionEditor.DisplayStacks = Modules.Config:CreateButtonWidget(ActionEditor, "Display Stacks");
+	ActionEditor.DisplayStacks:SetPoint("TOP", ActionEditor, "TOP", 60, -25);
+	ActionEditor.DisplayStacks:SetScript("OnClick", function(self)
+		-- Toggle self.
+		if(self.Selected) then
+			self:Deselect();
+			Modules.Config:UpdateActionData("stacks", nil);
+		else
+			self:Select();
+			Modules.Config:UpdateActionData("stacks", true);
+		end
+	end);
+	-- Tooltips (localization handled by the config module)
+	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayTimer, {
+		title = "Display Timer",
+		text = "Allows this button to display any enabled timers this aura has."
+	});
+	Modules.Config:RegisterConfigTooltip(ActionEditor.DisplayStacks, {
+		title = "Display Stacks",
+		text = "Allows this button to display any enabled stacks this aura has."
+	});
+	-- Add the necessary functions.
+	ActionEditor.UpdateAction = function(self, actionData)
+		if(actionData["timer"]) then
+			ActionEditor.DisplayTimer:Select();
+		else
+			ActionEditor.DisplayTimer:Deselect();
+		end
+		if(actionData["stacks"]) then
+			ActionEditor.DisplayStacks:Select();
+		else
+			ActionEditor.DisplayStacks:Deselect();
+		end
+	end;
+	-- Done.
+	Modules.Config:RegisterActionConfigFrame(ActionEditor, 3);
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnCreateInterfaceOptionsFrame
+
+Creates the interface options configuration frame for the Config module.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnCreateInterfaceOptionsFrame(name)
+	-- Only do this if the name matches the module name.
+	if(name ~= ModuleFrame.Name and name) then return; end
+	-- Split into two functions so I don't kill myself.
+	ModuleFrame:CreateInterfaceOptionsTimerFrame();
+	ModuleFrame:CreateInterfaceOptionsStacksFrame();
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateInterfaceOptionsTimerFrame
+
+Creates the timers configuration editor.
+
+WARNING: This function will drive you insane. I'm not optimizing it, I NEVER WANT TO SEE IT AGAIN.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateInterfaceOptionsTimerFrame()
+	-- Register the timers part.
+	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Timers");
+	-- Add some header(s).
+	InterfaceOptions.AnchorHeader = Modules.Config:CreateHeaderWidget("Timer Anchors",
+		InterfaceOptions, -60);
+	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -60);
+	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -60);
+	-- Timer anchoring first.
+	InterfaceOptions.TimerAnchor = CreateFrame("Frame", "PowerAurasButtons_TimerAnchor",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.TimerAnchor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -85);
+	-- Menu.
+	local menuList = {
+		"TOPLEFT",
+		"TOP",
+		"TOPRIGHT",
+		"LEFT",
+		"CENTER",
+		"RIGHT",
+		"BOTTOMLEFT",
+		"BOTTOM",
+		"BOTTOMRIGHT",
+	};
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.TimerAnchor, function(frame, level)
+		-- Go over those items.
+		for _, v in pairs(menuList) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = CoreFrame.L[v];
+			item.arg1 = v;
+			item.func = function(self, arg1)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in indexes 1 and 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][1] = arg1;
+				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][3] = arg1;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.TimerAnchor, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerAnchor, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerAnchor,
+		CoreFrame.L[CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[1]]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.TimerAnchor, "LEFT");
+
+	-- Now X/Y offsets. Two sliders.
+	InterfaceOptions.TimerOffsetX = CreateFrame("Slider", "PowerAurasButtons_TimerOffsetX",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.TimerOffsetX:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -130);
+	InterfaceOptions.TimerOffsetX:SetMinMaxValues(-32, 32);
+	InterfaceOptions.TimerOffsetX:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[4]);
+	InterfaceOptions.TimerOffsetX:SetValueStep(1);
+	InterfaceOptions.TimerOffsetX:SetWidth(125);
+
+	PowerAurasButtons_TimerOffsetXLow:SetText("-32");
+	PowerAurasButtons_TimerOffsetXHigh:SetText("32");
+	PowerAurasButtons_TimerOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[4] .. ")");
+	-- Update on value change.
+	InterfaceOptions.TimerOffsetX:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][4] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_TimerOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+
+	InterfaceOptions.TimerOffsetY = CreateFrame("Slider", "PowerAurasButtons_TimerOffsetY",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.TimerOffsetY:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 165, -130);
+	InterfaceOptions.TimerOffsetY:SetMinMaxValues(-32, 32);
+	InterfaceOptions.TimerOffsetY:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[5]);
+	InterfaceOptions.TimerOffsetY:SetValueStep(1);
+	InterfaceOptions.TimerOffsetY:SetWidth(125);
+
+	PowerAurasButtons_TimerOffsetYLow:SetText("-32");
+	PowerAurasButtons_TimerOffsetYHigh:SetText("32");
+	PowerAurasButtons_TimerOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerAnchors")[5] .. ")");
+	-- Update on value change.
+	InterfaceOptions.TimerOffsetY:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerAnchors"][5] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_TimerOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+	-- Add some header(s).
+	InterfaceOptions.FontHeader = Modules.Config:CreateHeaderWidget("Timer Font",
+		InterfaceOptions, -165);
+	InterfaceOptions.FontHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -165);
+	InterfaceOptions.FontHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -165);
+
+	-- Font selection.
+	InterfaceOptions.TimerFont = CreateFrame("Frame", "PowerAurasButtons_TimerFont",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.TimerFont:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -200);
+	-- Menu.
+	local fonts = {
+		["Arial Narrow"] = "Fonts\\ARIALN.ttf",
+		["Friz Quadrata TT"] = "Fonts\\FRIZQT_.ttf",
+		["Morpheus"] = "Fonts\\MORPHEUS.ttf",
+		["Skurri"] = "Fonts\\skurri.ttf",
+	};
+	-- Figure out if we're using default fonts or LSM.
+	local LSMFonts;
+	if(LibStub) then
+		-- Try LSM.
+		local LSM = LibStub("LibSharedMedia-3.0", true);
+		if(LSM) then
+			-- Get all fonts.
+			LSMFonts = LSM:HashTable(LSM.MediaType.FONT);
+		end
+	end
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.TimerFont, function(frame, level)
+		-- Go over those items.
+		for k, v in pairs(LSMFonts or fonts) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = k;
+			item.arg1 = v;
+			item.arg2 = k;
+			item.func = function(self, arg1, arg2)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in indexes 1 and 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][1] = arg1;
+				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4] = arg2;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.TimerFont, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerFont, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerFont,
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][4]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.TimerFont, "LEFT");
+
+	-- Font size slider.
+	InterfaceOptions.TimerFontSize = CreateFrame("Slider", "PowerAurasButtons_TimerFontSize",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.TimerFontSize:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 210, -205);
+	InterfaceOptions.TimerFontSize:SetMinMaxValues(1, 24);
+	InterfaceOptions.TimerFontSize:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerFont")[2]);
+	InterfaceOptions.TimerFontSize:SetValueStep(1);
+	InterfaceOptions.TimerFontSize:SetWidth(125);
+	PowerAurasButtons_TimerFontSizeLow:SetText("-32");
+	PowerAurasButtons_TimerFontSizeHigh:SetText("32");
+	PowerAurasButtons_TimerFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "TimerFont")[2] .. ")");
+	-- Update on value change.
+	InterfaceOptions.TimerFontSize:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][2] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_TimerFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+
+	-- Outline selector.
+	InterfaceOptions.TimerOutline = CreateFrame("Frame", "PowerAurasButtons_TimerOutline",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.TimerOutline:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -230);
+	-- Menu.
+	local menuList = {
+		"OUTLINE",
+		"THICKOUTLINE",
+		"MONOCHROME",
+		"OUTLINE, MONOCHROME",
+		"THICKOUTLINE, MONOCHROME"
+	};
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.TimerOutline, function(frame, level)
+		-- Go over those items.
+		for _, v in pairs(menuList) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = v;
+			item.arg1 = v;
+			item.func = function(self, arg1, arg2)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in index 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][3] = arg1;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.TimerOutline, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.TimerOutline, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.TimerOutline,
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerFont"][3]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.TimerOutline, "LEFT");
+
+	-- Font color. WE'RE ALMOST DONE.
+	InterfaceOptions.TimerColor = Modules.Config:CreateColorWidget(InterfaceOptions);
+	InterfaceOptions.TimerColor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 205, -236);
+	InterfaceOptions.TimerColor:SetScript("OnClick", function()
+		-- Display the color picker.
+		ColorPickerFrame:SetColorRGB(InterfaceOptions.TimerColor.Swatch:GetVertexColor());
+		-- Allow transparency.
+		ColorPickerFrame.hasOpacity = nil;
+		ColorPickerFrame.opacity = 1;
+		ColorPickerFrame.previousValues = InterfaceOptions.TimerColor.Swatch.Backup;
+		-- Save functions.
+		local saveFunc = function(restore)
+			-- Locals.
+			local r, g, b, a = nil, nil, nil, 1;
+			-- Get values.
+			if(not restore) then
+				r, g, b = ColorPickerFrame:GetColorRGB();
+			else
+				-- Restoring from restore table.
+				r, g, b, a = unpack(restore);
+			end
+			-- Save.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"] = { r, g, b, a };
+			InterfaceOptions.TimerColor.Swatch:SetVertexColor(r, g, b, a);
+			InterfaceOptions.TimerColor.Swatch.Backup = { r, g, b, a };
+			-- Trigger update.
+			Modules.TimerStacks:UpdateButtonFrames();
+		end;
+		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
+		-- Go.
+		ColorPickerFrame:Hide();
+		ColorPickerFrame:Show();
+	end);
+	-- Final bits.
+	InterfaceOptions.TimerColor.Swatch:SetVertexColor(
+		unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"]));
+	InterfaceOptions.TimerColor.Swatch.Backup =
+		PowerAurasButtons_SettingsDB["TimerStacks"]["TimerColours"];
+
+	-- Tooltips.
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerAnchor, {
+		title = "Anchor",
+		text = "Controls the anchor point of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOffsetX, {
+		title = "X Offset",
+		text = "Controls the X co-ordinate position of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOffsetY, {
+		title = "Y Offset",
+		text = "Controls the Y co-ordinate position of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerFont, {
+		title = "Font",
+		text = "Controls the name of the font to display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerFontSize, {
+		title = "Font Size",
+		text = "Controls the font size."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerOutline, {
+		title = "Font Outline",
+		text = "Controls the outline of the font."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.TimerColor, {
+		title = "Font Color",
+		text = "Controls color of the font."
+	});
+end
+--[[
+----------------------------------------------------------------------------------------------------
+CreateInterfaceOptionsStacksFrame
+
+Creates the stacks configuration editor.
+
+WARNING: This function will drive you insane. I'm not optimizing it, I NEVER WANT TO SEE IT AGAIN.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:CreateInterfaceOptionsStacksFrame()
+	-- Register the Stacks part.
+	local InterfaceOptions = Modules.Config:RegisterInterfaceOptionsFrame("Module: Stacks");
+	-- Add some header(s).
+	InterfaceOptions.AnchorHeader = Modules.Config:CreateHeaderWidget("Stacks Anchors",
+		InterfaceOptions, -60);
+	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -60);
+	InterfaceOptions.AnchorHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -60);
+	-- Stacks anchoring first.
+	InterfaceOptions.StacksAnchor = CreateFrame("Frame", "PowerAurasButtons_StacksAnchor",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.StacksAnchor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -85);
+	-- Menu.
+	local menuList = {
+		"TOPLEFT",
+		"TOP",
+		"TOPRIGHT",
+		"LEFT",
+		"CENTER",
+		"RIGHT",
+		"BOTTOMLEFT",
+		"BOTTOM",
+		"BOTTOMRIGHT",
+	};
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.StacksAnchor, function(frame, level)
+		-- Go over those items.
+		for _, v in pairs(menuList) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = CoreFrame.L[v];
+			item.arg1 = v;
+			item.func = function(self, arg1)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in indexes 1 and 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][1] = arg1;
+				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][3] = arg1;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.StacksAnchor, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksAnchor, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksAnchor,
+		CoreFrame.L[CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[1]]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.StacksAnchor, "LEFT");
+
+	-- Now X/Y offsets. Two sliders.
+	InterfaceOptions.StacksOffsetX = CreateFrame("Slider", "PowerAurasButtons_StacksOffsetX",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.StacksOffsetX:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 20, -130);
+	InterfaceOptions.StacksOffsetX:SetMinMaxValues(-32, 32);
+	InterfaceOptions.StacksOffsetX:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[4]);
+	InterfaceOptions.StacksOffsetX:SetValueStep(1);
+	InterfaceOptions.StacksOffsetX:SetWidth(125);
+
+	PowerAurasButtons_StacksOffsetXLow:SetText("-32");
+	PowerAurasButtons_StacksOffsetXHigh:SetText("32");
+	PowerAurasButtons_StacksOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[4] .. ")");
+	-- Update on value change.
+	InterfaceOptions.StacksOffsetX:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][4] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_StacksOffsetXText:SetText(CoreFrame.L["X Offset"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+
+	InterfaceOptions.StacksOffsetY = CreateFrame("Slider", "PowerAurasButtons_StacksOffsetY",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.StacksOffsetY:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 165, -130);
+	InterfaceOptions.StacksOffsetY:SetMinMaxValues(-32, 32);
+	InterfaceOptions.StacksOffsetY:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[5]);
+	InterfaceOptions.StacksOffsetY:SetValueStep(1);
+	InterfaceOptions.StacksOffsetY:SetWidth(125);
+
+	PowerAurasButtons_StacksOffsetYLow:SetText("-32");
+	PowerAurasButtons_StacksOffsetYHigh:SetText("32");
+	PowerAurasButtons_StacksOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksAnchors")[5] .. ")");
+	-- Update on value change.
+	InterfaceOptions.StacksOffsetY:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksAnchors"][5] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_StacksOffsetYText:SetText(CoreFrame.L["Y Offset"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+	-- Add some header(s).
+	InterfaceOptions.FontHeader = Modules.Config:CreateHeaderWidget("Stacks Font",
+		InterfaceOptions, -165);
+	InterfaceOptions.FontHeader.bg:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 4, -165);
+	InterfaceOptions.FontHeader.bg:SetPoint("TOPRIGHT", InterfaceOptions, "TOPRIGHT", -4, -165);
+
+	-- Font selection.
+	InterfaceOptions.StacksFont = CreateFrame("Frame", "PowerAurasButtons_StacksFont",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.StacksFont:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -200);
+	-- Menu.
+	local fonts = {
+		["Arial Narrow"] = "Fonts\\ARIALN.ttf",
+		["Friz Quadrata TT"] = "Fonts\\FRIZQT_.ttf",
+		["Morpheus"] = "Fonts\\MORPHEUS.ttf",
+		["Skurri"] = "Fonts\\skurri.ttf",
+	};
+	-- Figure out if we're using default fonts or LSM.
+	local LSMFonts;
+	if(LibStub) then
+		-- Try LSM.
+		local LSM = LibStub("LibSharedMedia-3.0", true);
+		if(LSM) then
+			-- Get all fonts.
+			LSMFonts = LSM:HashTable(LSM.MediaType.FONT);
+		end
+	end
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.StacksFont, function(frame, level)
+		-- Go over those items.
+		for k, v in pairs(LSMFonts or fonts) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = k;
+			item.arg1 = v;
+			item.arg2 = k;
+			item.func = function(self, arg1, arg2)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in indexes 1 and 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][1] = arg1;
+				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4] = arg2;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.StacksFont, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksFont, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksFont,
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][4]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.StacksFont, "LEFT");
+
+	-- Font size slider.
+	InterfaceOptions.StacksFontSize = CreateFrame("Slider", "PowerAurasButtons_StacksFontSize",
+		InterfaceOptions, "OptionsSliderTemplate");
+	InterfaceOptions.StacksFontSize:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 210, -205);
+	InterfaceOptions.StacksFontSize:SetMinMaxValues(1, 24);
+	InterfaceOptions.StacksFontSize:SetValue(
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksFont")[2]);
+	InterfaceOptions.StacksFontSize:SetValueStep(1);
+	InterfaceOptions.StacksFontSize:SetWidth(125);
+	PowerAurasButtons_StacksFontSizeLow:SetText("-32");
+	PowerAurasButtons_StacksFontSizeHigh:SetText("32");
+	PowerAurasButtons_StacksFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
+		CoreFrame:GetModuleSetting("TimerStacks", "StacksFont")[2] .. ")");
+	-- Update on value change.
+	InterfaceOptions.StacksFontSize:SetScript("OnValueChanged", function(self)
+		-- Set it.
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][2] = self:GetValue();
+		-- Update label too.
+		PowerAurasButtons_StacksFontSizeText:SetText(CoreFrame.L["Font Size"] .. " (" ..
+			self:GetValue() .. ")");
+		-- Trigger update.
+		Modules.TimerStacks:UpdateButtonFrames();
+	end);
+
+	-- Outline selector.
+	InterfaceOptions.StacksOutline = CreateFrame("Frame", "PowerAurasButtons_StacksOutline",
+		InterfaceOptions, "UIDropDownMenuTemplate");
+	InterfaceOptions.StacksOutline:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 0, -230);
+	-- Menu.
+	local menuList = {
+		"OUTLINE",
+		"THICKOUTLINE",
+		"MONOCHROME",
+		"OUTLINE, MONOCHROME",
+		"THICKOUTLINE, MONOCHROME"
+	};
+	-- Sort out the menu.
+	UIDropDownMenu_Initialize(InterfaceOptions.StacksOutline, function(frame, level)
+		-- Go over those items.
+		for _, v in pairs(menuList) do
+			-- Make an item.
+			item = UIDropDownMenu_CreateInfo();
+			item.text = v;
+			item.arg1 = v;
+			item.func = function(self, arg1, arg2)
+				-- Item clicked, change selection and save.
+				UIDropDownMenu_SetSelectedID(frame, self:GetID());
+				-- Store in index 3.
+				PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][3] = arg1;
+				-- Trigger update.
+				Modules.TimerStacks:UpdateButtonFrames();
+			end;
+			-- Add to list.
+			UIDropDownMenu_AddButton(item, level);
+		end
+	end);
+	UIDropDownMenu_SetWidth(InterfaceOptions.StacksOutline, 150);
+	UIDropDownMenu_SetButtonWidth(InterfaceOptions.StacksOutline, 165);
+	UIDropDownMenu_SetSelectedValue(InterfaceOptions.StacksOutline,
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksFont"][3]);
+	UIDropDownMenu_JustifyText(InterfaceOptions.StacksOutline, "LEFT");
+
+	-- Font color. WE'RE ALMOST DONE.
+	InterfaceOptions.StacksColor = Modules.Config:CreateColorWidget(InterfaceOptions);
+	InterfaceOptions.StacksColor:SetPoint("TOPLEFT", InterfaceOptions, "TOPLEFT", 205, -236);
+	InterfaceOptions.StacksColor:SetScript("OnClick", function()
+		-- Display the color picker.
+		ColorPickerFrame:SetColorRGB(InterfaceOptions.StacksColor.Swatch:GetVertexColor());
+		-- Allow transparency.
+		ColorPickerFrame.hasOpacity = nil;
+		ColorPickerFrame.opacity = 1;
+		ColorPickerFrame.previousValues = InterfaceOptions.StacksColor.Swatch.Backup;
+		-- Save functions.
+		local saveFunc = function(restore)
+			-- Locals.
+			local r, g, b, a = nil, nil, nil, 1;
+			-- Get values.
+			if(not restore) then
+				r, g, b = ColorPickerFrame:GetColorRGB();
+			else
+				-- Restoring from restore table.
+				r, g, b, a = unpack(restore);
+			end
+			-- Save.
+			PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"] = { r, g, b, a };
+			InterfaceOptions.StacksColor.Swatch:SetVertexColor(r, g, b, a);
+			InterfaceOptions.StacksColor.Swatch.Backup = { r, g, b, a };
+			-- Trigger update.
+			Modules.TimerStacks:UpdateButtonFrames();
+		end;
+		ColorPickerFrame.func, ColorPickerFrame.cancelFunc = saveFunc, saveFunc;
+		-- Go.
+		ColorPickerFrame:Hide();
+		ColorPickerFrame:Show();
+	end);
+	-- Final bits.
+	InterfaceOptions.StacksColor.Swatch:SetVertexColor(
+		unpack(PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"]));
+	InterfaceOptions.StacksColor.Swatch.Backup =
+		PowerAurasButtons_SettingsDB["TimerStacks"]["StacksColours"];
+
+	-- Tooltips.
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksAnchor, {
+		title = "Anchor",
+		text = "Controls the anchor point of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOffsetX, {
+		title = "X Offset",
+		text = "Controls the X co-ordinate position of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOffsetY, {
+		title = "Y Offset",
+		text = "Controls the Y co-ordinate position of the display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksFont, {
+		title = "Font",
+		text = "Controls the name of the font to display."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksFontSize, {
+		title = "Font Size",
+		text = "Controls the font size."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksOutline, {
+		title = "Font Outline",
+		text = "Controls the outline of the font."
+	});
+	Modules.Config:RegisterConfigTooltip(InterfaceOptions.StacksColor, {
+		title = "Font Color",
+		text = "Controls color of the font."
+	});
+end
+--[[
+----------------------------------------------------------------------------------------------------
+OnInitialize
+
+Fired by the module handler. Put all the loading code into here.
+----------------------------------------------------------------------------------------------------
+--]]
+function ModuleFrame:OnInitialize()
+	-- Register module events for config frames.
+	CoreFrame:RegisterModuleEventListener("OnCreateConfigurationFrame", ModuleFrame);
+	CoreFrame:RegisterModuleEventListener("OnCreateInterfaceOptionsFrame", ModuleFrame);
+	-- Done.
+	return true;
 end
\ No newline at end of file
diff --git a/PowerAurasButtons.toc b/PowerAurasButtons.toc
index d6af278..2664e91 100644
--- a/PowerAurasButtons.toc
+++ b/PowerAurasButtons.toc
@@ -1,30 +1,30 @@
-## Interface: 40100
-## Author: Daniel Yates
-## Version: @project-version@
-## Title: Power Auras Classic: Buttons
-## Notes: Allows you to use various displays on action buttons when a Power Auras aura is activated.
-## Dependencies: PowerAuras
-## OptionalDeps: LibActionButton-1.0, LibSharedMedia-3.0, SharedMedia, LibStub, Bartender4, Dominos
-## SavedVariables: PowerAurasButtons_AurasDB, PowerAurasButtons_SettingsDB
-## SavedVariablesPerCharacter: PowerAurasButtons_CharacterAurasDB
-
-# NOTE: Old SV's will be gone in 4.1.0.
-
-# Core addon. This will set up the global frame and event handlers - actual module init isn't done
-# until later.
-Core.lua
-
-# Modules. You could add these in whatever order you feel like, due to dependency management.
-Modules\Config.lua
-
-Modules\Auras.lua
-Modules\AurasConfig.lua
-
-Modules\Buttons.lua
-Modules\ButtonsConfig.lua
-
-Modules\TimerStacks.lua
-Modules\TimerStacksConfig.lua
-
-Modules\Border.lua
+## Interface: 40100
+## Author: Daniel Yates
+## Version: @project-version@
+## Title: Power Auras Classic: Buttons
+## Notes: Allows you to use various displays on action buttons when a Power Auras aura is activated.
+## Dependencies: PowerAuras
+## OptionalDeps: LibActionButton-1.0, LibSharedMedia-3.0, SharedMedia, LibStub, Bartender4, Dominos
+## SavedVariables: PowerAurasButtons_AurasDB, PowerAurasButtons_SettingsDB
+## SavedVariablesPerCharacter: PowerAurasButtons_CharacterAurasDB
+
+# NOTE: Old SV's will be gone in 4.1.0.
+
+# Core addon. This will set up the global frame and event handlers - actual module init isn't done
+# until later.
+Core.lua
+
+# Modules. You could add these in whatever order you feel like, due to dependency management.
+Modules\Config.lua
+
+Modules\Auras.lua
+Modules\AurasConfig.lua
+
+Modules\Buttons.lua
+Modules\ButtonsConfig.lua
+
+Modules\TimerStacks.lua
+Modules\TimerStacksConfig.lua
+
+Modules\Border.lua
 Modules\BorderConfig.lua
\ No newline at end of file