diff --git a/HideCoA.lua b/HideCoA.lua index ebc86fb..54b07b8 100644 --- a/HideCoA.lua +++ b/HideCoA.lua @@ -32,9 +32,158 @@ HideCoA.FRAMES = { "CoAResourceBar", } +local function CreateDefaultClassSettings() + + local classSettings = {} + + for _, class in ipairs(HideCoA.CUSTOM_CLASSES) do + classSettings[class] = {} + for _, frameName in ipairs(HideCoA.FRAMES) do + classSettings[class][frameName] = true + end + end + + return classSettings + +end + +local function EnsureClassSettingsComplete(classSettings) + + for _, class in ipairs(HideCoA.CUSTOM_CLASSES) do + + if type(classSettings[class]) ~= "table" then + classSettings[class] = {} + end + + for _, frameName in ipairs(HideCoA.FRAMES) do + if classSettings[class][frameName] == nil then + classSettings[class][frameName] = true + end + end + + end + +end + +local function GetCharacterKey() + return UnitName("player") .. " - " .. GetRealmName() +end + +HideCoA.GetCharacterKey = GetCharacterKey + +local function GetActiveProfileName() + + local charKey = GetCharacterKey() + local assigned = HideCoADB.charProfile and HideCoADB.charProfile[charKey] + + if assigned and HideCoADB.profiles[assigned] then + return assigned + end + + return charKey + +end + +HideCoA.GetActiveProfileName = GetActiveProfileName + +local function SetActiveProfileName(name) + HideCoADB.charProfile[GetCharacterKey()] = name +end + +HideCoA.SetActiveProfileName = SetActiveProfileName + +local function GetActiveClassSettings() + + local name = GetActiveProfileName() + local profile = HideCoADB.profiles[name] + + if not profile then + profile = { classSettings = CreateDefaultClassSettings() } + HideCoADB.profiles[name] = profile + end + + if not profile.classSettings then + profile.classSettings = CreateDefaultClassSettings() + end + + return profile.classSettings + +end + +HideCoA.GetActiveClassSettings = GetActiveClassSettings + +local function CopyProfile(sourceName, destName) + + local source = HideCoADB.profiles[sourceName] + + if not source or not source.classSettings then + return + end + + local copy = {} + + for class, settings in pairs(source.classSettings) do + copy[class] = {} + for frameName, value in pairs(settings) do + copy[class][frameName] = value + end + end + + if not HideCoADB.profiles[destName] then + HideCoADB.profiles[destName] = {} + end + + HideCoADB.profiles[destName].classSettings = copy + + HideCoA.ApplySetting() + +end + +HideCoA.CopyProfile = CopyProfile + +local function ResetProfile() + + local name = GetActiveProfileName() + + if not HideCoADB.profiles[name] then + HideCoADB.profiles[name] = {} + end + + HideCoADB.profiles[name].classSettings = CreateDefaultClassSettings() + + HideCoA.ApplySetting() + +end + +HideCoA.ResetProfile = ResetProfile + +local function DeleteProfile(name) + + if name == "Default" then + return + end + + local wasActive = (name == GetActiveProfileName()) + + HideCoADB.profiles[name] = nil + + for charKey, assigned in pairs(HideCoADB.charProfile) do + if assigned == name then + HideCoADB.charProfile[charKey] = nil + end + end + + if wasActive then + HideCoADB.charProfile[GetCharacterKey()] = "Default" + end + +end + +HideCoA.DeleteProfile = DeleteProfile + local function ShouldHideForClass(playerClass, frameName) - local classSettings = HideCoADB.classSettings[playerClass] + local classSettings = GetActiveClassSettings()[playerClass] if not classSettings or classSettings[frameName] == nil then return true @@ -107,46 +256,60 @@ f:SetScript("OnEvent", function(self, event, arg1) HideCoADB = {} end - if not HideCoADB.classSettings then - HideCoADB.classSettings = {} - end - - for _, class in ipairs(HideCoA.CUSTOM_CLASSES) do - - if type(HideCoADB.classSettings[class]) ~= "table" then - HideCoADB.classSettings[class] = {} - end - - for _, frameName in ipairs(HideCoA.FRAMES) do - if HideCoADB.classSettings[class][frameName] == nil then - HideCoADB.classSettings[class][frameName] = true - end - end - - end - if not HideCoADB.profiles then HideCoADB.profiles = {} end + if not HideCoADB.charProfile then + HideCoADB.charProfile = {} + end + + -- Legacy pre-profile saved variables stored a single flat classSettings + -- table shared by every character. Fold it into "Default" so nobody's + -- existing hide/show choices vanish when profiles were introduced. + if HideCoADB.classSettings and not HideCoADB.profiles["Default"] then + HideCoADB.profiles["Default"] = { classSettings = HideCoADB.classSettings } + end + + HideCoADB.classSettings = nil + if not HideCoADB.profiles["Default"] then - HideCoADB.profiles["Default"] = {} + HideCoADB.profiles["Default"] = { classSettings = CreateDefaultClassSettings() } end - local realmCharProfile = GetRealmName() .. " - " .. UnitName("player") + local charKey = GetCharacterKey() - if not HideCoADB.profiles[realmCharProfile] then - HideCoADB.profiles[realmCharProfile] = {} + -- The profile-name syntax used to be "realm - character"; rename any + -- existing profile created under that scheme to the new ordering + -- instead of leaving it orphaned in the list. + local oldCharKey = GetRealmName() .. " - " .. UnitName("player") + + if HideCoADB.profiles[oldCharKey] and not HideCoADB.profiles[charKey] then + HideCoADB.profiles[charKey] = HideCoADB.profiles[oldCharKey] + HideCoADB.profiles[oldCharKey] = nil end - if not HideCoADB.selectedProfile then - HideCoADB.selectedProfile = "Default" + if not HideCoADB.profiles[charKey] then + HideCoADB.profiles[charKey] = { classSettings = CreateDefaultClassSettings() } end + for _, profile in pairs(HideCoADB.profiles) do + if not profile.classSettings then + profile.classSettings = CreateDefaultClassSettings() + end + EnsureClassSettingsComplete(profile.classSettings) + end + + if not HideCoADB.charProfile[charKey] then + HideCoADB.charProfile[charKey] = charKey + end + + HideCoADB.selectedProfile = nil + elseif event == "PLAYER_LOGIN" then ApplySetting() end -end) \ No newline at end of file +end) diff --git a/Options.lua b/Options.lua index 691c7ca..92ff84a 100644 --- a/Options.lua +++ b/Options.lua @@ -59,7 +59,7 @@ for _, frameName in ipairs(HideCoA.FRAMES) do return end - HideCoADB.classSettings[selectedClass][self.frameName] = self:GetChecked() and true or false + HideCoA.GetActiveClassSettings()[selectedClass][self.frameName] = self:GetChecked() and true or false HideCoA.ApplySetting() end) @@ -94,7 +94,7 @@ local function SelectClass(class) end for _, frameName in ipairs(HideCoA.FRAMES) do - checks[frameName]:SetChecked(HideCoADB.classSettings[class][frameName]) + checks[frameName]:SetChecked(HideCoA.GetActiveClassSettings()[class][frameName]) end for tabClass, button in pairs(tabButtons) do @@ -147,22 +147,28 @@ profileContent:Hide() local profileTitle = profileContent:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") profileTitle:SetPoint("TOPLEFT", profileContent, "TOPLEFT", 0, 0) profileTitle:SetFont(titleFont, titleSize + 4, "OUTLINE") -profileTitle:SetText("Profile") +profileTitle:SetText("Profiles") local function GetProfileNames() local names = {} + local hasDefault = false if HideCoADB and HideCoADB.profiles then for name in pairs(HideCoADB.profiles) do - if name ~= "Default" then + if name == "Default" then + hasDefault = true + else table.insert(names, name) end end end table.sort(names) - table.insert(names, 1, "Default") + + if hasDefault then + table.insert(names, 1, "Default") + end return names @@ -171,9 +177,14 @@ end local profileDropDown = CreateFrame("Frame", "HideCoAProfileDropDown", profileContent, "UIDropDownMenuTemplate") profileDropDown:SetPoint("TOPLEFT", profileTitle, "BOTTOMLEFT", -16, -12) +if ElvSkins then + ElvSkins:HandleDropDownBox(profileDropDown, 140) +end + local function ProfileDropDown_OnClick(self) - HideCoADB.selectedProfile = self.value + HideCoA.SetActiveProfileName(self.value) UIDropDownMenu_SetText(profileDropDown, self.value) + HideCoA.ApplySetting() end UIDropDownMenu_Initialize(profileDropDown, function(self, level) @@ -184,7 +195,7 @@ UIDropDownMenu_Initialize(profileDropDown, function(self, level) info.text = name info.value = name info.func = ProfileDropDown_OnClick - info.checked = HideCoADB and (HideCoADB.selectedProfile == name) + info.checked = HideCoADB and HideCoADB.charProfile and (HideCoA.GetActiveProfileName() == name) UIDropDownMenu_AddButton(info, level) @@ -194,6 +205,170 @@ end) UIDropDownMenu_SetWidth(profileDropDown, 140) +local resetDesc = profileContent:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") +resetDesc:SetPoint("TOPLEFT", profileDropDown, "BOTTOMLEFT", 16, -20) +resetDesc:SetWidth(260) +resetDesc:SetJustifyH("LEFT") +resetDesc:SetText("Reset the currently active profile's settings back to their defaults.") + +local resetButton = CreateFrame("Button", "HideCoAResetProfileButton", profileContent, "UIPanelButtonTemplate") +resetButton:SetPoint("TOPLEFT", resetDesc, "BOTTOMLEFT", 0, -8) +resetButton:SetSize(140, 22) +resetButton:SetText("Reset Profile") + +if ElvSkins then + ElvSkins:HandleButton(resetButton) +end + +StaticPopupDialogs["HIDECOA_CONFIRM_RESET_PROFILE"] = { + text = "Reset the active profile '%s' to its default settings? This cannot be undone.", + button1 = YES, + button2 = NO, + OnAccept = function() + HideCoA.ResetProfile() + if selectedClass then + SelectClass(selectedClass) + end + end, + timeout = 0, + whileDead = true, + hideOnEscape = true, + preferredIndex = 3, +} + +resetButton:SetScript("OnClick", function() + StaticPopup_Show("HIDECOA_CONFIRM_RESET_PROFILE", HideCoA.GetActiveProfileName()) +end) + +local copyDesc = profileContent:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") +copyDesc:SetPoint("TOPLEFT", resetButton, "BOTTOMLEFT", 0, -20) +copyDesc:SetWidth(260) +copyDesc:SetJustifyH("LEFT") +copyDesc:SetText("Copy the settings from one existing profile into the currently active profile.") + +local copyLabel = profileContent:CreateFontString(nil, "ARTWORK", "GameFontNormal") +copyLabel:SetPoint("TOPLEFT", copyDesc, "BOTTOMLEFT", 0, -8) +copyLabel:SetTextColor(1, 0.82, 0) +copyLabel:SetText("Copy From") + +local copyDropDown = CreateFrame("Frame", "HideCoACopyProfileDropDown", profileContent, "UIDropDownMenuTemplate") +copyDropDown:SetPoint("TOPLEFT", copyLabel, "BOTTOMLEFT", -16, -4) + +if ElvSkins then + ElvSkins:HandleDropDownBox(copyDropDown, 140) +end + +StaticPopupDialogs["HIDECOA_CONFIRM_COPY_PROFILE"] = { + text = "Copy settings from '%s' into the active profile '%s'? This will overwrite the active profile's settings.", + button1 = YES, + button2 = NO, + OnAccept = function(self, data) + HideCoA.CopyProfile(data.sourceName, data.activeName) + UIDropDownMenu_SetText(copyDropDown, "") + if selectedClass then + SelectClass(selectedClass) + end + end, + timeout = 0, + whileDead = true, + hideOnEscape = true, + preferredIndex = 3, +} + +local function CopyProfile_OnClick(self) + + local sourceName = self.value + local activeName = HideCoA.GetActiveProfileName() + + StaticPopup_Show("HIDECOA_CONFIRM_COPY_PROFILE", sourceName, activeName, + { sourceName = sourceName, activeName = activeName }) + +end + +UIDropDownMenu_Initialize(copyDropDown, function(self, level) + + local activeName = HideCoADB and HideCoA.GetActiveProfileName() + + for _, name in ipairs(GetProfileNames()) do + if name ~= activeName then + + local info = UIDropDownMenu_CreateInfo() + info.text = name + info.value = name + info.func = CopyProfile_OnClick + + UIDropDownMenu_AddButton(info, level) + + end + end + +end) + +UIDropDownMenu_SetWidth(copyDropDown, 140) +UIDropDownMenu_SetText(copyDropDown, "") + +local deleteDesc = profileContent:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall") +deleteDesc:SetPoint("TOPLEFT", copyDropDown, "BOTTOMLEFT", 16, -20) +deleteDesc:SetWidth(260) +deleteDesc:SetJustifyH("LEFT") +deleteDesc:SetText("Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.") + +local deleteLabel = profileContent:CreateFontString(nil, "ARTWORK", "GameFontNormal") +deleteLabel:SetPoint("TOPLEFT", deleteDesc, "BOTTOMLEFT", 0, -8) +deleteLabel:SetTextColor(1, 0.82, 0) +deleteLabel:SetText("Delete a Profile") + +local deleteDropDown = CreateFrame("Frame", "HideCoADeleteProfileDropDown", profileContent, "UIDropDownMenuTemplate") +deleteDropDown:SetPoint("TOPLEFT", deleteLabel, "BOTTOMLEFT", -16, -4) + +if ElvSkins then + ElvSkins:HandleDropDownBox(deleteDropDown, 140) +end + +StaticPopupDialogs["HIDECOA_CONFIRM_DELETE_PROFILE"] = { + text = "Delete profile '%s'? This cannot be undone.", + button1 = YES, + button2 = NO, + OnAccept = function(self, data) + HideCoA.DeleteProfile(data.targetName) + UIDropDownMenu_SetText(deleteDropDown, "") + UIDropDownMenu_SetText(profileDropDown, HideCoA.GetActiveProfileName()) + HideCoA.ApplySetting() + end, + timeout = 0, + whileDead = true, + hideOnEscape = true, + preferredIndex = 3, +} + +local function DeleteProfile_OnClick(self) + + local targetName = self.value + + StaticPopup_Show("HIDECOA_CONFIRM_DELETE_PROFILE", targetName, nil, { targetName = targetName }) + +end + +UIDropDownMenu_Initialize(deleteDropDown, function(self, level) + + for _, name in ipairs(GetProfileNames()) do + if name ~= "Default" then + + local info = UIDropDownMenu_CreateInfo() + info.text = name + info.value = name + info.func = DeleteProfile_OnClick + + UIDropDownMenu_AddButton(info, level) + + end + end + +end) + +UIDropDownMenu_SetWidth(deleteDropDown, 140) +UIDropDownMenu_SetText(deleteDropDown, "") + local divider = sidebar:CreateTexture(nil, "ARTWORK") divider:SetHeight(1) divider:SetTexture(1, 1, 1, 0.3) @@ -216,7 +391,7 @@ profileTabButton:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighli local profileTabText = profileTabButton:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") profileTabText:SetPoint("LEFT", 4, 0) -profileTabText:SetText("Profile") +profileTabText:SetText("Profiles") local function SelectProfileTab() @@ -229,7 +404,7 @@ local function SelectProfileTab() profileTabButton.selectedTexture:Show() - UIDropDownMenu_SetText(profileDropDown, HideCoADB.selectedProfile or "Default") + UIDropDownMenu_SetText(profileDropDown, HideCoA.GetActiveProfileName()) end