Quantcast

Add options panel, spec-based profile swaps and profile support

James Whitehead II [10-10-10 - 17:04]
Add options panel, spec-based profile swaps and profile support
Filename
Clique.lua
Clique.toc
FrameOptionsPanel.lua
OptionsPanel.lua
diff --git a/Clique.lua b/Clique.lua
index 1b79704..8727545 100755
--- a/Clique.lua
+++ b/Clique.lua
@@ -107,12 +107,15 @@ function addon:Initialize()
     end
     self:EnableBlizzardFrames()

-    -- Update GLOBAL attributes
-    self:UpdateGlobalAttributes()
+    -- Trigger a profile change, updating all attributes
+    self:ChangeProfile()

     -- Register for combat events to ensure we can swap between the two states
     self:RegisterEvent("PLAYER_REGEN_DISABLED", "UpdateAttributes")
     self:RegisterEvent("PLAYER_REGEN_ENABLED", "UpdateAttributes")
+    self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", function()
+        self:ChangeProfile()
+    end)
 end

 function addon:RegisterFrame(button)
@@ -167,7 +170,9 @@ function addon:InitializeDatabase()
     local db = CliqueDB2
     local realmKey = GetRealmName()
     local charKey = UnitName("player") .. " - " .. realmKey
+    addon.staticProfileKey = charKey

