diff --git a/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.lua b/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.lua
new file mode 100644
index 0000000..7a29450
--- /dev/null
+++ b/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.lua
@@ -0,0 +1,728 @@
+--- **AceDB-3.0** manages the SavedVariables of your addon.
+-- It offers profile management, smart defaults and namespaces for modules.\\
+-- Data can be saved in different data-types, depending on its intended usage.
+-- The most common data-type is the `profile` type, which allows the user to choose
+-- the active profile, and manage the profiles of all of his characters.\\
+-- The following data types are available:
+-- * **char** Character-specific data. Every character has its own database.
+-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
+-- * **class** Class-specific data. All of the players characters of the same class share this database.
+-- * **race** Race-specific data. All of the players characters of the same race share this database.
+-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
+-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
+-- * **global** Global Data. All characters on the same account share this database.
+-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
+--
+-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
+-- of the DBObjectLib listed here. \\
+-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
+-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
+-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
+--
+-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
+--
+-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
+--
+-- @usage
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
+--
+-- -- declare defaults to be used in the DB
+-- local defaults = {
+-- profile = {
+-- setting = true,
+-- }
+-- }
+--
+-- function MyAddon:OnInitialize()
+-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
+-- end
+-- @class file
+-- @name AceDB-3.0.lua
+-- @release $Id: AceDB-3.0.lua 940 2010-06-19 08:01:47Z nevcairiel $
+local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 21
+local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
+
+if not AceDB then return end -- No upgrade needed
+
+-- Lua APIs
+local type, pairs, next, error = type, pairs, next, error
+local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
+
+-- WoW APIs
+local _G = _G
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub
+
+AceDB.db_registry = AceDB.db_registry or {}
+AceDB.frame = AceDB.frame or CreateFrame("Frame")
+
+local CallbackHandler
+local CallbackDummy = { Fire = function() end }
+
+local DBObjectLib = {}
+
+--[[-------------------------------------------------------------------------
+ AceDB Utility Functions
+---------------------------------------------------------------------------]]
+
+-- Simple shallow copy for copying defaults
+local function copyTable(src, dest)
+ if type(dest) ~= "table" then dest = {} end
+ if type(src) == "table" then
+ for k,v in pairs(src) do
+ if type(v) == "table" then
+ -- try to index the key first so that the metatable creates the defaults, if set, and use that table
+ v = copyTable(v, dest[k])
+ end
+ dest[k] = v
+ end
+ end
+ return dest
+end
+
+-- Called to add defaults to a section of the database
+--
+-- When a ["*"] default section is indexed with a new key, a table is returned
+-- and set in the host table. These tables must be cleaned up by removeDefaults
+-- in order to ensure we don't write empty default tables.
+local function copyDefaults(dest, src)
+ -- this happens if some value in the SV overwrites our default value with a non-table
+ --if type(dest) ~= "table" then return end
+ for k, v in pairs(src) do
+ if k == "*" or k == "**" then
+ if type(v) == "table" then
+ -- This is a metatable used for table defaults
+ local mt = {
+ -- This handles the lookup and creation of new subtables
+ __index = function(t,k)
+ if k == nil then return nil end
+ local tbl = {}
+ copyDefaults(tbl, v)
+ rawset(t, k, tbl)
+ return tbl
+ end,
+ }
+ setmetatable(dest, mt)
+ -- handle already existing tables in the SV
+ for dk, dv in pairs(dest) do
+ if not rawget(src, dk) and type(dv) == "table" then
+ copyDefaults(dv, v)
+ end
+ end
+ else
+ -- Values are not tables, so this is just a simple return
+ local mt = {__index = function(t,k) return k~=nil and v or nil end}
+ setmetatable(dest, mt)
+ end
+ elseif type(v) == "table" then
+ if not rawget(dest, k) then rawset(dest, k, {}) end
+ if type(dest[k]) == "table" then
+ copyDefaults(dest[k], v)
+ if src['**'] then
+ copyDefaults(dest[k], src['**'])
+ end
+ end
+ else
+ if rawget(dest, k) == nil then
+ rawset(dest, k, v)
+ end
+ end
+ end
+end
+
+-- Called to remove all defaults in the default table from the database
+local function removeDefaults(db, defaults, blocker)
+ -- remove all metatables from the db, so we don't accidentally create new sub-tables through them
+ setmetatable(db, nil)
+ -- loop through the defaults and remove their content
+ for k,v in pairs(defaults) do
+ if k == "*" or k == "**" then
+ if type(v) == "table" then
+ -- Loop through all the actual k,v pairs and remove
+ for key, value in pairs(db) do
+ if type(value) == "table" then
+ -- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
+ if defaults[key] == nil and (not blocker or blocker[key] == nil) then
+ removeDefaults(value, v)
+ -- if the table is empty afterwards, remove it
+ if next(value) == nil then
+ db[key] = nil
+ end
+ -- if it was specified, only strip ** content, but block values which were set in the key table
+ elseif k == "**" then
+ removeDefaults(value, v, defaults[key])
+ end
+ end
+ end
+ elseif k == "*" then
+ -- check for non-table default
+ for key, value in pairs(db) do
+ if defaults[key] == nil and v == value then
+ db[key] = nil
+ end
+ end
+ end
+ elseif type(v) == "table" and type(db[k]) == "table" then
+ -- if a blocker was set, dive into it, to allow multi-level defaults
+ removeDefaults(db[k], v, blocker and blocker[k])
+ if next(db[k]) == nil then
+ db[k] = nil
+ end
+ else
+ -- check if the current value matches the default, and that its not blocked by another defaults table
+ if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
+ db[k] = nil
+ end
+ end
+ end
+end
+
+-- This is called when a table section is first accessed, to set up the defaults
+local function initSection(db, section, svstore, key, defaults)
+ local sv = rawget(db, "sv")
+
+ local tableCreated
+ if not sv[svstore] then sv[svstore] = {} end
+ if not sv[svstore][key] then
+ sv[svstore][key] = {}
+ tableCreated = true
+ end
+
+ local tbl = sv[svstore][key]
+
+ if defaults then
+ copyDefaults(tbl, defaults)
+ end
+ rawset(db, section, tbl)
+
+ return tableCreated, tbl
+end
+
+-- Metatable to handle the dynamic creation of sections and copying of sections.
+local dbmt = {
+ __index = function(t, section)
+ local keys = rawget(t, "keys")
+ local key = keys[section]
+ if key then
+ local defaultTbl = rawget(t, "defaults")
+ local defaults = defaultTbl and defaultTbl[section]
+
+ if section == "profile" then
+ local new = initSection(t, section, "profiles", key, defaults)
+ if new then
+ -- Callback: OnNewProfile, database, newProfileKey
+ t.callbacks:Fire("OnNewProfile", t, key)
+ end
+ elseif section == "profiles" then
+ local sv = rawget(t, "sv")
+ if not sv.profiles then sv.profiles = {} end
+ rawset(t, "profiles", sv.profiles)
+ elseif section == "global" then
+ local sv = rawget(t, "sv")
+ if not sv.global then sv.global = {} end
+ if defaults then
+ copyDefaults(sv.global, defaults)
+ end
+ rawset(t, section, sv.global)
+ else
+ initSection(t, section, section, key, defaults)
+ end
+ end
+
+ return rawget(t, section)
+ end
+}
+
+local function validateDefaults(defaults, keyTbl, offset)
+ if not defaults then return end
+ offset = offset or 0
+ for k in pairs(defaults) do
+ if not keyTbl[k] or k == "profiles" then
+ error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
+ end
+ end
+end
+
+local preserve_keys = {
+ ["callbacks"] = true,
+ ["RegisterCallback"] = true,
+ ["UnregisterCallback"] = true,
+ ["UnregisterAllCallbacks"] = true,
+ ["children"] = true,
+}
+
+local realmKey = GetRealmName()
+local charKey = UnitName("player") .. " - " .. realmKey
+local _, classKey = UnitClass("player")
+local _, raceKey = UnitRace("player")
+local factionKey = UnitFactionGroup("player")
+local factionrealmKey = factionKey .. " - " .. realmKey
+-- Actual database initialization function
+local function initdb(sv, defaults, defaultProfile, olddb, parent)
+ -- Generate the database keys for each section
+
+ -- map "true" to our "Default" profile
+ if defaultProfile == true then defaultProfile = "Default" end
+
+ local profileKey
+ if not parent then
+ -- Make a container for profile keys
+ if not sv.profileKeys then sv.profileKeys = {} end
+
+ -- Try to get the profile selected from the char db
+ profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
+
+ -- save the selected profile for later
+ sv.profileKeys[charKey] = profileKey
+ else
+ -- Use the profile of the parents DB
+ profileKey = parent.keys.profile or defaultProfile or charKey
+
+ -- clear the profileKeys in the DB, namespaces don't need to store them
+ sv.profileKeys = nil
+ end
+
+ -- This table contains keys that enable the dynamic creation
+ -- of each section of the table. The 'global' and 'profiles'
+ -- have a key of true, since they are handled in a special case
+ local keyTbl= {
+ ["char"] = charKey,
+ ["realm"] = realmKey,
+ ["class"] = classKey,
+ ["race"] = raceKey,
+ ["faction"] = factionKey,
+ ["factionrealm"] = factionrealmKey,
+ ["profile"] = profileKey,
+ ["global"] = true,
+ ["profiles"] = true,
+ }
+
+ validateDefaults(defaults, keyTbl, 1)
+
+ -- This allows us to use this function to reset an entire database
+ -- Clear out the old database
+ if olddb then
+ for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
+ end
+
+ -- Give this database the metatable so it initializes dynamically
+ local db = setmetatable(olddb or {}, dbmt)
+
+ if not rawget(db, "callbacks") then
+ -- try to load CallbackHandler-1.0 if it loaded after our library
+ if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
+ db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
+ end
+
+ -- Copy methods locally into the database object, to avoid hitting
+ -- the metatable when calling methods
+
+ if not parent then
+ for name, func in pairs(DBObjectLib) do
+ db[name] = func
+ end
+ else
+ -- hack this one in
+ db.RegisterDefaults = DBObjectLib.RegisterDefaults
+ db.ResetProfile = DBObjectLib.ResetProfile
+ end
+
+ -- Set some properties in the database object
+ db.profiles = sv.profiles
+ db.keys = keyTbl
+ db.sv = sv
+ --db.sv_name = name
+ db.defaults = defaults
+ db.parent = parent
+
+ -- store the DB in the registry
+ AceDB.db_registry[db] = true
+
+ return db
+end
+
+-- handle PLAYER_LOGOUT
+-- strip all defaults from all databases
+-- and cleans up empty sections
+local function logoutHandler(frame, event)
+ if event == "PLAYER_LOGOUT" then
+ for db in pairs(AceDB.db_registry) do
+ db.callbacks:Fire("OnDatabaseShutdown", db)
+ db:RegisterDefaults(nil)
+
+ -- cleanup sections that are empty without defaults
+ local sv = rawget(db, "sv")
+ for section in pairs(db.keys) do
+ if rawget(sv, section) then
+ -- global is special, all other sections have sub-entrys
+ -- also don't delete empty profiles on main dbs, only on namespaces
+ if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
+ for key in pairs(sv[section]) do
+ if not next(sv[section][key]) then
+ sv[section][key] = nil
+ end
+ end
+ end
+ if not next(sv[section]) then
+ sv[section] = nil
+ end
+ end
+ end
+ end
+ end
+end
+
+AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
+AceDB.frame:SetScript("OnEvent", logoutHandler)
+
+
+--[[-------------------------------------------------------------------------
+ AceDB Object Method Definitions
+---------------------------------------------------------------------------]]
+
+--- Sets the defaults table for the given database object by clearing any
+-- that are currently set, and then setting the new defaults.
+-- @param defaults A table of defaults for this database
+function DBObjectLib:RegisterDefaults(defaults)
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
+ end
+
+ validateDefaults(defaults, self.keys)
+
+ -- Remove any currently set defaults
+ if self.defaults then
+ for section,key in pairs(self.keys) do
+ if self.defaults[section] and rawget(self, section) then
+ removeDefaults(self[section], self.defaults[section])
+ end
+ end
+ end
+
+ -- Set the DBObject.defaults table
+ self.defaults = defaults
+
+ -- Copy in any defaults, only touching those sections already created
+ if defaults then
+ for section,key in pairs(self.keys) do
+ if defaults[section] and rawget(self, section) then
+ copyDefaults(self[section], defaults[section])
+ end
+ end
+ end
+end
+
+--- Changes the profile of the database and all of it's namespaces to the
+-- supplied named profile
+-- @param name The name of the profile to set as the current profile
+function DBObjectLib:SetProfile(name)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
+ end
+
+ -- changing to the same profile, dont do anything
+ if name == self.keys.profile then return end
+
+ local oldProfile = self.profile
+ local defaults = self.defaults and self.defaults.profile
+
+ -- Callback: OnProfileShutdown, database
+ self.callbacks:Fire("OnProfileShutdown", self)
+
+ if oldProfile and defaults then
+ -- Remove the defaults from the old profile
+ removeDefaults(oldProfile, defaults)
+ end
+
+ self.profile = nil
+ self.keys["profile"] = name
+
+ -- if the storage exists, save the new profile
+ -- this won't exist on namespaces.
+ if self.sv.profileKeys then
+ self.sv.profileKeys[charKey] = name
+ end
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.SetProfile(db, name)
+ end
+ end
+
+ -- Callback: OnProfileChanged, database, newProfileKey
+ self.callbacks:Fire("OnProfileChanged", self, name)
+end
+
+--- Returns a table with the names of the existing profiles in the database.
+-- You can optionally supply a table to re-use for this purpose.
+-- @param tbl A table to store the profile names in (optional)
+function DBObjectLib:GetProfiles(tbl)
+ if tbl and type(tbl) ~= "table" then
+ error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
+ end
+
+ -- Clear the container table
+ if tbl then
+ for k,v in pairs(tbl) do tbl[k] = nil end
+ else
+ tbl = {}
+ end
+
+ local curProfile = self.keys.profile
+
+ local i = 0
+ for profileKey in pairs(self.profiles) do
+ i = i + 1
+ tbl[i] = profileKey
+ if curProfile and profileKey == curProfile then curProfile = nil end
+ end
+
+ -- Add the current profile, if it hasn't been created yet
+ if curProfile then
+ i = i + 1
+ tbl[i] = curProfile
+ end
+
+ return tbl, i
+end
+
+--- Returns the current profile name used by the database
+function DBObjectLib:GetCurrentProfile()
+ return self.keys.profile
+end
+
+--- Deletes a named profile. This profile must not be the active profile.
+-- @param name The name of the profile to be deleted
+-- @param silent If true, do not raise an error when the profile does not exist
+function DBObjectLib:DeleteProfile(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
+ end
+
+ if self.keys.profile == name then
+ error("Cannot delete the active profile in an AceDBObject.", 2)
+ end
+
+ if not rawget(self.profiles, name) and not silent then
+ error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
+ end
+
+ self.profiles[name] = nil
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.DeleteProfile(db, name, true)
+ end
+ end
+
+ -- Callback: OnProfileDeleted, database, profileKey
+ self.callbacks:Fire("OnProfileDeleted", self, name)
+end
+
+--- Copies a named profile into the current profile, overwriting any conflicting
+-- settings.
+-- @param name The name of the profile to be copied into the current profile
+-- @param silent If true, do not raise an error when the profile does not exist
+function DBObjectLib:CopyProfile(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
+ end
+
+ if name == self.keys.profile then
+ error("Cannot have the same source and destination profiles.", 2)
+ end
+
+ if not rawget(self.profiles, name) and not silent then
+ error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
+ end
+
+ -- Reset the profile before copying
+ DBObjectLib.ResetProfile(self, nil, true)
+
+ local profile = self.profile
+ local source = self.profiles[name]
+
+ copyTable(source, profile)
+
+ -- populate to child namespaces
+ if self.children then
+ for _, db in pairs(self.children) do
+ DBObjectLib.CopyProfile(db, name, true)
+ end
+ end
+
+ -- Callback: OnProfileCopied, database, sourceProfileKey
+ self.callbacks:Fire("OnProfileCopied", self, name)
+end
+
+--- Resets the current profile to the default values (if specified).
+-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
+-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
+function DBObjectLib:ResetProfile(noChildren, noCallbacks)
+ local profile = self.profile
+
+ for k,v in pairs(profile) do
+ profile[k] = nil
+ end
+
+ local defaults = self.defaults and self.defaults.profile
+ if defaults then
+ copyDefaults(profile, defaults)
+ end
+
+ -- populate to child namespaces
+ if self.children and not noChildren then
+ for _, db in pairs(self.children) do
+ DBObjectLib.ResetProfile(db, nil, noCallbacks)
+ end
+ end
+
+ -- Callback: OnProfileReset, database
+ if not noCallbacks then
+ self.callbacks:Fire("OnProfileReset", self)
+ end
+end
+
+--- Resets the entire database, using the string defaultProfile as the new default
+-- profile.
+-- @param defaultProfile The profile name to use as the default
+function DBObjectLib:ResetDB(defaultProfile)
+ if defaultProfile and type(defaultProfile) ~= "string" then
+ error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
+ end
+
+ local sv = self.sv
+ for k,v in pairs(sv) do
+ sv[k] = nil
+ end
+
+ local parent = self.parent
+
+ initdb(sv, self.defaults, defaultProfile, self)
+
+ -- fix the child namespaces
+ if self.children then
+ if not sv.namespaces then sv.namespaces = {} end
+ for name, db in pairs(self.children) do
+ if not sv.namespaces[name] then sv.namespaces[name] = {} end
+ initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
+ end
+ end
+
+ -- Callback: OnDatabaseReset, database
+ self.callbacks:Fire("OnDatabaseReset", self)
+ -- Callback: OnProfileChanged, database, profileKey
+ self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
+
+ return self
+end
+
+--- Creates a new database namespace, directly tied to the database. This
+-- is a full scale database in it's own rights other than the fact that
+-- it cannot control its profile individually
+-- @param name The name of the new namespace
+-- @param defaults A table of values to use as defaults
+function DBObjectLib:RegisterNamespace(name, defaults)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
+ end
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
+ end
+ if self.children and self.children[name] then
+ error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
+ end
+
+ local sv = self.sv
+ if not sv.namespaces then sv.namespaces = {} end
+ if not sv.namespaces[name] then
+ sv.namespaces[name] = {}
+ end
+
+ local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
+
+ if not self.children then self.children = {} end
+ self.children[name] = newDB
+ return newDB
+end
+
+--- Returns an already existing namespace from the database object.
+-- @param name The name of the new namespace
+-- @param silent if true, the addon is optional, silently return nil if its not found
+-- @usage
+-- local namespace = self.db:GetNamespace('namespace')
+-- @return the namespace object if found
+function DBObjectLib:GetNamespace(name, silent)
+ if type(name) ~= "string" then
+ error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
+ end
+ if not silent and not (self.children and self.children[name]) then
+ error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
+ end
+ if not self.children then self.children = {} end
+ return self.children[name]
+end
+
+--[[-------------------------------------------------------------------------
+ AceDB Exposed Methods
+---------------------------------------------------------------------------]]
+
+--- Creates a new database object that can be used to handle database settings and profiles.
+-- By default, an empty DB is created, using a character specific profile.
+--
+-- You can override the default profile used by passing any profile name as the third argument,
+-- or by passing //true// as the third argument to use a globally shared profile called "Default".
+--
+-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
+-- will use a profile named "char", and not a character-specific profile.
+-- @param tbl The name of variable, or table to use for the database
+-- @param defaults A table of database defaults
+-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
+-- You can also pass //true// to use a shared global profile called "Default".
+-- @usage
+-- -- Create an empty DB using a character-specific default profile.
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
+-- @usage
+-- -- Create a DB using defaults and using a shared default profile
+-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
+function AceDB:New(tbl, defaults, defaultProfile)
+ if type(tbl) == "string" then
+ local name = tbl
+ tbl = _G[name]
+ if not tbl then
+ tbl = {}
+ _G[name] = tbl
+ end
+ end
+
+ if type(tbl) ~= "table" then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
+ end
+
+ if defaults and type(defaults) ~= "table" then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
+ end
+
+ if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
+ error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
+ end
+
+ return initdb(tbl, defaults, defaultProfile)
+end
+
+-- upgrade existing databases
+for db in pairs(AceDB.db_registry) do
+ if not db.parent then
+ for name,func in pairs(DBObjectLib) do
+ db[name] = func
+ end
+ else
+ db.RegisterDefaults = DBObjectLib.RegisterDefaults
+ db.ResetProfile = DBObjectLib.ResetProfile
+ end
+end
diff --git a/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.xml b/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.xml
new file mode 100644
index 0000000..46b20ba
--- /dev/null
+++ b/ProfessionMenu/Libs/AceDB-3.0/AceDB-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/ProfessionMenu/Libs/DewdropLib/Dewdrop-2.0/Dewdrop-2.0.lua b/ProfessionMenu/Libs/DewdropLib/Dewdrop-2.0/Dewdrop-2.0.lua
index eda0833..9da73b8 100644
--- a/ProfessionMenu/Libs/DewdropLib/Dewdrop-2.0/Dewdrop-2.0.lua
+++ b/ProfessionMenu/Libs/DewdropLib/Dewdrop-2.0/Dewdrop-2.0.lua
@@ -11,7 +11,7 @@ License: LGPL v2.1
]]
local MAJOR_VERSION = "Dewdrop-2.0"
-local MINOR_VERSION = tonumber(strmatch("$Revision: 327 $", "%d+")) + 90000
+local MINOR_VERSION = tonumber(strmatch("$Revision: 328 $", "%d+")) + 90000
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
@@ -247,6 +247,7 @@ secureFrame:HookScript("OnClick",
function(this , buttonClick)
local realthis = this
this = this.owner
+ if not this then return end
this:GetScript("OnClick")(this, buttonClick)
end
)
diff --git a/ProfessionMenu/ProfessionMenu.lua b/ProfessionMenu/ProfessionMenu.lua
index 54f71e7..364a3ed 100644
--- a/ProfessionMenu/ProfessionMenu.lua
+++ b/ProfessionMenu/ProfessionMenu.lua
@@ -1,6 +1,5 @@
-ProfessionMenu = LibStub("AceAddon-3.0"):NewAddon("ProfessionMenu", "AceConsole-3.0", "AceTimer-3.0", "AceEvent-3.0", "AceComm-3.0", "AceSerializer-3.0")
-local PM = LibStub("AceAddon-3.0"):GetAddon("ProfessionMenu")
-local addonName = ...
+local PM = LibStub("AceAddon-3.0"):NewAddon("ProfessionMenu", "AceTimer-3.0", "AceEvent-3.0")
+PROFESSIONMENU = PM
local professionbutton, mainframe
local dewdrop = AceLibrary("Dewdrop-2.0")
local defIcon = "Interface\\Icons\\achievement_guildperk_bountifulbags"
@@ -8,13 +7,11 @@ local icon = LibStub('LibDBIcon-1.0')
local CYAN = "|cff00ffff"
local WHITE = "|cffFFFFFF"
-PROFESSIONMENU_MINIMAP = LibStub:GetLibrary('LibDataBroker-1.1'):NewDataObject(addonName, {
+local minimap = LibStub:GetLibrary('LibDataBroker-1.1'):NewDataObject("ProfessionMenu", {
type = 'data source',
text = "ProfessionMenu",
icon = defIcon,
})
-local minimap = PROFESSIONMENU_MINIMAP
-
--Set Savedvariables defaults
local DefaultSettings = {
@@ -137,7 +134,7 @@ local profList = {
7413, -- Expert 225
7412, -- Journeyman 150
7411, -- Apprentice 75
- frame = {"ProfessionMenuExtractFrame", "Enchanting", "Right click to open disenchanting frame"}
+ frame = {_G["PROFESSIONMENU"]["Extractframe"], "Enchanting", "Right click to open disenchanting frame"}
}, --ENCHANTING
{
51306, -- Grand Master 450
@@ -210,8 +207,48 @@ local profSubList = {
1804,
8200016,
}
+
+function PM:OnEnable()
+ if icon then
+ self.map = {hide = self.db.minimap}
+ icon:Register('ProfessionMenu', minimap, self.map)
+ end
+
+ if self.db.menuPos then
+ local pos = self.db.menuPos
+ mainframe:ClearAllPoints()
+ mainframe:SetPoint(pos[1], pos[2], pos[3], pos[4], pos[5])
+ else
+ mainframe:ClearAllPoints()
+ mainframe:SetPoint("CENTER", UIParent)
+ end
+
+ self:ToggleMainButton("hide")
+
+ --self:RegisterEvent("ADDON_LOADED")
+ if self.db.ShowOldTradeSkillUI then
+ UIParent:UnregisterEvent("TRADE_SKILL_SHOW")
+ self:RegisterEvent("TRADE_SKILL_SHOW")
+ end
+
+ --Add the ProfessionMenu Extract Frame to the special frames tables to enable closing wih the ESC key
+ tinsert(UISpecialFrames, self.Extractframe)
+end
+
+function PM:OnInitialize()
+ if not ProfessionMenuDB then ProfessionMenuDB = {} end
+ self.db = ProfessionMenuDB
+ setupSettings(self.db)
+ --Enable the use of /PM or /PROFESSIONMENU to open the loot browser
+ SLASH_PROFESSIONMENU1 = "/PROFESSIONMENU"
+ SLASH_PROFESSIONMENU2 = "/PM"
+ SlashCmdList["PROFESSIONMENU"] = function(msg)
+ PM:SlashCommand(msg)
+ end
+end
+
function PM:UNIT_SPELLCAST_SUCCEEDED(event, arg1, arg2)
- PM:RemoveItem(arg2)
+ self:RemoveItem(arg2)
end
local cTip = CreateFrame("GameTooltip","cTooltip",nil,"GameTooltipTemplate")
@@ -255,23 +292,23 @@ local items = {
-- deletes item from players inventory if value 2 in the items table is set
function PM:RemoveItem(arg2)
- if not PM.db.DeleteItem then return end
+ if not self.db.DeleteItem then return end
for _, item in ipairs(items) do
if arg2 == item[2] then
- local found, bag, slot = PM:HasItem(item[1])
- if found and C_VanityCollection.IsCollectionItemOwned(item[1]) and PM:IsSoulbound(bag, slot) then
+ local found, bag, slot = self:HasItem(item[1])
+ if found and C_VanityCollection.IsCollectionItemOwned(item[1]) and self:IsSoulbound(bag, slot) then
PickupContainerItem(bag, slot)
DeleteCursorItem()
end
end
end
- PM:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED")
+ self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED")
end
-local function returnItemIDs()
+function PM:ReturnItemIDs()
local list = {}
for _, item in ipairs(items) do
- if PM:HasItem(item[1]) or C_VanityCollection.IsCollectionItemOwned(item[1]) then
+ if self:HasItem(item[1]) or C_VanityCollection.IsCollectionItemOwned(item[1]) then
tinsert(list, item[1])
end
end
@@ -279,7 +316,7 @@ local function returnItemIDs()
end
-- returns a list of known spellIDs
-local function returnSpellIDs()
+function PM:ReturnSpellIDs()
local list = {}
for _, spellID in ipairs(profSubList) do
if CA_IsSpellKnown(spellID) then
@@ -290,7 +327,7 @@ local function returnSpellIDs()
end
-- add altar summon button via dewdrop secure
-local function addItem(itemID)
+function PM:AddItem(itemID)
local name, _, _, _, _, _, _, _, _, icon = GetItemInfo(itemID)
local startTime, duration = GetItemCooldown(itemID)
local cooldown = math.ceil(((duration - (GetTime() - startTime))/60))
@@ -306,9 +343,9 @@ local function addItem(itemID)
'text', text,
'icon', icon,
'secure', secure,
- 'func', function() if not PM:HasItem(itemID) then RequestDeliverVanityCollectionItem(itemID) else if PM.db.DeleteItem then PM:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") end dewdrop:Close() end end,
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize
+ 'func', function() if not self:HasItem(itemID) then RequestDeliverVanityCollectionItem(itemID) else if self.db.DeleteItem then self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") end dewdrop:Close() end end,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize
)
end
@@ -317,8 +354,8 @@ function PM:AddDividerLine(maxLenght)
local text = WHITE.."----------------------------------------------------------------------------------------------------"
dewdrop:AddLine(
'text' , text:sub(1, maxLenght),
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
'isTitle', true,
"notCheckable", true
)
@@ -337,7 +374,7 @@ function PM:AddProfessions()
for _, prof in ipairs(profList) do
for _, spellID in ipairs(prof) do
- if IsSpellKnown(spellID) and ((prof.Show and PM.db[prof.Show]) or not prof.Show) then
+ if IsSpellKnown(spellID) and ((prof.Show and self.db[prof.Show]) or not prof.Show) then
local name, _, icon = GetSpellInfo(spellID)
if prof.Name then
name = prof.Name
@@ -347,13 +384,13 @@ function PM:AddProfessions()
profName = GetSpellInfo(prof.main)
end
local rank, maxRank = getProfessionRanks(profName)
- if not PM.db.hideRank and PM.db.hideMaxRank then
+ if not self.db.hideRank and self.db.hideMaxRank then
name = name .. " |cFF00FFFF("..rank..")"
end
- if not PM.db.hideMaxRank and PM.db.hideRank then
+ if not self.db.hideMaxRank and self.db.hideRank then
name = name .. " |cFF00FFFF("..maxRank..")"
end
- if not PM.db.hideMaxRank and not PM.db.hideRank then
+ if not self.db.hideMaxRank and not self.db.hideRank then
name = name .. " |cFF00FFFF("..rank.."/"..maxRank..")"
end
local secure = {
@@ -371,9 +408,9 @@ function PM:AddProfessions()
'icon', icon,
'secure', secure,
'closeWhenClicked', true,
- 'funcRight', function() PM:InventoryFrame_Open(openFrame) end,
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
+ 'funcRight', function() self:InventoryFrame_Open(openFrame) end,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
'tooltipTitle', tooltipTitle,
'tooltipText', tooltipText
)
@@ -384,64 +421,62 @@ function PM:AddProfessions()
end
--sets up the drop down menu for specs
-local function ProfessionMenu_DewdropRegister(self)
- if dewdrop:IsOpen(self) then dewdrop:Close() return end
- dewdrop:Register(self,
- 'point', function(parent)
- return "TOP", "BOTTOM"
- end,
+function PM:DewdropRegister(button, showUnlock, resetPoint)
+ if dewdrop:IsOpen(button) then dewdrop:Close() return end
+ dewdrop:Register(button,
+ 'point', function(parent) if resetPoint then return nil, nil else return "TOP", "BOTTOM" end end,
'children', function(level, value)
dewdrop:AddLine(
'text', "|cffffff00Professions",
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
'isTitle', true,
'notCheckable', true
)
- PM:AddProfessions()
+ self:AddProfessions()
local divider
- local SummonItems = returnItemIDs()
+ local SummonItems = self:ReturnItemIDs()
if #SummonItems > 0 then
- if not divider then divider = PM:AddDividerLine(35) end
+ if not divider then divider = self:AddDividerLine(35) end
for _, itemID in ipairs(SummonItems) do
- addItem(itemID)
+ self:AddItem(itemID)
end
end
if CA_IsSpellKnown(750750) then
- if not divider then divider = PM:AddDividerLine(35) end
+ if not divider then divider = self:AddDividerLine(35) end
local name, _, icon = GetSpellInfo(750750)
local secure = { type1 = 'spell', spell = name }
- dewdrop:AddLine( 'text', name, 'icon', icon, 'secure', secure, 'closeWhenClicked', true, 'textHeight', PM.db.txtSize, 'textWidth', PM.db.txtSize)
+ dewdrop:AddLine( 'text', name, 'icon', icon, 'secure', secure, 'closeWhenClicked', true, 'textHeight', self.db.txtSize, 'textWidth', self.db.txtSize)
end
- local spellIDs = returnSpellIDs()
+ local spellIDs = self:ReturnSpellIDs()
if #spellIDs > 0 then
- PM:AddDividerLine(35)
+ self:AddDividerLine(35)
for _, spellID in ipairs(spellIDs) do
local name, _, icon = GetSpellInfo(spellID)
local secure = { type1 = 'spell', spell = spellID }
- dewdrop:AddLine( 'text', name, 'icon', icon,'secure', secure, 'closeWhenClicked', true, 'textHeight', PM.db.txtSize, 'textWidth', PM.db.txtSize)
+ dewdrop:AddLine( 'text', name, 'icon', icon,'secure', secure, 'closeWhenClicked', true, 'textHeight', self.db.txtSize, 'textWidth', self.db.txtSize)
end
end
- PM:AddDividerLine(35)
- if self.show then
+ self:AddDividerLine(35)
+ if showUnlock then
dewdrop:AddLine(
'text', "Unlock Frame",
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
- 'func', PM.UnlockFrame,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
+ 'func', self.UnlockFrame,
'notCheckable', true,
'closeWhenClicked', true
)
end
dewdrop:AddLine(
'text', "Options",
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
- 'func', PM.Options_Toggle,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
+ 'func', self.Options_Toggle,
'notCheckable', true,
'closeWhenClicked', true
)
@@ -450,19 +485,19 @@ local function ProfessionMenu_DewdropRegister(self)
'textR', 0,
'textG', 1,
'textB', 1,
- 'textHeight', PM.db.txtSize,
- 'textWidth', PM.db.txtSize,
+ 'textHeight', self.db.txtSize,
+ 'textWidth', self.db.txtSize,
'closeWhenClicked', true,
'notCheckable', true
)
end,
'dontHook', true
)
- dewdrop:Open(self)
+ dewdrop:Open(button)
local hook
if not hook then
WorldFrame:HookScript("OnEnter", function()
- if dewdrop:IsOpen(self) then
+ if dewdrop:IsOpen(button) then
dewdrop:Close()
end
end)
@@ -472,8 +507,8 @@ local function ProfessionMenu_DewdropRegister(self)
GameTooltip:Hide()
end
-local function toggleMainButton(toggle)
- if PM.db.ShowMenuOnHover then
+function PM:ToggleMainButton(toggle)
+ if self.db.ShowMenuOnHover then
if toggle == "show" then
ProfessionMenuFrame_Menu:Show()
ProfessionMenuFrame.icon:Show()
@@ -501,21 +536,22 @@ function PM:UnlockFrame()
end
end
+function PM:CreateUI()
--Creates the main interface
mainframe = CreateFrame("Button", "ProfessionMenuFrame", UIParent, nil)
mainframe:SetSize(70,70)
mainframe:EnableMouse(true)
mainframe:RegisterForDrag("LeftButton")
- mainframe:SetScript("OnDragStart", function(self) mainframe:StartMoving() end)
- mainframe:SetScript("OnDragStop", function(self)
+ mainframe:SetScript("OnDragStart", function() mainframe:StartMoving() end)
+ mainframe:SetScript("OnDragStop", function()
mainframe:StopMovingOrSizing()
- PM.db.menuPos = {mainframe:GetPoint()}
- PM.db.menuPos[2] = "UIParent"
+ self.db.menuPos = {mainframe:GetPoint()}
+ self.db.menuPos[2] = "UIParent"
end)
mainframe:SetMovable(true)
mainframe:RegisterForClicks("RightButtonDown")
- mainframe:SetScript("OnClick", function(self, btnclick) if unlocked then PM:UnlockFrame() end end)
+ mainframe:SetScript("OnClick", function() if unlocked then self:UnlockFrame() end end)
mainframe.icon = mainframe:CreateTexture(nil, "ARTWORK")
mainframe.icon:SetSize(55,55)
mainframe.icon:SetPoint("CENTER", mainframe,"CENTER",0,0)
@@ -531,14 +567,14 @@ end
mainframe.Highlight:SetTexture("Interface\\AddOns\\AwAddons\\Textures\\EnchOverhaul\\Slot2Selected")
mainframe.Highlight:Hide()
mainframe:Hide()
- mainframe:SetScript("OnEnter", function(self)
+ mainframe:SetScript("OnEnter", function(button)
if unlocked then
- GameTooltip:SetOwner(self, "ANCHOR_TOP")
+ GameTooltip:SetOwner(button, "ANCHOR_TOP")
GameTooltip:AddLine("Left click to drag")
GameTooltip:AddLine("Right click to lock frame")
GameTooltip:Show()
else
- toggleMainButton("show")
+ self:ToggleMainButton("show")
end
end)
mainframe:SetScript("OnLeave", function() GameTooltip:Hide() end)
@@ -548,38 +584,28 @@ end
professionbutton:SetPoint("BOTTOM", ProfessionMenuFrame, "BOTTOM", 0, 2)
professionbutton:RegisterForClicks("LeftButtonDown", "RightButtonDown")
professionbutton:Show()
- professionbutton:SetScript("OnClick", function(self, btnclick) if not PM.db.autoMenu then ProfessionMenu_DewdropRegister(self) end end)
- professionbutton.show = true
- professionbutton:SetScript("OnEnter", function(self)
- if PM.db.autoMenu then
- ProfessionMenu_DewdropRegister(self)
- end
- if not dewdrop:IsOpen() then
- PM:OnEnter(self)
- end
+ professionbutton:SetScript("OnClick", function(button, btnclick) if not self.db.autoMenu then self:DewdropRegister(button, true) end end)
+ professionbutton:SetScript("OnEnter", function(button)
+ self:OnEnter(button, true)
mainframe.Highlight:Show()
- toggleMainButton("show")
+ self:ToggleMainButton("show")
end)
professionbutton:SetScript("OnLeave", function()
mainframe.Highlight:Hide()
GameTooltip:Hide()
- toggleMainButton("hide")
+ self:ToggleMainButton("hide")
end)
+end
+PM:CreateUI()
InterfaceOptionsFrame:HookScript("OnShow", function()
if InterfaceOptionsFrame and ProfessionMenuOptionsFrame:IsVisible() then
- PM:OpenOptions()
+ ProfessionMenu_OpenOptions()
end
end)
-function PM:OnInitialize()
- if not ProfessionMenuDB then ProfessionMenuDB = {} end
- PM.db = ProfessionMenuDB
- setupSettings(PM.db)
-end
-
-- toggle the main button frame
-local function toggleMainFrame()
+function PM:ToggleMainFrame()
if ProfessionMenuFrame:IsVisible() then
ProfessionMenuFrame:Hide()
else
@@ -588,54 +614,24 @@ local function toggleMainFrame()
end
--[[
-SlashCommand(msg):
+PM:SlashCommand(msg):
msg - takes the argument for the /mysticextended command so that the appropriate action can be performed
If someone types /mysticextended, bring up the options box
]]
-local function SlashCommand(msg)
+function PM:SlashCommand(msg)
if msg == "reset" then
ProfessionMenuDB = nil
PM:OnInitialize()
DEFAULT_CHAT_FRAME:AddMessage("Settings Reset")
elseif msg == "options" then
PM:Options_Toggle()
+ elseif msg == "macromenu" then
+ PM:DewdropRegister(GetMouseFocus(), nil, true)
else
- toggleMainFrame()
+ PM:ToggleMainFrame()
end
end
-function PM:OnEnable()
- if icon then
- PM.map = {hide = PM.db.minimap}
- icon:Register('ProfessionMenu', minimap, PM.map)
- end
-
- if PM.db.menuPos then
- local pos = PM.db.menuPos
- mainframe:ClearAllPoints()
- mainframe:SetPoint(pos[1], pos[2], pos[3], pos[4], pos[5])
- else
- mainframe:ClearAllPoints()
- mainframe:SetPoint("CENTER", UIParent)
- end
-
- toggleMainButton("hide")
- --Enable the use of /me or /mysticextended to open the loot browser
- SLASH_PROFESSIONMENU1 = "/PROFESSIONMENU"
- SLASH_PROFESSIONMENU2 = "/PM"
- SlashCmdList["PROFESSIONMENU"] = function(msg)
- SlashCommand(msg)
- end
- PM:RegisterEvent("ADDON_LOADED")
- if PM.db.ShowOldTradeSkillUI then
- UIParent:UnregisterEvent("TRADE_SKILL_SHOW")
- PM:RegisterEvent("TRADE_SKILL_SHOW")
- end
-
- --Add the ProfessionMenu Extract Frame to the special frames tables to enable closing wih the ESC key
- tinsert(UISpecialFrames, "ProfessionMenuExtractFrame")
-end
-
function PM:TRADE_SKILL_SHOW()
TradeSkillFrame_LoadUI()
if TradeSkillFrame_Show then
@@ -654,7 +650,7 @@ end
function minimap.OnClick(self, button)
GameTooltip:Hide()
if not PM.db.autoMenu then
- ProfessionMenu_DewdropRegister(self)
+ PM:DewdropRegister(self)
end
end
@@ -662,25 +658,25 @@ function minimap.OnLeave()
GameTooltip:Hide()
end
-function PM:OnEnter(self)
- if PM.db.autoMenu then
- ProfessionMenu_DewdropRegister(self)
+function PM:OnEnter(button, show)
+ if self.db.autoMenu and not UnitAffectingCombat("player") then
+ self:DewdropRegister(button, show)
else
- GameTooltip:SetOwner(self, 'ANCHOR_NONE')
- GameTooltip:SetPoint(GetTipAnchor(self))
+ GameTooltip:SetOwner(button, 'ANCHOR_NONE')
+ GameTooltip:SetPoint(GetTipAnchor(button))
GameTooltip:ClearLines()
GameTooltip:AddLine("ProfessionMenu")
GameTooltip:Show()
end
end
-function minimap.OnEnter(self)
- PM:OnEnter(self)
+function minimap.OnEnter(button)
+ PM:OnEnter(button)
end
function PM:ToggleMinimap()
- local hide = not PM.db.minimap
- PM.db.minimap = hide
+ local hide = not self.db.minimap
+ self.db.minimap = hide
if hide then
icon:Hide('ProfessionMenu')
else
@@ -692,7 +688,7 @@ function PM:UpdateButtonText(i)
local scrollFrame = HelpMenuFrameRightInsetItemRestorePanel.RecoveryScroll.ScrollFrame
local text = scrollFrame.buttons[i].SubText:GetText()
if scrollFrame.buttons[i].item then
- local spellID = PM:GetRecipeData(scrollFrame.buttons[i].item.ItemEntry, "item")
+ local spellID = self:GetRecipeData(scrollFrame.buttons[i].item.ItemEntry, "item")
if spellID then
if CA_IsSpellKnown(spellID) then
scrollFrame.buttons[i].SubText:SetText(text.." |cff1eff00(Known)")
@@ -709,7 +705,7 @@ function PM:InitializeTextUpdate()
local updateItemButtonOld = updateItemButton.Update
updateItemButton.Update = function(...)
updateItemButtonOld(...)
- PM:UpdateButtonText(i)
+ self:UpdateButtonText(i)
end
end
end
@@ -729,8 +725,8 @@ end
function PM:ADDON_LOADED(event, arg1, arg2, arg3)
-- setup for auction house window
if event == "ADDON_LOADED" and arg1 == "Ascension_HelpUI" then
- PM:LoadTradeskillRecipes()
- PM:InitializeTextUpdate()
+ self:LoadTradeskillRecipes()
+ self:InitializeTextUpdate()
end
end
diff --git a/ProfessionMenu/ProfessionMenu.toc b/ProfessionMenu/ProfessionMenu.toc
index a53bf56..0b56225 100644
--- a/ProfessionMenu/ProfessionMenu.toc
+++ b/ProfessionMenu/ProfessionMenu.toc
@@ -7,6 +7,6 @@
## X-Category: Profession
## X-OptionsFrame: ProfessionMenuOptionsFrame
## DefaultState: enabled
-## Version: 1.7
+## Version: 1.8
embeds.xml
diff --git a/ProfessionMenu/ProfessionMenuInventory.lua b/ProfessionMenu/ProfessionMenuInventory.lua
index 8f834cc..72bfc47 100644
--- a/ProfessionMenu/ProfessionMenuInventory.lua
+++ b/ProfessionMenu/ProfessionMenuInventory.lua
@@ -1,27 +1,31 @@
local PM = LibStub("AceAddon-3.0"):GetAddon("ProfessionMenu")
local dewdrop = AceLibrary("Dewdrop-2.0")
-local mainframe = CreateFrame("FRAME", "ProfessionMenuExtractFrame", UIParent,"UIPanelDialogTemplate")
- mainframe:SetSize(640,508)
- mainframe:SetPoint("CENTER",0,0)
- mainframe:EnableMouse(true)
- mainframe:SetMovable(true)
- mainframe:RegisterForDrag("LeftButton")
- mainframe:SetScript("OnDragStart", function(self) mainframe:StartMoving() end)
- mainframe:SetScript("OnDragStop", function(self) mainframe:StopMovingOrSizing() end)
- mainframe:SetScript("OnShow", function()
- PM:SearchBags()
- PM:RegisterEvent("BAG_UPDATE")
- end)
- mainframe:SetScript("OnHide", function()
- PM:UnregisterEvent("BAG_UPDATE")
- end)
- mainframe.TitleText = mainframe:CreateFontString()
- mainframe.TitleText:SetFont("Fonts\\FRIZQT__.TTF", 12)
- mainframe.TitleText:SetFontObject(GameFontNormal)
- mainframe.TitleText:SetText("Disenchanting List")
- mainframe.TitleText:SetPoint("TOP", 0, -9)
- mainframe.TitleText:SetShadowOffset(1,-1)
- mainframe:Hide()
+function PM:CreateInventoryUI()
+ self.Extractframe = CreateFrame("FRAME", "ProfessionMenuExtractFrame", UIParent,"UIPanelDialogTemplate")
+ local mainframe = self.Extractframe
+ mainframe:SetSize(640,508)
+ mainframe:SetPoint("CENTER",0,0)
+ mainframe:EnableMouse(true)
+ mainframe:SetMovable(true)
+ mainframe:RegisterForDrag("LeftButton")
+ mainframe:SetScript("OnDragStart", function(self) mainframe:StartMoving() end)
+ mainframe:SetScript("OnDragStop", function(self) mainframe:StopMovingOrSizing() end)
+ mainframe:SetScript("OnShow", function()
+ self:SearchBags()
+ self:RegisterEvent("BAG_UPDATE")
+ end)
+ mainframe:SetScript("OnHide", function()
+ self:UnregisterEvent("BAG_UPDATE")
+ end)
+ mainframe.TitleText = mainframe:CreateFontString()
+ mainframe.TitleText:SetFont("Fonts\\FRIZQT__.TTF", 12)
+ mainframe.TitleText:SetFontObject(GameFontNormal)
+ mainframe.TitleText:SetText("Disenchanting List")
+ mainframe.TitleText:SetPoint("TOP", 0, -9)
+ mainframe.TitleText:SetShadowOffset(1,-1)
+ mainframe:Hide()
+end
+PM:CreateInventoryUI()
PM.FilterList = {
[1] = {"Uncommon", 2},
@@ -84,7 +88,7 @@ local enchantingMats = {
}
}
-local function GetPosibleMats(quality, itemLevel)
+function PM:GetPosibleMats(quality, itemLevel)
if quality == 2 then
for _, mat in ipairs (enchantingMats.Commen) do
if itemLevel >= mat.itemLevel[1] and itemLevel <= mat.itemLevel[2] then
@@ -117,21 +121,20 @@ local InventoryTypes = {
function PM:InventoryFrame_Open(isEnabled)
if not isEnabled then return end
- if mainframe:IsVisible() then
- mainframe:Hide()
+ if self.Extractframe:IsVisible() then
+ self.Extractframe:Hide()
else
- mainframe:Show()
+ self.Extractframe:Show()
end
end
function PM:BAG_UPDATE()
- PM:ScheduleTimer(function() PM:SearchBags() end, .10)
-
+ self:ScheduleTimer(function() self:SearchBags() end, .10)
end
-local function filterCheck(quality, bagID, slotID)
- for _, _ in ipairs(PM.FilterList) do
- if (PM.db.FilterList[4] and PM:IsSoulbound(bagID, slotID)) or (quality < 1 or quality > 5) or PM.db.FilterList[quality-1] then
+function PM:FilterCheck(quality, bagID, slotID)
+ for _, _ in ipairs(self.FilterList) do
+ if (self.db.FilterList[4] and self:IsSoulbound(bagID, slotID)) or (quality < 1 or quality > 5) or self.db.FilterList[quality-1] then
return true
end
end
@@ -145,13 +148,13 @@ function PM:SearchBags()
if not bagThrottle then
inventoryItems = {}
for bagID = 0, 4 do
- if not PM.db.BagFilter[bagID+1] then
+ if not self.db.BagFilter[bagID+1] then
for slotID = 1, GetContainerNumSlots(bagID) do
local quality,_,_,link = select(4,GetContainerItemInfo(bagID,slotID))
local itemID = GetContainerItemID(bagID,slotID)
- if link and not PM.db.ItemBlacklist[itemID] then
+ if link and not self.db.ItemBlacklist[itemID] then
local itemLevel, _, itemType = select(4,GetItemInfo(itemID))
- if not filterCheck(quality, bagID, slotID) and InventoryTypes[itemType] then
+ if not self:FilterCheck(quality, bagID, slotID) and InventoryTypes[itemType] then
tinsert(inventoryItems,{bagID,slotID,link,quality,itemLevel})
end
end
@@ -159,35 +162,37 @@ function PM:SearchBags()
end
end
bagThrottle = true
- PM.bagThrottle = PM:ScheduleTimer(function() bagThrottle = false end, .1)
- ProfessionMenu_InventroyScrollFrameUpdate()
+ self.bagThrottle = self:ScheduleTimer(function() bagThrottle = false end, .1)
+ self:InventroyScrollFrameUpdate()
end
end
-function PM:ItemMenuRegister(self)
- dewdrop:Register(self,
+function PM:ItemMenuRegister(button)
+ if dewdrop:IsOpen(button) then dewdrop:Close() return end
+
+ dewdrop:Register(button,
'point', function(parent)
return "TOP", "BOTTOM"
end,
'children', function(level, value)
if level == 1 then
- for k, v in ipairs(PM.FilterList) do
+ for k, v in ipairs(self.FilterList) do
local text = v[1]
if tonumber(v[2]) then
text = select(4, GetItemQualityColor(v[2])) .. v[1]
end
dewdrop:AddLine(
'text', text,
- 'func', function() PM.db.FilterList[k] = not PM.db.FilterList[k] PM:SearchBags() end,
- 'checked', PM.db.FilterList[k],
+ 'func', function() self.db.FilterList[k] = not self.db.FilterList[k] self:SearchBags() end,
+ 'checked', self.db.FilterList[k],
'textHeight', 12,
'textWidth', 12
)
end
dewdrop:AddLine(
- 'text', PM.FilterList.Soulbound,
- 'func', function() PM.db.FilterList[4] = not PM.db.FilterList[4] PM:SearchBags() end,
- 'checked', PM.db.FilterList[4],
+ 'text', self.FilterList.Soulbound,
+ 'func', function() self.db.FilterList[4] = not self.db.FilterList[4] self:SearchBags() end,
+ 'checked', self.db.FilterList[4],
'textHeight', 12,
'textWidth', 12
)
@@ -211,11 +216,11 @@ function PM:ItemMenuRegister(self)
)
elseif level == 2 then
if value and value == "BagFilter" then
- for i, bag in ipairs(PM.FilterList.Bags) do
+ for i, bag in ipairs(self.FilterList.Bags) do
dewdrop:AddLine(
'text', bag,
- 'func', function() PM.db.BagFilter[i] = not PM.db.BagFilter[i] PM:SearchBags() end,
- 'checked', PM.db.BagFilter[i],
+ 'func', function() self.db.BagFilter[i] = not self.db.BagFilter[i] self:SearchBags() end,
+ 'checked', self.db.BagFilter[i],
'textHeight', 12,
'textWidth', 12
)
@@ -225,9 +230,12 @@ function PM:ItemMenuRegister(self)
end,
'dontHook', true
)
+ dewdrop:Open(button)
end
------------------ScrollFrameTooltips---------------------------
+function PM:DeScrollFrameCreate()
+
local function ItemTemplate_OnEnter(self)
if not self.link then return end
GameTooltip:SetOwner(self, "ANCHOR_RIGHT", -13, -50)
@@ -244,26 +252,31 @@ end
local ROW_HEIGHT = 16 -- How tall is each row?
local MAX_ROWS = 25 -- How many rows can be shown at once?
-local scrollFrame = CreateFrame("Frame", "ProfessionMenu_DE_ScrollFrame", ProfessionMenuExtractFrame)
- scrollFrame:EnableMouse(true)
- scrollFrame:SetSize(mainframe:GetWidth()-40, ROW_HEIGHT * MAX_ROWS + 16)
- scrollFrame:SetPoint("TOP",0,-42)
- scrollFrame:SetBackdrop({
- bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", tile = true, tileSize = 16,
- edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16,
- insets = { left = 4, right = 4, top = 4, bottom = 4 },
- })
-function ProfessionMenu_InventroyScrollFrameUpdate()
+ self.DeScrollFrame = CreateFrame("Frame", "", self.Extractframe)
+ local scrollFrame = self.DeScrollFrame
+ scrollFrame:EnableMouse(true)
+ scrollFrame:SetSize(self.Extractframe:GetWidth()-40, ROW_HEIGHT * MAX_ROWS + 16)
+ scrollFrame:SetPoint("TOP",0,-42)
+ scrollFrame:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", tile = true, tileSize = 16,
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16,
+ insets = { left = 4, right = 4, top = 4, bottom = 4 },
+ })
+
+
+
+function PM:InventroyScrollFrameUpdate()
local maxValue = #inventoryItems
FauxScrollFrame_Update(scrollFrame.scrollBar, maxValue, MAX_ROWS, ROW_HEIGHT)
local offset = FauxScrollFrame_GetOffset(scrollFrame.scrollBar)
for i = 1, MAX_ROWS do
local value = i + offset
scrollFrame.rows[i]:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
+ scrollFrame.rows[i]:Hide()
if value <= maxValue then
local row = scrollFrame.rows[i]
- local text1, text2 = GetPosibleMats(inventoryItems[value][4], inventoryItems[value][5])
+ local text1, text2 = self:GetPosibleMats(inventoryItems[value][4], inventoryItems[value][5])
row.Text:SetText(inventoryItems[value][3])
row.Text1:SetText(text1)
if text2 then
@@ -280,18 +293,16 @@ function ProfessionMenu_InventroyScrollFrameUpdate()
row:SetAttribute("target-slot", row.slot)
row.tNumber = value
row:Show()
- else
- scrollFrame.rows[i]:Hide()
end
end
end
-local scrollSlider = CreateFrame("ScrollFrame","ProfessionMenuDEListFrameScroll",ProfessionMenu_DE_ScrollFrame,"FauxScrollFrameTemplate")
+local scrollSlider = CreateFrame("ScrollFrame","ProfessionMenuDEListFrameScroll",self.DeScrollFrame,"FauxScrollFrameTemplate")
scrollSlider:SetPoint("TOPLEFT", 0, -8)
scrollSlider:SetPoint("BOTTOMRIGHT", -30, 8)
scrollSlider:SetScript("OnVerticalScroll", function(self, offset)
self.offset = math.floor(offset / ROW_HEIGHT + 0.5)
- ProfessionMenu_InventroyScrollFrameUpdate()
+ PM:InventroyScrollFrameUpdate()
end)
scrollFrame.scrollBar = scrollSlider
@@ -312,6 +323,11 @@ local rows = setmetatable({}, { __index = function(t, i)
row.Text2:SetSize(180, ROW_HEIGHT)
row.Text2:SetPoint("LEFT",row,390,0)
row.Text2:SetJustifyH("LEFT")
+ row:SetScript("OnShow", function(self)
+ if GameTooltip:GetOwner() == self:GetName() then
+ ItemTemplate_OnEnter(self)
+ end
+ end)
row:SetScript("OnEnter", function(self)
ItemTemplate_OnEnter(self)
end)
@@ -328,17 +344,14 @@ end })
scrollFrame.rows = rows
--Shows a menu with options and sharing options
-local extractMenu = CreateFrame("Button", "ProfessionMenu_ExtractInterface_FilterMenu", ProfessionMenu_DE_ScrollFrame, "FilterDropDownMenuTemplate")
+local extractMenu = CreateFrame("Button", "ProfessionMenu_ExtractInterface_FilterMenu", self.DeScrollFrame, "FilterDropDownMenuTemplate")
extractMenu:SetSize(133, 30)
- extractMenu:SetPoint("BOTTOMRIGHT", ProfessionMenu_DE_ScrollFrame, "BOTTOMRIGHT", 0, -35)
+ extractMenu:SetPoint("BOTTOMRIGHT", self.DeScrollFrame, "BOTTOMRIGHT", 0, -35)
extractMenu:RegisterForClicks("LeftButtonDown")
- extractMenu:SetScript("OnClick", function(self)
- if dewdrop:IsOpen() then
- dewdrop:Close()
- else
- PM:ItemMenuRegister(self)
- dewdrop:Open(self)
- end
+ extractMenu:SetScript("OnClick", function(button)
+ self:ItemMenuRegister(button)
end)
+end
+PM:DeScrollFrameCreate()
diff --git a/ProfessionMenu/ProfessionMenuOptions.lua b/ProfessionMenu/ProfessionMenuOptions.lua
index 0c4953c..bf5a1a9 100644
--- a/ProfessionMenu/ProfessionMenuOptions.lua
+++ b/ProfessionMenu/ProfessionMenuOptions.lua
@@ -8,13 +8,15 @@ function PM:Options_Toggle()
end
end
-function PM:OpenOptions()
+function ProfessionMenu_OpenOptions()
if InterfaceOptionsFrame:GetWidth() < 850 then InterfaceOptionsFrame:SetWidth(850) end
- PM:DropDownInitialize()
+ ProfessionMenu_DropDownInitialize()
UIDropDownMenu_SetText(ProfessionMenuOptions_TxtSizeMenu, PM.db.txtSize)
end
--Creates the options frame and all its assets
+
+function PM:CreateOptionsUI()
if InterfaceOptionsFrame:GetWidth() < 850 then InterfaceOptionsFrame:SetWidth(850) end
local mainframe = {}
mainframe.panel = CreateFrame("FRAME", "ProfessionMenuOptionsFrame", UIParent, nil)
@@ -31,12 +33,12 @@ end
hideMenu.Lable:SetPoint("LEFT", 30, 0)
hideMenu.Lable:SetText("Hide Standalone Button")
hideMenu:SetScript("OnClick", function()
- if PM.db.HideMenu then
+ if self.db.HideMenu then
ProfessionMenuFrame:Show()
- PM.db.HideMenu = false
+ self.db.HideMenu = false
else
ProfessionMenuFrame:Hide()
- PM.db.HideMenu = true
+ self.db.HideMenu = true
end
end)
@@ -47,16 +49,16 @@ end
hideHover.Lable:SetPoint("LEFT", 30, 0)
hideHover.Lable:SetText("Only Show Standalone Button on Hover")
hideHover:SetScript("OnClick", function()
- if PM.db.ShowMenuOnHover then
+ if self.db.ShowMenuOnHover then
ProfessionMenuFrame_Menu:Show()
ProfessionMenuFrame.icon:Show()
ProfessionMenuFrame.Text:Show()
- PM.db.ShowMenuOnHover = false
+ self.db.ShowMenuOnHover = false
else
ProfessionMenuFrame_Menu:Hide()
ProfessionMenuFrame.icon:Hide()
ProfessionMenuFrame.Text:Hide()
- PM.db.ShowMenuOnHover = true
+ self.db.ShowMenuOnHover = true
end
end)
@@ -67,7 +69,7 @@ end
hideMinimap.Lable:SetJustifyH("LEFT")
hideMinimap.Lable:SetPoint("LEFT", 30, 0)
hideMinimap.Lable:SetText("Hide Minimap Icon")
- hideMinimap:SetScript("OnClick", function() PM:ToggleMinimap() end)
+ hideMinimap:SetScript("OnClick", function() self:ToggleMinimap() end)
local itemDel = CreateFrame("CheckButton", "ProfessionMenuOptions_DeleteMenu", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
itemDel:SetPoint("TOPLEFT", 15, -165)
@@ -75,7 +77,7 @@ end
itemDel.Lable:SetJustifyH("LEFT")
itemDel.Lable:SetPoint("LEFT", 30, 0)
itemDel.Lable:SetText("Delete vanity items after summoning")
- itemDel:SetScript("OnClick", function() PM.db.DeleteItem = not PM.db.DeleteItem end)
+ itemDel:SetScript("OnClick", function() self.db.DeleteItem = not self.db.DeleteItem end)
local autoMenu = CreateFrame("CheckButton", "ProfessionMenuOptions_AutoMenu", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
autoMenu:SetPoint("TOPLEFT", 15, -200)
@@ -83,7 +85,7 @@ end
autoMenu.Lable:SetJustifyH("LEFT")
autoMenu.Lable:SetPoint("LEFT", 30, 0)
autoMenu.Lable:SetText("Show menu on hover")
- autoMenu:SetScript("OnClick", function() PM.db.autoMenu = not PM.db.autoMenu end)
+ autoMenu:SetScript("OnClick", function() self.db.autoMenu = not self.db.autoMenu end)
local hideRank = CreateFrame("CheckButton", "ProfessionMenuOptions_HideRank", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
hideRank:SetPoint("TOPLEFT", 15, -235)
@@ -91,7 +93,7 @@ end
hideRank.Lable:SetJustifyH("LEFT")
hideRank.Lable:SetPoint("LEFT", 30, 0)
hideRank.Lable:SetText("Hide profession rank")
- hideRank:SetScript("OnClick", function() PM.db.hideRank = not PM.db.hideRank end)
+ hideRank:SetScript("OnClick", function() self.db.hideRank = not self.db.hideRank end)
local hideMaxRank = CreateFrame("CheckButton", "ProfessionMenuOptions_HideMaxRank", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
hideMaxRank:SetPoint("TOPLEFT", 15, -270)
@@ -99,7 +101,7 @@ end
hideMaxRank.Lable:SetJustifyH("LEFT")
hideMaxRank.Lable:SetPoint("LEFT", 30, 0)
hideMaxRank.Lable:SetText("Hide profession max rank")
- hideMaxRank:SetScript("OnClick", function() PM.db.hideMaxRank = not PM.db.hideMaxRank end)
+ hideMaxRank:SetScript("OnClick", function() self.db.hideMaxRank = not self.db.hideMaxRank end)
local showHerb = CreateFrame("CheckButton", "ProfessionMenuOptions_ShowHerb", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
showHerb:SetPoint("TOPLEFT", 15, -305)
@@ -107,7 +109,7 @@ end
showHerb.Lable:SetJustifyH("LEFT")
showHerb.Lable:SetPoint("LEFT", 30, 0)
showHerb.Lable:SetText("Show Herbalism")
- showHerb:SetScript("OnClick", function() PM.db.showHerb = not PM.db.showHerb end)
+ showHerb:SetScript("OnClick", function() self.db.showHerb = not self.db.showHerb end)
local showOldTradeUI = CreateFrame("CheckButton", "ProfessionMenuOptions_ShowOldTradeSkillUI", ProfessionMenuOptionsFrame, "UICheckButtonTemplate")
showOldTradeUI:SetPoint("TOPLEFT", 15, -335)
@@ -116,12 +118,12 @@ end
showOldTradeUI.Lable:SetPoint("LEFT", 30, 0)
showOldTradeUI.Lable:SetText("Show old Blizzard Trade Skill UI")
showOldTradeUI:SetScript("OnClick", function()
- PM.db.ShowOldTradeSkillUI = not PM.db.ShowOldTradeSkillUI
- if PM.db.ShowOldTradeSkillUI then
+ self.db.ShowOldTradeSkillUI = not self.db.ShowOldTradeSkillUI
+ if self.db.ShowOldTradeSkillUI then
UIParent:UnregisterEvent("TRADE_SKILL_SHOW")
- PM:RegisterEvent("TRADE_SKILL_SHOW")
+ self:RegisterEvent("TRADE_SKILL_SHOW")
else
- PM:UnregisterEvent("TRADE_SKILL_SHOW")
+ self:UnregisterEvent("TRADE_SKILL_SHOW")
UIParent:RegisterEvent("TRADE_SKILL_SHOW")
end
end)
@@ -132,8 +134,11 @@ end
txtSize.Lable:SetJustifyH("LEFT")
txtSize.Lable:SetPoint("LEFT", txtSize, 190, 0)
txtSize.Lable:SetText("Menu Text Size")
+end
- local function options_Menu_Initialize()
+PM:CreateOptionsUI()
+
+ function ProfessionMenu_Options_Menu_Initialize()
local info
for i = 10, 25 do
info = {
@@ -148,9 +153,9 @@ end
end
end
- function PM:DropDownInitialize()
+ function ProfessionMenu_DropDownInitialize()
--Setup for Dropdown menus in the settings
- UIDropDownMenu_Initialize(ProfessionMenuOptions_TxtSizeMenu, options_Menu_Initialize)
+ UIDropDownMenu_Initialize(ProfessionMenuOptions_TxtSizeMenu, ProfessionMenu_Options_Menu_Initialize )
UIDropDownMenu_SetSelectedID(ProfessionMenuOptions_TxtSizeMenu)
UIDropDownMenu_SetWidth(ProfessionMenuOptions_TxtSizeMenu, 150)
end
\ No newline at end of file
diff --git a/ProfessionMenu/embeds.xml b/ProfessionMenu/embeds.xml
index 8ee5203..2b6f1c8 100644
--- a/ProfessionMenu/embeds.xml
+++ b/ProfessionMenu/embeds.xml
@@ -7,6 +7,7 @@
+