annotate LibModuleDBShare-1.0/LibModuleDBShare-1.0.lua @ 46:eb3383e30b5e

Corrected error in default slash command handler function.
author Andrew Knoll <andrewtknoll@gmail.com>
date Fri, 12 Apr 2013 22:57:15 -0400
parents 9e1b25004509
children c48d2d940e82
rev   line source
andrewtknoll@33 1 --- **LibModuleDBShare-1.0** provides a shared profile manager for addons without a central core.
andrewtknoll@33 2 -- A basic options panel for the group is added to the Blizzard options panel, as well as a
andrewtknoll@33 3 -- standard profile manager as a subpanel. Changes through the profiles panel are propagated
andrewtknoll@33 4 -- to member databases. The root panel can be used as a parent for your module config panels,
andrewtknoll@33 5 -- to keep all your addon's config in one place. The root panel's name is the same as the group's
andrewtknoll@33 6 -- name.\\
andrewtknoll@33 7 -- \\
andrewtknoll@35 8 -- A group can be created using the ':NewGroup' library method. The returned object inherits all
andrewtknoll@35 9 -- methods of the DBGroup object described below.\\
andrewtknoll@33 10 -- \\
andrewtknoll@33 11 -- **LibDualSpec Support**\\
andrewtknoll@33 12 -- LibModuleDBShare can use LibDualSpec to manage automatic profile switching with talent spec
andrewtknoll@33 13 -- changes. This integration is handled by the library; there is no need to use LibDualSpec
andrewtknoll@40 14 -- on member databases directly.\\
andrewtknoll@40 15 -- \\
andrewtknoll@40 16 -- **Slash Command Support**\\
andrewtknoll@40 17 -- LibModuleDBShare can associate a slash command with a DBGroup. The default handler function
andrewtknoll@40 18 -- for the slash command opens the root options panel.\\
andrewtknoll@40 19 -- Additional handler functions can be registered to respond to specific arguments given to the
andrewtknoll@44 20 -- slash command. If you provide a custom handler function for the slash command, that function
andrewtknoll@44 21 -- is responsible for detecting secondary commands.
>@5 22 --
>@5 23 -- @usage
andrewtknoll@33 24 -- local database;
andrewtknoll@33 25 -- -- this function is called after the ADDON_LOADED event fires
andrewtknoll@33 26 -- function initializeDB()
andrewtknoll@33 27 -- database = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true);
andrewtknoll@33 28 -- local group = LibStub("LibModuleDBShare-1.0"):GetGroup("Group Name");
andrewtknoll@33 29 -- if not group then
andrewtknoll@33 30 -- group = LibStub("LibModuleDBShare-1.0"):NewGroup("Group Name", "A description for this group.", database);
andrewtknoll@33 31 -- else
andrewtknoll@33 32 -- group:AddDB(database);
andrewtknoll@33 33 -- end
andrewtknoll@40 34 -- -- if you want to add a slash command
andrewtknoll@40 35 -- if not group:HasSlashCommand() then
andrewtknoll@40 36 -- group:EnableSlashCommand("COMMAND_NAME", "/groupname");
andrewtknoll@40 37 -- end
andrewtknoll@33 38 -- end
>@5 39 -- @class file
andrewtknoll@33 40 -- @name LibModuleDBShare-1.0
andrewtknoll@39 41 local MAJOR, MINOR = "LibModuleDBShare-1.0", 5
>@3 42 local LibModuleDBShare, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
>@3 43
>@4 44 if not LibModuleDBShare then return end -- No upgrade needed
>@4 45
andrewtknoll@29 46 -- Lua functions
andrewtknoll@26 47 local error, type, pairs, time = error, type, pairs, time;
andrewtknoll@15 48
andrewtknoll@17 49 -- Required Libraries
@12 50 local AceDB = LibStub("AceDB-3.0");
andrewtknoll@17 51 local AceDBOptions = LibStub("AceDBOptions-3.0");
andrewtknoll@17 52 local AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
andrewtknoll@17 53 local AceConfigDialog = LibStub("AceConfigDialog-3.0");
@12 54
andrewtknoll@28 55 -- Optional Libraries
andrewtknoll@28 56 local LibDualSpec = LibStub("LibDualSpec-1.0", true);
andrewtknoll@28 57
>@4 58 LibModuleDBShare.groups = LibModuleDBShare.groups or {};
>@4 59
>@5 60 local DBGroup = {};
>@5 61
>@5 62 --- Creates a new DB group.
andrewtknoll@42 63 -- @paramsig groupName, groupDescription, initialDB[, usesDualSpec]
andrewtknoll@40 64 -- @param groupName The name of the new DB group, as shown in the options panel. (string)
andrewtknoll@40 65 -- @param groupDescription A description of the group to be shown in the root options panel. (string)
andrewtknoll@40 66 -- @param initialDB The first DB to add to the group. (table)
andrewtknoll@40 67 -- @param usesDualSpec True if this group should use LibDualSpec, false otherwise. (boolean or nil)
andrewtknoll@44 68 -- @return the new DB group object (table)
andrewtknoll@21 69 function LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec)
andrewtknoll@35 70 -- check to see if LibDualSpec has been loaded
andrewtknoll@35 71 if not LibDualSpec then
andrewtknoll@35 72 LibDualSpec = LibStub("LibDualSpec-1.0", true);
andrewtknoll@35 73 end
andrewtknoll@21 74 -- verify parameters
andrewtknoll@26 75 if type(groupName) ~= "string" then
andrewtknoll@26 76 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'groupName' must be a string.", 2);
andrewtknoll@26 77 elseif type(groupDescription) ~= "string" then
andrewtknoll@26 78 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'groupDescription' must be a string.", 2);
andrewtknoll@26 79 elseif type(LibModuleDBShare.groups[groupName]) ~= "nil" then
andrewtknoll@31 80 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): group '"..groupName.."' already exists.", 2);
andrewtknoll@27 81 elseif type(initialDB) ~= "table" or not AceDB.db_registry[initialDB] then
andrewtknoll@31 82 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'initialDB' must be an AceDB-3.0 database.", 2);
andrewtknoll@31 83 elseif initialDB.parent then
andrewtknoll@31 84 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'initialDB' must not be a namespace.", 2)
andrewtknoll@28 85 elseif type(usesDualSpec) ~= "boolean" and type(usesDualSpec) ~= "nil" then
andrewtknoll@31 86 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'usesDualSpec' must be a boolean or nil.", 2);
andrewtknoll@28 87 elseif usesDualSpec and not LibDualSpec then
andrewtknoll@31 88 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'usesDualSpec' cannot be true without LibDualSpec-1.0 installed.", 2);
andrewtknoll@26 89 end
andrewtknoll@21 90 -- create group
@12 91 local group = {}
@12 92 group.name = groupName;
andrewtknoll@21 93 group.members = {};
andrewtknoll@21 94 -- create root option panel for group
andrewtknoll@17 95 group.rootOptionsTable = {
andrewtknoll@17 96 type = "group",
andrewtknoll@17 97 name = groupName,
andrewtknoll@17 98 args = {
andrewtknoll@17 99 text = {
andrewtknoll@17 100 type = "description",
andrewtknoll@21 101 name = groupDescription,
andrewtknoll@17 102 },
andrewtknoll@17 103 },
andrewtknoll@17 104 };
andrewtknoll@17 105 AceConfigRegistry:RegisterOptionsTable(groupName, group.rootOptionsTable);
andrewtknoll@17 106 AceConfigDialog:AddToBlizOptions(groupName);
andrewtknoll@21 107 -- create sync DB and profile options page
@12 108 group.syncDBTable = {};
andrewtknoll@21 109 group.syncDB = AceDB:New(group.syncDBTable, nil, initialDB:GetCurrentProfile());
andrewtknoll@17 110 group.profileOptionsTable = AceDBOptions:GetOptionsTable(group.syncDB, false);
andrewtknoll@28 111 if usesDualSpec then
andrewtknoll@29 112 group.usesDualSpec = true;
andrewtknoll@28 113 LibDualSpec:EnhanceDatabase(group.syncDB, groupName);
andrewtknoll@28 114 LibDualSpec:EnhanceOptions(group.profileOptionsTable, group.syncDB);
andrewtknoll@29 115 else
andrewtknoll@29 116 group.usesDualSpec = false;
andrewtknoll@28 117 end
andrewtknoll@17 118 AceConfigRegistry:RegisterOptionsTable(groupName.."Profiles", group.profileOptionsTable);
andrewtknoll@18 119 AceConfigDialog:AddToBlizOptions(groupName.."Profiles", group.profileOptionsTable.name, groupName);
andrewtknoll@21 120 -- add all profiles from initialDB to syncDB
andrewtknoll@21 121 for i, profile in pairs(initialDB:GetProfiles()) do
andrewtknoll@21 122 group.syncDB:SetProfile(profile);
andrewtknoll@21 123 end
andrewtknoll@28 124 -- load profile info from initialDB
andrewtknoll@21 125 group.syncDB:SetProfile(initialDB:GetCurrentProfile());
andrewtknoll@27 126 group.members[initialDB] = initialDB:GetNamespace(MAJOR, true) or initialDB:RegisterNamespace(MAJOR);
andrewtknoll@29 127 local storedData = group.members[initialDB].char;
andrewtknoll@29 128 if type(storedData.logoutTimestamp) == "number" then
andrewtknoll@29 129 group.profileTimestamp = storedData.logoutTimestamp;
andrewtknoll@22 130 else
andrewtknoll@22 131 group.profileTimestamp = 0;
andrewtknoll@22 132 end
andrewtknoll@35 133 if usesDualSpec then
andrewtknoll@35 134 local LDSnamespace = group.syncDB:GetNamespace("LibDualSpec-1.0");
andrewtknoll@35 135 LDSnamespace.char.enabled = storedData.dualSpecEnabled;
andrewtknoll@35 136 LDSnamespace.char.profile = storedData.altProfile;
andrewtknoll@35 137 LDSnamespace.char.specGroup = storedData.activeSpecGroup;
andrewtknoll@30 138 group.syncDB:CheckDualSpecState();
andrewtknoll@35 139 else
andrewtknoll@35 140 group.syncDB.char.enabled = storedData.dualSpecEnabled;
andrewtknoll@35 141 group.syncDB.char.profile = storedData.altProfile;
andrewtknoll@35 142 group.syncDB.char.specGroup = storedData.activeSpecGroup;
andrewtknoll@28 143 end
andrewtknoll@21 144 -- add methods and callbacks
@12 145 for k, v in pairs(DBGroup) do
@12 146 group[k] = v;
@12 147 end
andrewtknoll@19 148 group.syncDB.RegisterCallback(group, "OnProfileChanged", "OnProfileChanged");
andrewtknoll@19 149 group.syncDB.RegisterCallback(group, "OnProfileDeleted", "OnProfileDeleted");
andrewtknoll@19 150 group.syncDB.RegisterCallback(group, "OnProfileCopied", "OnProfileCopied");
andrewtknoll@19 151 group.syncDB.RegisterCallback(group, "OnProfileReset", "OnProfileReset");
andrewtknoll@28 152 group.syncDB.RegisterCallback(group, "OnDatabaseShutdown", "OnSyncShutdown");
andrewtknoll@41 153 group.members[initialDB].RegisterCallback(group, "OnDatabaseShutdown", "OnMemberShutdown"); -- register the namespace, not the base db
andrewtknoll@20 154 group.squelchCallbacks = false;
andrewtknoll@19 155 LibModuleDBShare.groups[groupName] = group;
@12 156 return group;
>@4 157 end
>@4 158
>@5 159 --- Retrieves an existing DB group.
andrewtknoll@40 160 -- @param groupName The name of the DB group to retrieve. (string)
andrewtknoll@44 161 -- @return the DB group object, or ##nil## if not found (table)
>@5 162 function LibModuleDBShare:GetGroup(groupName)
andrewtknoll@27 163 if type(groupName) ~= "string" then
andrewtknoll@27 164 error("Usage: LibModuleDBShare:GetGroup(groupName): 'groupName' must be a string.", 2);
andrewtknoll@27 165 end
@12 166 return LibModuleDBShare.groups[groupName];
>@4 167 end
>@5 168
>@5 169 --- Adds a database to the group.
andrewtknoll@40 170 -- @param newDB The database to add. (table)
andrewtknoll@22 171 function DBGroup:AddDB(newDB)
andrewtknoll@22 172 -- verify parameters
andrewtknoll@26 173 if type(newDB) ~= "table" or not AceDB.db_registry[newDB] then
andrewtknoll@31 174 error("Usage: DBGroup:AddDB(newDB): 'newDB' must be an AceDB-3.0 database.", 2);
andrewtknoll@31 175 elseif newDB.parent then
andrewtknoll@31 176 error("Usage: DBGroup:AddDB(newDB): 'newDB' must not be a namespace.", 2)
andrewtknoll@26 177 elseif type(self.members[newDB]) ~= "nil" then
andrewtknoll@31 178 error("Usage: DBGroup:AddDB(newDB): 'newDB' is already a member of DBGroup.", 2);
andrewtknoll@31 179 end
andrewtknoll@31 180 for groupName, group in pairs(LibModuleDBShare.groups) do
andrewtknoll@31 181 if group.members[newDB] ~= nil then
andrewtknoll@31 182 error("Usage: DBGroup:AddDB(newDB): 'newDB' is already a member of group '"..groupName.."'.", 2);
andrewtknoll@31 183 end
andrewtknoll@26 184 end
andrewtknoll@22 185 -- record current profile
andrewtknoll@20 186 local syncProfile = self.syncDB:GetCurrentProfile();
andrewtknoll@22 187 -- add new profiles to syncDB
andrewtknoll@20 188 self.squelchCallbacks = true;
andrewtknoll@22 189 for i, profile in pairs(newDB:GetProfiles()) do
andrewtknoll@20 190 self.syncDB:SetProfile(profile);
andrewtknoll@20 191 end
andrewtknoll@22 192 -- set current profile based on timestamps
andrewtknoll@27 193 local namespace = newDB:GetNamespace(MAJOR, true) or newDB:RegisterNamespace(MAJOR);
andrewtknoll@29 194 local storedData = namespace.char;
andrewtknoll@29 195 if type(storedData.logoutTimestamp) == "number" and storedData.logoutTimestamp > self.profileTimestamp then
andrewtknoll@22 196 self.squelchCallbacks = false;
andrewtknoll@22 197 self.syncDB:SetProfile(newDB:GetCurrentProfile());
andrewtknoll@29 198 self.profileTimestamp = storedData.logoutTimestamp;
andrewtknoll@35 199 if self.usesDualSpec and storedData.altProfile then
andrewtknoll@35 200 local LDSnamespace = group.syncDB:GetNamespace("LibDualSpec-1.0");
andrewtknoll@35 201 LDSnamespace.char.enabled = storedData.dualSpecEnabled;
andrewtknoll@35 202 LDSnamespace.char.profile = storedData.altProfile;
andrewtknoll@35 203 LDSnamespace.char.specGroup = storedData.activeSpecGroup;
andrewtknoll@30 204 group.syncDB:CheckDualSpecState();
andrewtknoll@35 205 elseif storedData.altProfile then
andrewtknoll@35 206 self.syncDB.char.enabled = storedData.dualSpecEnabled;
andrewtknoll@35 207 self.syncDB.char.profile = storedData.altProfile;
andrewtknoll@35 208 self.syncDB.char.specGroup = storedData.activeSpecGroup;
andrewtknoll@28 209 end
andrewtknoll@20 210 else
andrewtknoll@20 211 self.syncDB:SetProfile(syncProfile);
andrewtknoll@22 212 newDB:SetProfile(syncProfile);
andrewtknoll@22 213 self.squelchCallbacks = false;
andrewtknoll@20 214 end
andrewtknoll@22 215 -- add to members list
andrewtknoll@27 216 self.members[newDB] = namespace;
andrewtknoll@41 217 namespace.RegisterCallback(self, "OnDatabaseShutdown", "OnMemberShutdown"); -- register the namespace, not the base db
>@5 218 end
andrewtknoll@18 219
andrewtknoll@39 220 -- LibDualSpec support
andrewtknoll@39 221
andrewtknoll@35 222 --- Checks to see if this group uses LibDualSpec.
andrewtknoll@44 223 -- @return ##true## if this group uses LibDualSpec, ##false## otherwise (boolean)
andrewtknoll@35 224 function DBGroup:IsUsingDualSpec()
andrewtknoll@35 225 return self.usesDualSpec;
andrewtknoll@35 226 end
andrewtknoll@35 227
andrewtknoll@35 228 --- Enables dual spec support if not already enabled.
andrewtknoll@35 229 function DBGroup:EnableDualSpec()
andrewtknoll@35 230 if not LibDualSpec then
andrewtknoll@35 231 LibDualSpec = LibStub("LibDualSpec-1.0"); -- this will error if LDS isn't found
andrewtknoll@35 232 end
andrewtknoll@35 233 if not self.usesDualSpec then
andrewtknoll@35 234 LibDualSpec:EnhanceDatabase(self.syncDB, self.name);
andrewtknoll@35 235 LibDualSpec:EnhanceOptions(self.profileOptionsTable, self.syncDB);
andrewtknoll@37 236 AceConfigRegistry:NotifyChange(self.name.."Profiles");
andrewtknoll@35 237 self.usesDualSpec = true;
andrewtknoll@35 238 local namespace = self.syncDB:GetNamespace("LibDualSpec-1.0");
andrewtknoll@35 239 namespace.char.enabled = self.syncDB.char.enabled;
andrewtknoll@35 240 namespace.char.profile = self.syncDB.char.profile;
andrewtknoll@35 241 namespace.char.specGroup = self.syncDB.char.specGroup;
andrewtknoll@35 242 self.syncDB:CheckDualSpecState();
andrewtknoll@35 243 end
andrewtknoll@35 244 end
andrewtknoll@35 245
andrewtknoll@39 246 -- slash command support
andrewtknoll@39 247
andrewtknoll@39 248 --- Adds a slash command to the group.
andrewtknoll@42 249 -- @paramsig slug, commandList[, handler]
andrewtknoll@40 250 -- @param slug The base identifier to use for the slash command. (string)
andrewtknoll@40 251 -- @param commandList The command itself, or a list of commands to use. (string or table)
andrewtknoll@40 252 -- @param handler A handler function for the command. If nil, defaults to a function that
andrewtknoll@40 253 -- calls the appropriate secondary command, or opens the root options panel. (function)
andrewtknoll@39 254 function DBGroup:EnableSlashCommand(slug, commandList, handler)
andrewtknoll@39 255 if self.slug then
andrewtknoll@39 256 error("Usage: DBGroup:EnableSlashCommand(slug, commandList[, handler]): group already has a slash command.", 2);
andrewtknoll@39 257 elseif type(slug) ~= "string" then
andrewtknoll@39 258 error("Usage: DBGroup:EnableSlashCommand(slug, commandList[, handler]): 'slug' must be a string.", 2);
andrewtknoll@39 259 elseif type(commandList) ~= "string" and type(commandList) ~= "table" then
andrewtknoll@39 260 error("Usage: DBGroup:EnableSlashCommand(slug, commandList[, handler]): 'commandList' must be a string or table.", 2);
andrewtknoll@39 261 elseif handler and type(handler) ~= "function" then
andrewtknoll@39 262 error("Usage: DBGroup:EnableSlashCommand(slug, commandList[, handler]): 'handler' must be nil or a function.", 2);
andrewtknoll@39 263 elseif type(commandList) == "table" then
andrewtknoll@39 264 for i = 1, #commandList do
andrewtknoll@39 265 if type(commandList[i]) ~= "string" then
andrewtknoll@39 266 error("Usage: DBGroup:EnableSlashCommand(slug, commandList[, handler]): 'commandList' must contain only strings.", 2);
andrewtknoll@39 267 end
andrewtknoll@39 268 end
andrewtknoll@39 269 end
andrewtknoll@39 270
andrewtknoll@39 271 self.slug = slug;
andrewtknoll@39 272 self.subCmdList = {};
andrewtknoll@39 273 if type(commandList) == "string" then
andrewtknoll@39 274 _G["SLASH_"..slug.."1"] = commandList;
andrewtknoll@39 275 else
andrewtknoll@39 276 for i = 1, #commandList do
andrewtknoll@39 277 _G["SLASH_"..slug..i] = commandList[i];
andrewtknoll@39 278 end
andrewtknoll@39 279 end
andrewtknoll@39 280
andrewtknoll@40 281 if handler then
andrewtknoll@40 282 SlashCmdList[slug] = handler;
andrewtknoll@40 283 else
andrewtknoll@40 284 SlashCmdList[slug] = function(msg, editBox)
andrewtknoll@40 285 for cmd, func in pairs(self.subCmdList) do
andrewtknoll@40 286 if msg == cmd then
andrewtknoll@40 287 func("", editBox);
andrewtknoll@39 288 return;
andrewtknoll@40 289 elseif msg:len() > cmd:len() then
andrewtknoll@40 290 if msg:sub(1, cmd:len() + 1) == (cmd.." ") then
andrewtknoll@40 291 func(msg:sub(cmd:len() + 2), editBox);
andrewtknoll@40 292 return;
andrewtknoll@40 293 end
andrewtknoll@39 294 end
andrewtknoll@39 295 end
andrewtknoll@39 296
andrewtknoll@40 297 for k, button in pairs(InterfaceOptionsFrameAddOns.buttons) do
andrewtknoll@46 298 if button.element and button.element.name == self.name and button.element.collapsed then
andrewtknoll@40 299 OptionsListButtonToggle_OnClick(button.toggle);
andrewtknoll@40 300 break;
andrewtknoll@40 301 end
andrewtknoll@39 302 end
andrewtknoll@40 303 InterfaceOptionsFrame_OpenToCategory(self.name);
andrewtknoll@40 304 end;
andrewtknoll@40 305 end
andrewtknoll@39 306 end
andrewtknoll@39 307
andrewtknoll@40 308 --- Checks to see if this group has a slash command.
andrewtknoll@44 309 -- @return ##true## if this group has a slash command, ##false## otherwise (boolean)
andrewtknoll@40 310 function DBGroup:HasSlashCommand()
andrewtknoll@40 311 if self.slug then
andrewtknoll@40 312 return true;
andrewtknoll@40 313 else
andrewtknoll@40 314 return false;
andrewtknoll@40 315 end
andrewtknoll@40 316 end
andrewtknoll@40 317
andrewtknoll@40 318 --- Adds an alias for the slash command.
andrewtknoll@40 319 -- @param alias The alternate name for the slash command. (string)
andrewtknoll@39 320 function DBGroup:AddSlashCommandAlias(alias)
andrewtknoll@39 321 if type(alias) ~= "string" then
andrewtknoll@39 322 error("Usage: DBGroup:AddSlashCommandAlias(alias): 'alias' must be a string.", 2);
andrewtknoll@39 323 elseif not self.slug then
andrewtknoll@39 324 error("Usage: DBGroup:AddSlashCommandAlias(alias): slash commands for this group have not be enabled.", 2);
andrewtknoll@39 325 end
andrewtknoll@39 326
andrewtknoll@39 327 local i = 1;
andrewtknoll@39 328 while _G["SLASH_"..self.slug..i] do
andrewtknoll@39 329 i = i + 1;
andrewtknoll@39 330 end
andrewtknoll@39 331
andrewtknoll@39 332 _G["SLASH_"..self.slug..i] = alias;
andrewtknoll@39 333 end
andrewtknoll@39 334
andrewtknoll@39 335 --- Adds a secondary command handler to the slash command for this group.
andrewtknoll@40 336 -- This handler will be called if the argument to the slash command matches the name provided.
andrewtknoll@42 337 -- @paramsig name, handler[, silent]
andrewtknoll@40 338 -- @param name The name of the secondary command. (string)
andrewtknoll@40 339 -- @param handler The function to handle the command. (function)
andrewtknoll@42 340 -- @param silent ##True## if you want to replace the currently registered command, ##false##
andrewtknoll@40 341 -- otherwise. (boolean)
andrewtknoll@42 342 function DBGroup:AddSecondaryCommand(name, handler, silent)
andrewtknoll@39 343 if type(name) ~= "string" then
andrewtknoll@40 344 error("Usage: DBGroup:AddSecondaryCommand(name, handler[, overwrite]): 'name' must be a string.", 2);
andrewtknoll@42 345 elseif type(handler) ~= "function" then
andrewtknoll@40 346 error("Usage: DBGroup:AddSecondaryCommand(name, handler[, overwrite]): 'handler' must be a function.", 2);
andrewtknoll@42 347 elseif not self.slug then
andrewtknoll@40 348 error("Usage: DBGroup:AddSecondaryCommand(name, handler[, overwrite]): slash commands for this group have not be enabled.", 2);
andrewtknoll@40 349 elseif type(overwrite) ~= "boolean" and type(overwrite) ~= "nil" then
andrewtknoll@40 350 error("Usage: DBGroup:AddSecondaryCommand(name, handler[, overwrite]): 'overwrite' must be a boolean or nil", 2);
andrewtknoll@39 351 end
andrewtknoll@42 352 if not silent then
andrewtknoll@40 353 for k, v in pairs(self.subCmdList) do
andrewtknoll@40 354 if k == name then
andrewtknoll@40 355 error("Usage: DBGroup:AddSecondaryCommand(name, handler[, overwrite]): command '"..name.."' already exists.", 2);
andrewtknoll@40 356 end
andrewtknoll@39 357 end
andrewtknoll@39 358 end
andrewtknoll@40 359
andrewtknoll@39 360 self.subCmdList[name] = handler;
andrewtknoll@39 361 end
andrewtknoll@39 362
andrewtknoll@44 363 --- Returns the list of secondary commands registered with this group.
andrewtknoll@44 364 -- @return A table containing name-function pairs for secondary commands. (table)
andrewtknoll@44 365 function DBGroup:GetSecondaryCommands()
andrewtknoll@44 366 if not self.slug then
andrewtknoll@44 367 error("Usage: DBGroup:GetSecondaryCommands(): Slash commands for this group have not been enabled", 2);
andrewtknoll@44 368 end
andrewtknoll@44 369 return self.subCmdList;
andrewtknoll@44 370 end
andrewtknoll@44 371
andrewtknoll@19 372 -- callback handlers (new profiles are handled by OnProfileChanged)
andrewtknoll@19 373
andrewtknoll@24 374 function DBGroup:OnProfileChanged(callback, syncDB, profile)
andrewtknoll@24 375 if not self.squelchCallbacks then
andrewtknoll@24 376 for db, _ in pairs(self.members) do
andrewtknoll@25 377 db:SetProfile(profile);
andrewtknoll@24 378 end
andrewtknoll@24 379 end
andrewtknoll@18 380 end
andrewtknoll@18 381
andrewtknoll@24 382 function DBGroup:OnProfileDeleted(callback, syncDB, profile)
andrewtknoll@24 383 for db, _ in pairs(self.members) do
andrewtknoll@24 384 db:DeleteProfile(profile, true);
andrewtknoll@24 385 end
andrewtknoll@18 386 end
andrewtknoll@18 387
andrewtknoll@24 388 function DBGroup:OnProfileCopied(callback, syncDB, profile)
andrewtknoll@24 389 for db, _ in pairs(self.members) do
andrewtknoll@24 390 db:CopyProfile(profile, true);
andrewtknoll@24 391 end
andrewtknoll@18 392 end
andrewtknoll@18 393
andrewtknoll@24 394 function DBGroup:OnProfileReset(callback, syncDB)
andrewtknoll@24 395 for db, _ in pairs(self.members) do
andrewtknoll@24 396 db:ResetProfile(false, false);
andrewtknoll@24 397 end
andrewtknoll@18 398 end
andrewtknoll@23 399
andrewtknoll@42 400 -- shutdown handling
andrewtknoll@42 401
andrewtknoll@29 402 local altProfile = nil;
andrewtknoll@29 403 local dualSpecEnabled = nil;
andrewtknoll@29 404 local activeSpecGroup = nil;
andrewtknoll@28 405
andrewtknoll@28 406 function DBGroup:OnSyncShutdown(callback, syncDB)
andrewtknoll@29 407 if self.usesDualSpec and not altProfile then
andrewtknoll@29 408 altProfile = syncDB:GetDualSpecProfile();
andrewtknoll@29 409 dualSpecEnabled = syncDB:IsDualSpecEnabled();
andrewtknoll@29 410 activeSpecGroup = GetActiveSpecGroup();
andrewtknoll@28 411 end
andrewtknoll@28 412 end
andrewtknoll@28 413
andrewtknoll@24 414 local timestamp = nil;
andrewtknoll@24 415
andrewtknoll@28 416 function DBGroup:OnMemberShutdown(callback, db)
andrewtknoll@27 417 if not timestamp then -- ensure uniform timestamps to minimize
andrewtknoll@27 418 timestamp = time(); -- calls to SetProfile in NewGroup
andrewtknoll@24 419 end
andrewtknoll@41 420 db.char.logoutTimestamp = timestamp; -- namespace is registered for callback, not base db
andrewtknoll@29 421 if self.usesDualSpec then
andrewtknoll@29 422 if not altProfile then
andrewtknoll@29 423 altProfile = self.syncDB:GetDualSpecProfile();
andrewtknoll@29 424 dualSpecEnabled = self.syncDB:IsDualSpecEnabled();
andrewtknoll@29 425 activeSpecGroup = GetActiveSpecGroup();
andrewtknoll@29 426 end
andrewtknoll@41 427 db.char.altProfile = altProfile;
andrewtknoll@41 428 db.char.dualSpecEnabled = dualSpecEnabled;
andrewtknoll@41 429 db.char.activeSpecGroup = activeSpecGroup;
andrewtknoll@28 430 end
andrewtknoll@23 431 end
andrewtknoll@33 432
andrewtknoll@33 433 -- update existing groups
andrewtknoll@33 434 for groupName, group in pairs(LibModuleDBShare.groups) do
andrewtknoll@33 435 for funcName, func in pairs(DBGroup) do
andrewtknoll@33 436 group[funcName] = func;
andrewtknoll@33 437 end
andrewtknoll@33 438 end