+    addon.db = db
     if not db.settings[charKey] then
         db.settings[charKey] = {
             profileKey = charKey,
@@ -437,6 +442,38 @@ function addon:UpdateGlobalAttributes()
     globutton:Execute(globutton.setbinds)
 end

+function addon:ChangeProfile(profileName)
+    -- Clear the current profile
+    addon:ClearAttributes()
+    addon:ClearGlobalAttributes()
+
+    -- Check to see if this is a force-create of a new profile
+    if type(profileName) == "string" and #profileName > 0 then
+        -- Do nothing
+    else
+        -- Determine which profile to set, based on talent group
+        self.talentGroup = GetActiveTalentGroup()
+        if self.talentGroup == 1 and self.settings.pri_profileKey then
+            profileName = self.settings.pri_profileKey
+        elseif self.talentGroup == 2 and self.settings.sec_profileKey then
+            profileName = self.settings.sec_profileKey
+        end
+
+        if type(profileName) == "string" and addon.db.bindings[profileName] then
+            -- Do nothing
+        else
+            profileName = addon.staticProfileKey
+        end
+    end
+
+    -- We've been given a profile name, so just change to it
+    addon.settings.profileKey = profileName
+    addon:InitializeBindingProfile()
+    addon:UpdateAttributes()
+    addon:UpdateGlobalAttributes()
+    addon:UpdateOptionsPanel()
+end
+
 SLASH_CLIQUE1 = "/clique"
 SlashCmdList["CLIQUE"] = function(msg, editbox)
     ShowUIPanel(CliqueConfig)
diff --git a/Clique.toc b/Clique.toc
index e2905e5..42ffad7 100755
--- a/Clique.toc
+++ b/Clique.toc
@@ -14,8 +14,11 @@ Clique.xml

 Clique.lua
 Utils.lua
+
 BindConfig.lua
+
 OptionsPanel.lua
+FrameOptionsPanel.lua

 HeaderTest.xml
 HeaderTest.lua
diff --git a/FrameOptionsPanel.lua b/FrameOptionsPanel.lua
new file mode 100644
index 0000000..678ee5d
--- /dev/null
+++ b/FrameOptionsPanel.lua
@@ -0,0 +1,17 @@
+local addonName, addon = ...
+
+local panel = CreateFrame("Frame")
+panel.name = "Frame Editor"
+panel.parent = addonName
+
+panel:SetScript("OnShow", function(self)
+    if not panel.initialized then
+        panel:CreateOptions()
+    end
+end)
+
+function panel:CreateOptions()
+end
+
+InterfaceOptions_AddCategory(panel)
+
diff --git a/OptionsPanel.lua b/OptionsPanel.lua
index 27f067b..f596a6a 100644
--- a/OptionsPanel.lua
+++ b/OptionsPanel.lua
@@ -1,7 +1,8 @@
 local addonName, addon = ...
+local L = addon.L

 local panel = CreateFrame("Frame")
-panel.name = "Clique"
+panel.name = addonName

 panel:SetScript("OnShow", function(self)
     if not panel.initialized then
@@ -9,7 +10,367 @@ panel:SetScript("OnShow", function(self)
     end
 end)

+local function make_checkbox(name, parent)
+    local frame = CreateFrame("CheckButton", name, parent, "UICheckButtonTemplate")
+    frame.text = _G[frame:GetName() .. "Text"]
+    frame.type = "checkbox"
+    return frame
+end
+
+local function make_dropdown(name, parent)
+    local frame = CreateFrame("Frame", name, parent, "UIDropDownMenuTemplate")
+    frame:SetClampedToScreen(true)
+    frame.type = "dropdown"
+    return frame
+end
+
+local function make_label(name, parent, template)
+    local label = parent:CreateFontString("OVERLAY", name, template)
+    label:SetWidth(parent:GetWidth())
+    label:SetJustifyH("LEFT")
+    label.type = "label"
+    return label
+end
+
 function panel:CreateOptions()
+    -- Ensure the panel isn't created twice (thanks haste)
+    panel.initialized = true
+
+    -- Create the general options panel here:
+    local bits = {}
+
+    self.updown = make_checkbox("CliqueOptionsUpDownClick", self)
+    self.updown.text:SetText(L["Trigger bindings on the 'down' portion of the click (requires reload)"])
+
+    self.specswap = make_checkbox("CliqueOptionsSpecSwap", self)
+    self.specswap.text:SetText(L["Swap profiles based on talent spec"])
+    self.specswap.EnableDisable = function()
+        if self.specswap:GetChecked() then
+            UIDropDownMenu_EnableDropDown(panel.prispec)
+            UIDropDownMenu_EnableDropDown(panel.secspec)
+        else
+            UIDropDownMenu_DisableDropDown(panel.prispec)
+            UIDropDownMenu_DisableDropDown(panel.secspec)
+        end
+    end
+    self.specswap:SetScript("PostClick", self.specswap.EnableDisable)
+
+    self.prispeclabel = make_label("CliqueOptionsPriSpecLabel", self, "GameFontNormalSmall")
+    self.prispeclabel:SetText(L["Primary talent spec profile:"])
+    self.prispec = make_dropdown("CliqueOptionsPriSpec", self)
+    UIDropDownMenu_SetWidth(self.prispec, 150)
+    BlizzardOptionsPanel_SetupDependentControl(self.specswap, self.prispec)
+
+    self.secspeclabel = make_label("CliqueOptionsSecSpecLabel", self, "GameFontNormalSmall")
+    self.secspeclabel:SetText(L["Secondary talent spec profile:"])
+    self.secspec = make_dropdown("CliqueOptionsSecSpec", self)
+    UIDropDownMenu_SetWidth(self.secspec, 150)
+    BlizzardOptionsPanel_SetupDependentControl(self.specswap, self.secspec)
+
+    self.profilelabel = make_label("CliqueOptionsProfileMgmtLabel", self, "GameFontNormalSmall")
+    self.profilelabel:SetText(L["Profile Management:"])
+    self.profiledd = make_dropdown("CliqueOptionsProfileMgmt", self)
+    UIDropDownMenu_SetWidth(self.profiledd, 150)
+
+    -- Collect and anchor the bits together
+    table.insert(bits, self.intro)
+    table.insert(bits, self.updown)
+    table.insert(bits, self.specswap)
+    table.insert(bits, self.prispeclabel)
+    table.insert(bits, self.prispec)
+    table.insert(bits, self.secspeclabel)
+    table.insert(bits, self.secspec)
+    table.insert(bits, self.profilelabel)
+    table.insert(bits, self.profiledd)
+
+    bits[1]:SetPoint("TOPLEFT", 5, -5)
+
+    for i = 2, #bits, 1 do
+        if bits[i].type == "label" then
+            bits[i]:SetPoint("TOPLEFT", bits[i-1], "BOTTOMLEFT", 5, -5)
+        elseif bits[i].type == "dropdown" then
+            bits[i]:SetPoint("TOPLEFT", bits[i-1], "BOTTOMLEFT", -5, -5)
+        else
+            bits[i]:SetPoint("TOPLEFT", bits[i-1], "BOTTOMLEFT", 0, -5)
+        end
+    end
+
+    -- Trigger bindings on 'down' clicks instead of 'up' clicks
+    -- Automatically switch profile based on spec
+    --   Dropdown to select primary profile
+    --   Dropdown to select secondary profile
+    -- Profile managerment
+    --   * set profile
+    --   * delete profile
+    --   * add profile
+end
+
+StaticPopupDialogs["CLIQUE_CONFIRM_PROFILE_DELETE"] = {
+    button1 = YES,
+    button2 = NO,
+    hideOnEscape = 1,
+    timeout = 0,
+    whileDead = 1,
+}
+
+StaticPopupDialogs["CLIQUE_NEW_PROFILE"] = {
+	text = TEXT("Enter the name of a new profile you'd like to create"),
+	button1 = TEXT(OKAY),
+	button2 = TEXT(CANCEL),
+	OnAccept = function(self)
+		local base = self:GetName()
+		local editbox = getglobal(base .. "EditBox")
+        local profileName = editbox:GetText()
+        addon:ChangeProfile(profileName)
+	end,
+	timeout = 0,
+	whileDead = 1,
+	exclusive = 1,
+	showAlert = 1,
+	hideOnEscape = 1,
+	hasEditBox = 1,
+	maxLetters = 32,
+	OnShow = function(self)
+		getglobal(self:GetName().."Button1"):Disable();
+		getglobal(self:GetName().."EditBox"):SetFocus();
+	end,
+	EditBoxOnEnterPressed = function(self)
+		if ( getglobal(self:GetParent():GetName().."Button1"):IsEnabled() == 1 ) then
+            local base = self:GetParent():GetName()
+            local editbox = _G[base .. "EditBox"]
+            local profileName = editbox:GetText()
+            addon:ChangeProfile(profileName)
+        end
+        self:GetParent():Hide();
+	end,
+	EditBoxOnTextChanged = function (self)
+		local editBox = getglobal(self:GetParent():GetName().."EditBox");
+		local txt = editBox:GetText()
+		if #txt > 0 then
+			getglobal(self:GetParent():GetName().."Button1"):Enable();
+		else
+			getglobal(self:GetParent():GetName().."Button1"):Disable();
+		end
+	end,
+	EditBoxOnEscapePressed = function(self)
+		self:GetParent():Hide();
+		ClearCursor();
+	end
+}
+
+local function getsorttbl()
+    local sort = {}
+    for k, v in pairs(addon.db.bindings) do
+        table.insert(sort, k)
+    end
+    table.sort(sort)
+    return sort
+end
+
+local function spec_initialize(dropdown, level)
+    local sort = getsorttbl()
+    local paged = (#sort >= 15)
+
+    if not level or level == 1 then
+        if not paged then
+            -- Display the profiles un-paged
+            for idx, entry in ipairs(sort) do
+                local info = UIDropDownMenu_CreateInfo()
+                info.text = entry
+                info.value = entry
+                info.func = function(frame, ...)
+                    UIDropDownMenu_SetSelectedValue(dropdown, entry)
+                end
+                UIDropDownMenu_AddButton(info, level)
+            end
+        else
+            -- Page the results into sub-menus
+            for idx = 1, #sort, 10 do
+                -- Make the submenus for each group
+                local lastidx = (idx + 9 > #sort) and #sort or (idx + 9)
+                local info = UIDropDownMenu_CreateInfo()
+                local first = sort[idx]
+                local last = sort[lastidx]
+                info.text = first:sub(1, 5):trim() .. ".." .. last:sub(1, 5):trim()
+                info.value = idx
+                info.hasArrow = true
+                info.notCheckable = true
+                UIDropDownMenu_AddButton(info, level)
+            end
+        end
+    elseif level == 2 then
+        -- Generate the appropriate submenus depending on need
+        if paged then
+            -- Generate the frame submenu
+            local startIdx = UIDROPDOWNMENU_MENU_VALUE
+            local lastIdx = (startIdx + 9 > #sort) and #sort or (startIdx + 9)
+            for idx = startIdx, lastIdx do
+                local info = UIDropDownMenu_CreateInfo()
+                info.text = sort[idx]
+                info.value = sort[idx]
+                info.func = function(frame, ...)
+                    UIDropDownMenu_SetSelectedValue(dropdown, sort[idx])
+                end
+                UIDropDownMenu_AddButton(info, level)
+            end
+        end
+    end
+end
+
+local function mgmt_initialize(dropdown, level)
+    local sort = getsorttbl()
+    local paged = (#sort >= 15)
+
+    if not level or level == 1 then
+        if not paged then
+            -- Display the profiles un-paged
+            for idx, entry in ipairs(sort) do
+                local info = UIDropDownMenu_CreateInfo()
+                info.text = entry
+                info.value = entry
+                info.notCheckable = true
+                info.hasArrow = true
+                UIDropDownMenu_AddButton(info, level)
+            end
+        else
+            -- Page the results into sub-menus
+            for idx = 1, #sort, 10 do
+                -- Make the submenus for each group
+                local lastidx = (idx + 9 > #sort) and #sort or (idx + 9)
+                local info = UIDropDownMenu_CreateInfo()
+                local first = sort[idx]
+                local last = sort[lastidx]
+                info.text = first:sub(1, 5):trim() .. ".." .. last:sub(1, 5):trim()
+                info.value = idx
+                info.notCheckable = true
+                info.hasArrow = true
+                UIDropDownMenu_AddButton(info, level)
+            end
+        end
+
+        -- Create the 'Add profile' option regardless
+        local info = UIDropDownMenu_CreateInfo()
+        info.text = L["Add new profile"]
+        info.value = "add"
+        info.notCheckable = true
+        info.func = function()
+            HideDropDownMenu(1)
+            StaticPopup_Show("CLIQUE_NEW_PROFILE")
+        end
+        UIDropDownMenu_AddButton(info, level)
+    elseif level == 2 then
+        -- Generate the appropriate submenus depending on need
+        if paged then
+            -- Generate the frame submenu
+            local startIdx = UIDROPDOWNMENU_MENU_VALUE
+            local lastIdx = (startIdx + 9 > #sort) and #sort or (startIdx + 9)
+            for idx = startIdx, lastIdx do
+                local info = UIDropDownMenu_CreateInfo()
+                info.text = sort[idx]
+                info.value = sort[idx]
+                info.hasArrow = true
+                info.notCheckable = true
+                UIDropDownMenu_AddButton(info, level)
+            end
+        else
+            local info = UIDropDownMenu_CreateInfo()
+            info.text = L["Select profile: %s"]:format(UIDROPDOWNMENU_MENU_VALUE)
+            info.value = sort[UIDROPDOWNMENU_MENU_VALUE]
+            info.notCheckable = true
+            info.disabled = addon.settings.specswap
+            info.func = function(frame)
+                UIDropDownMenu_SetSelectedValue(dropdown, UIDROPDOWNMENU_MENU_VALUE)
+                UIDropDownMenu_SetText(dropdown, UIDROPDOWNMENU_MENU_VALUE)
+                addon:ChangeProfile(UIDROPDOWNMENU_MENU_VALUE)
+            end
+            UIDropDownMenu_AddButton(info, level)
+
+            info = UIDropDownMenu_CreateInfo()
+            info.text = L["Delete profile: %s"]:format(UIDROPDOWNMENU_MENU_VALUE)
+            info.disabled = UIDROPDOWNMENU_MENU_VALUE == addon.settings.profileKey
+            info.value = sort[UIDROPDOWNMENU_MENU_VALUE]
+            info.notCheckable = true
+            info.func = function(frame)
+                local dialog = StaticPopupDialogs["CLIQUE_CONFIRM_PROFILE_DELETE"]
+                dialog.text = L["Delete profile '%s'"]:format(UIDROPDOWNMENU_MENU_VALUE)
+                dialog.OnAccept = function(self)
+                    addon.db.bindings[UIDROPDOWNMENU_MENU_VALUE] = nil
+                end
+                HideDropDownMenu(1)
+                StaticPopup_Show("CLIQUE_CONFIRM_PROFILE_DELETE")
+            end
+            UIDropDownMenu_AddButton(info, level)
+        end
+    elseif level == 3 then
+        local info = UIDropDownMenu_CreateInfo()
+        info.text = L["Select profile: %s"]:format(UIDROPDOWNMENU_MENU_VALUE)
+        info.value = sort[UIDROPDOWNMENU_MENU_VALUE]
+        info.disabled = addon.settings.specswap
+        info.func = function(frame)
+            UIDropDownMenu_SetSelectedValue(dropdown, UIDROPDOWNMENU_MENU_VALUE)
+            UIDropDownMenu_SetText(dropdown, UIDROPDOWNMENU_MENU_VALUE)
+            addon:ChangeProfile(UIDROPDOWNMENU_MENU_VALUE)
+        end
+        UIDropDownMenu_AddButton(info, level)
+
+        info = UIDropDownMenu_CreateInfo()
+        info.text = L["Delete profile: %s"]:format(UIDROPDOWNMENU_MENU_VALUE)
+        info.disabled = UIDROPDOWNMENU_MENU_VALUE == addon.settings.profileKey
+        info.value = sort[UIDROPDOWNMENU_MENU_VALUE]
+        info.func = function(frame)
+            local dialog = StaticPopupDialogs["CLIQUE_CONFIRM_PROFILE_DELETE"]
+            dialog.text = L["Delete profile '%s'"]:format(UIDROPDOWNMENU_MENU_VALUE)
+            dialog.OnAccept = function(self)
+                addon.db.bindings[UIDROPDOWNMENU_MENU_VALUE] = nil
+            end
+            HideDropDownMenu(1)
+            StaticPopup_Show("CLIQUE_CONFIRM_PROFILE_DELETE")
+        end
+        UIDropDownMenu_AddButton(info, level)
+    end
+end
+
+-- Update the elements on the panel to the current state
+function panel.refresh()
+    -- Initialize the dropdowns
+    local settings = addon.settings
+
+    UIDropDownMenu_Initialize(panel.prispec, spec_initialize)
+    UIDropDownMenu_SetSelectedValue(panel.prispec, settings.pri_profileKey or settings.profileKey)
+    UIDropDownMenu_SetText(panel.prispec, settings.pri_profileKey or settings.profileKey)
+
+    UIDropDownMenu_Initialize(panel.secspec, spec_initialize)
+    UIDropDownMenu_SetSelectedValue(panel.secspec, settings.sec_profileKey or settings.profileKey)
+    UIDropDownMenu_SetText(panel.secspec, settings.sec_profileKey or settings.profileKey)
+
+    UIDropDownMenu_Initialize(panel.profiledd, mgmt_initialize)
+    UIDropDownMenu_SetSelectedValue(panel.profiledd, settings.profileKey)
+    UIDropDownMenu_SetText(panel.profiledd, settings.profileKey)
+
+    panel.updown:SetChecked(settings.downclick)
+    panel.specswap:SetChecked(settings.specswap)
+    panel.specswap.EnableDisable()
+end
+
+function panel.okay()
+    local settings = addon.settings
+
+    -- Update the saved variables
+    settings.downclick = not not panel.updown:GetChecked()
+    settings.specswap = not not panel.specswap:GetChecked()
+    settings.pri_profileKey = UIDropDownMenu_GetSelectedValue(panel.prispec)
+    settings.sec_profileKey = UIDropDownMenu_GetSelectedValue(panel.secspec)
+    settings.profileKey = UIDropDownMenu_GetSelectedValue(panel.profiledd)
+
+    addon:ChangeProfile()
+end
+
+panel.cancel = panel.refresh
+
+function addon:UpdateOptionsPanel()
+    if panel:IsVisible() and panel.initialized then
+        panel.refresh()
+    end
 end

 InterfaceOptions_AddCategory(panel)