diff --git a/Inventory.lua b/Inventory.lua index 03d5256..ce8434c 100644 --- a/Inventory.lua +++ b/Inventory.lua @@ -1,85 +1,85 @@ -local SousChef = SousChef -local u = SousChef.Utility -local m = SousChef.Media -local LibSort = LibStub:GetLibrary("LibSort-1.0") - -function SousChef.AddRankToSlot(row, funcs) - local idFunc = funcs[1] - local slot = row.dataEntry.data - local bagId = slot[funcs[2]] - local slotIndex = funcs[3] and slot[funcs[3]] or nil - - local rankIcon = SousChef.getIcon(row) - - -- Allow for ingeniousclown's Inventory Grid View - if row:GetWidth() - row:GetHeight() < 5 then -- if we're mostly square - rankIcon:SetDimensions(20,20) - rankIcon:ClearAnchors() - rankIcon:SetAnchor(TOPLEFT, row, TOPLEFT, 2) - else - rankIcon:SetDimensions(30, 30) - rankIcon:ClearAnchors() - rankIcon:SetAnchor(RIGHT, row, RIGHT, -50) - end - - rankIcon:SetHidden(true) - - -- Are we gold or soulgem slot? Stay hidden and go away - if not bagId or not slot.name or slot.name == "" then return end - - local id = u.GetItemID(idFunc(bagId, slotIndex)) - local texture = SousChef.Pantry[id] - if SousChef.settings.showAltIngredientKnowledge then texture = SousChef.settings.Pantry[id] end - if texture then - - rankIcon:SetHidden(false) - - if SousChef.settings.boldIcon then - rankIcon:SetTexture(m.COOKINGB[texture]) - else - rankIcon:SetTexture(m.COOKING[texture]) - end - - if SousChef:IsOnShoppingList(id) then - rankIcon:SetColor(SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3]) - else - if SousChef.settings.onlyShowShopping then return rankIcon:SetHidden(true) end - rankIcon:SetColor(SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3]) - end - return - end - - if SousChef.settings.processRecipes then - if u.MatchInIgnoreList(slot.name) then return end - if slot.name:find(GetString(SI_ITEMTYPE29)) then - local match = u.MatchInCookbook(slot.name) - local gmatch = u.MatchInGlobalCookbook(slot.name) - if (match and SousChef.settings.checkKnown == "known") or - (not match and SousChef.settings.checkKnown == "unknown")then - rankIcon:SetTexture(m.CANLEARN) - rankIcon:SetHidden(false) - if not match and gmatch and SousChef.settings.checkKnown == "unknown" and SousChef.settings.markAlt then - rankIcon:SetColor(1,1,1,0.2) - else - rankIcon:SetColor(1,1,1,1) - end - end - end - end -end - -function SousChef.UnregisterSort() - LibSort:Unregister("Sous Chef") -end - -function SousChef.SetupSort() - LibSort:Register("Sous Chef", "Ingredient Rank", "The Provisioning Rank", "provisioningRank", SousChef.FindIngredientRank) - LibSort:RegisterDefaultOrder("Sous Chef", {"Ingredient Rank"}) -end - -function SousChef.FindIngredientRank(slotType, bagId, slotIndex) - local id = u.GetItemID(GetItemLink(bagId, slotIndex)) - local texture = SousChef.Pantry[id] - if SousChef.settings.showAltIngredientKnowledge then texture = SousChef.settings.Pantry[id] end - return texture or 100 +local SousChef = SousChef +local u = SousChef.Utility +local m = SousChef.Media +local LibSort = LibStub:GetLibrary("LibSort-1.0") + +function SousChef.AddRankToSlot(row, funcs) + local idFunc = funcs[1] + local slot = row.dataEntry.data + local bagId = slot[funcs[2]] + local slotIndex = funcs[3] and slot[funcs[3]] or nil + + local rankIcon = SousChef.getIcon(row) + + -- Allow for ingeniousclown's Inventory Grid View + if row:GetWidth() - row:GetHeight() < 5 then -- if we're mostly square + rankIcon:SetDimensions(20,20) + rankIcon:ClearAnchors() + rankIcon:SetAnchor(TOPLEFT, row, TOPLEFT, 2) + else + rankIcon:SetDimensions(30, 30) + rankIcon:ClearAnchors() + rankIcon:SetAnchor(RIGHT, row, RIGHT, -50) + end + + rankIcon:SetHidden(true) + + -- Are we gold or soulgem slot? Stay hidden and go away + if not bagId or not slot.name or slot.name == "" then return end + + local id = u.GetItemID(idFunc(bagId, slotIndex)) + local texture = SousChef.Pantry[id] + if SousChef.settings.showAltIngredientKnowledge then texture = SousChef.settings.Pantry[id] end + if texture then + + rankIcon:SetHidden(false) + + if SousChef.settings.boldIcon then + rankIcon:SetTexture(m.COOKINGB[texture]) + else + rankIcon:SetTexture(m.COOKING[texture]) + end + + if SousChef:IsOnShoppingList(id) then + rankIcon:SetColor(SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3]) + else + if SousChef.settings.onlyShowShopping then return rankIcon:SetHidden(true) end + rankIcon:SetColor(SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3]) + end + return + end + + if SousChef.settings.processRecipes then + if u.MatchInIgnoreList(slot.name) then return end + if slot.name:find(GetString(SI_ITEMTYPE29)) then + local match = u.MatchInCookbook(slot.name) + local gmatch = u.MatchInGlobalCookbook(slot.name) + if (match and SousChef.settings.checkKnown == "known") or + (not match and SousChef.settings.checkKnown == "unknown")then + rankIcon:SetTexture(m.CANLEARN) + rankIcon:SetHidden(false) + if not match and gmatch and SousChef.settings.checkKnown == "unknown" and SousChef.settings.markAlt then + rankIcon:SetColor(1,1,1,0.2) + else + rankIcon:SetColor(1,1,1,1) + end + end + end + end +end + +function SousChef.UnregisterSort() + LibSort:Unregister("Sous Chef") +end + +function SousChef.SetupSort() + LibSort:Register("Sous Chef", "Ingredient Rank", "The Provisioning Rank", "provisioningRank", SousChef.FindIngredientRank) + LibSort:RegisterDefaultOrder("Sous Chef", {"Ingredient Rank"}) +end + +function SousChef.FindIngredientRank(slotType, bagId, slotIndex) + local id = u.GetItemID(GetItemLink(bagId, slotIndex)) + local texture = SousChef.Pantry[id] + if SousChef.settings.showAltIngredientKnowledge then texture = SousChef.settings.Pantry[id] end + return texture or 100 end \ No newline at end of file diff --git a/Provisioning.lua b/Provisioning.lua index 1d24859..800a9fd 100644 --- a/Provisioning.lua +++ b/Provisioning.lua @@ -1,276 +1,276 @@ -local SousChef = SousChef -local u = SousChef.Utility -local m = SousChef.Media - --- SousChef:UpdateProvisioningTable() adds the Quality checkbox to the provisioner window and overrides the filtering function to incorporate it -function SousChef:UpdateProvisioningTable() - local function OnFilterChanged() - self.settings.qualityChecked = ZO_CheckButton_IsChecked(self.qualityCheckBox) - PROVISIONER:DirtyRecipeTree() - end - -- set up the quality checkbox - self.qualityCheckBox = SousChef_ControllerOnlyQuality - self.qualityCheckBox:SetParent(ZO_ProvisionerTopLevel) - ZO_CheckButton_SetLabelText(self.qualityCheckBox, "Quality") - ZO_CheckButton_SetToggleFunction(self.qualityCheckBox, OnFilterChanged) - ZO_CraftingUtils_ConnectCheckBoxToCraftingProcess(self.qualityCheckBox) - ZO_CheckButton_SetCheckState(self.qualityCheckBox, self.settings.qualityChecked) - - -- make room for the checkbox - ZO_ProvisionerTopLevelHaveSkills:ClearAnchors() - ZO_ProvisionerTopLevelHaveSkills:SetAnchor( LEFT, ZO_ProvisionerTopLevelHaveIngredients, RIGHT, 180 ) - - -- incorporate new checkbox into the filter - SousChef.filter = PROVISIONER.DoesRecipePassFilter - PROVISIONER.DoesRecipePassFilter = - function(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) - if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end - return SousChef.filter(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) - end -end - --- this is our "Mark Recipe" button definition -SousChef.ProvisioningButton= -{{ - name = "Mark Recipe", -- or function that returns a name - keybind = "SC_MARK_RECIPE", - control = self, - callback = function(descriptor) SousChef:MarkRecipe() end, - visible = function(descriptor) return PROVISIONER:GetSelectedRecipeIndex() ~= nil end, - alignment = KEYBIND_STRIP_ALIGN_RIGHT, -}} -local bGroup = SousChef.ProvisioningButton - --- SousChef:HookRecipeTreeFunction() adds the "Mark Recipe" button to the keybind bar, and set the provisioning window to display checkmarks by marked recipes -function SousChef:HookRecipeTreeFunction() - if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then - KEYBIND_STRIP:AddKeybindButtonGroup(bGroup) - else - KEYBIND_STRIP:UpdateKeybindButtonGroup(bGroup) - end - - -- Hook the provisioning panel - if not SousChef.hookedProvisioningFunction then - local ref = PROVISIONER.recipeTree.templateInfo.ZO_ProvisionerNavigationEntry - if ref then - SousChef.hookedProvisioningFunction = ref.setupFunction - ref.setupFunction = - function(...) - local node, control, data, open, userRequested, enabled = ... - SousChef.hookedProvisioningFunction(...) - local link = zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(data.recipeListIndex, data.recipeIndex, LINK_STYLE_BRACKETS)) - if link then - SousChef:AddNotifier(control, type(SousChef.settings.shoppingList[link]) == "table" and u.TableKeyConcat(SousChef.settings.shoppingList[link])) - end - end - end - end - PROVISIONER:DirtyRecipeTree() -end - --- SousChef:getMarkedIcon(row, marked) adds the checkmark next to each marked line in the provisioning window -function SousChef:getMarkedIcon(row, marked) - local rankIcon = SousChef.slotLines[row:GetName()] - -- first, if the control for the checkmark doesn't exist, create it - if(not rankIcon) then - rankIcon = WINDOW_MANAGER:CreateControl(row:GetName() .. "SousChef", row, CT_TEXTURE) - SousChef.slotLines[row:GetName()] = rankIcon - rankIcon:SetTexture(m.CANLEARN) - rankIcon:SetDimensions(20, 20) - rankIcon:SetAnchor(RIGHT, row, LEFT, -10) - rankIcon:SetMouseEnabled(true) - rankIcon:SetHandler("OnMouseExit", function() - ClearTooltip(InformationTooltip) - end) - end - -- then, if the recipe is marked by someone, show who, and set the checkmark's alpha accordingly - if marked then - rankIcon:SetHandler("OnMouseEnter", function() - InitializeTooltip(InformationTooltip, rankIcon, RIGHT, -15, 0) - InformationTooltip:AddLine("Marked by: " .. marked) - end) - if not marked:find(GetUnitName("player")) then - rankIcon:SetColor(1,1,1,0.2) - else - rankIcon:SetColor(1,1,1,1) - end - end - return rankIcon -end - --- SousChef:AddNotifier(control, marked) shows or hides the checkmark next to each recipe according to whether it's marked by anyone -function SousChef:AddNotifier(control, marked) - local icon = self:getMarkedIcon(control, marked) - if marked then - icon:SetHidden(false) - else - icon:SetHidden(true) - end -end - -function SousChef:IsOnShoppingList(id) - for i,v in ipairs(SousChef.settings.ReverseCookbook[id]) do - if type(SousChef.settings.shoppingList[v]) == "table" and next(SousChef.settings.shoppingList[v]) then return SousChef.settings.shoppingList[v] end - end - return false -end - -function SousChef:MarkRecipe() - local link = zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(PROVISIONER:GetSelectedRecipeListIndex(), PROVISIONER:GetSelectedRecipeIndex(), LINK_STYLE_BRACKETS)) - - if type(SousChef.settings.shoppingList[link]) ~= "table" then SousChef.settings.shoppingList[link] = {} end - - if not SousChef.settings.shoppingList[link][GetUnitName("player")] then - SousChef.settings.shoppingList[link][GetUnitName("player")] = true -- we're now marked - else - SousChef.settings.shoppingList[link][GetUnitName("player")] = nil -- we're now unmarked - -- if that was the last mark we just got rid of, then nil out the entire recipe entry - if u.TableLength(SousChef.settings.shoppingList[link]) == 0 then - SousChef.settings.shoppingList[link] = nil - end - end - - PROVISIONER:DirtyRecipeTree() -end - -function SousChef:HookRecipeTree(...) - local eventId, craftingTable = ... - if craftingTable ~= CRAFTING_TYPE_PROVISIONING then return end - zo_callLater(function() SousChef:HookRecipeTreeFunction() end, 1000) -end - -function SousChef:UnhookRecipeTree() - if KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then - KEYBIND_STRIP:RemoveKeybindButtonGroup(bGroup) - end -end - -function SousChef:HookGetRecipeInfo() - - if SousChef.settings.sortProvisioningTable then - SousChef.OldRefreshRecipeTree = ZO_Provisioner.RefreshRecipeTree - ZO_Provisioner.RefreshRecipeTree = - function() - return SousChef.RefreshRecipeTree(PROVISIONER) - end - end - SousChef.OldZO_ProvisionerRow_GetTextColor = ZO_ProvisionerRow_GetTextColor - ZO_ProvisionerRow_GetTextColor = - function(self) - return SousChef.ZO_ProvisionerRow_GetTextColor(self) - end -end - -local function SortRecipe(a, b) - if a.provisionerLevelReq == b.provisionerLevelReq then - if a.qualityReq == b.qualityReq then - if a.name == b.name then - return a.recipeIndex < b.recipeIndex - end - return a.name < b.name - end - return a.qualityReq < b.qualityReq - end - return a.provisionerLevelReq < b.provisionerLevelReq -end - -local function CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients) - local minCount - - for ingredientIndex = 1, numIngredients do - local _, _, requiredQuantity = GetRecipeIngredientItemInfo(recipeListIndex, recipeIndex, ingredientIndex) - local ingredientCount = GetCurrentRecipeIngredientCount(recipeListIndex, recipeIndex, ingredientIndex) - - minCount = zo_min(zo_floor(ingredientCount / requiredQuantity), minCount or math.huge) - if minCount == 0 then - return 0 - end - end - - return minCount or 0 -end - --- This is an almost direct clone of the existing function --- Except for two parts. --- 1) Storing the parent in the data (for each category of recipe) --- 2) Putting them all in a table first, then sorting, then adding them to the tree -function SousChef:RefreshRecipeTree() - self.dirty = false - - self.recipeTree:Reset() - - local hasAnyRecipes = false - local RecipeLines = {} - for recipeListIndex = 1, GetNumRecipeLists() do - local recipeListName, numRecipes, upIcon, downIcon, overIcon, disabledIcon, createSound = GetRecipeListInfo(recipeListIndex) - local parent - - for recipeIndex = 1, numRecipes do - local known, recipeName, numIngredients, provisionerLevelReq, qualityReq, specialIngredientType = GetRecipeInfo(recipeListIndex, recipeIndex) - if known then - local numCreatable = CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients) - if self:DoesRecipePassFilter(specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) then - parent = parent or self.recipeTree:AddNode("ZO_IconHeader", { recipeListIndex = recipeListIndex, name = recipeListName, upIcon = upIcon, downIcon = downIcon, overIcon = overIcon, disabledIcon = disabledIcon }, nil, SOUNDS.PROVISIONING_BLADE_SELECTED) - local data = { - recipeListIndex = recipeListIndex, - recipeIndex = recipeIndex, - name = recipeName, - provisionerLevelReq = provisionerLevelReq, - qualityReq = qualityReq, - specialIngredientType = specialIngredientType, - numIngredients = numIngredients, - numCreatable = numCreatable, - createSound = createSound, - parent = parent - } - - table.insert(RecipeLines, data) - hasAnyRecipes = true - end - end - end - end - - table.sort(RecipeLines, SortRecipe) - for i,data in ipairs(RecipeLines) do - self.recipeTree:AddNode("ZO_ProvisionerNavigationEntry", data, data.parent, SOUNDS.PROVISIONING_ENTRY_SELECTED) - end - - self.recipeTree:Commit() - - self.noRecipesLabel:SetHidden(hasAnyRecipes) - if not hasAnyRecipes then - self:RefreshRecipeDetails() - end -end - -local function Lighten(...) - r, g, b = ... - return r + 0.1, g + 0.1, b + 0.1 -end - -local function Lightest(...) - r, g, b = ... - return r + 0.3, g + 0.3, b + 0.3 -end - -function SousChef:ZO_ProvisionerRow_GetTextColor() - if not self.enabled then return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_DISABLED) end - - if self.selected then - if self.data.qualityReq > 1 then return Lightest(GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1)) end - return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_SELECTED) - end - - if self.mouseover then - if self.data.qualityReq > 1 then return Lighten(GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1)) end - return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_HIGHLIGHT) - end - - if self.meetsLevelReq and self.meetsQualityReq then - if self.data.qualityReq > 1 then return GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1) end - return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_NORMAL) - end - - return ZO_ERROR_COLOR:UnpackRGBA() +local SousChef = SousChef +local u = SousChef.Utility +local m = SousChef.Media + +-- SousChef:UpdateProvisioningTable() adds the Quality checkbox to the provisioner window and overrides the filtering function to incorporate it +function SousChef:UpdateProvisioningTable() + local function OnFilterChanged() + self.settings.qualityChecked = ZO_CheckButton_IsChecked(self.qualityCheckBox) + PROVISIONER:DirtyRecipeTree() + end + -- set up the quality checkbox + self.qualityCheckBox = SousChef_ControllerOnlyQuality + self.qualityCheckBox:SetParent(ZO_ProvisionerTopLevel) + ZO_CheckButton_SetLabelText(self.qualityCheckBox, "Quality") + ZO_CheckButton_SetToggleFunction(self.qualityCheckBox, OnFilterChanged) + ZO_CraftingUtils_ConnectCheckBoxToCraftingProcess(self.qualityCheckBox) + ZO_CheckButton_SetCheckState(self.qualityCheckBox, self.settings.qualityChecked) + + -- make room for the checkbox + ZO_ProvisionerTopLevelHaveSkills:ClearAnchors() + ZO_ProvisionerTopLevelHaveSkills:SetAnchor( LEFT, ZO_ProvisionerTopLevelHaveIngredients, RIGHT, 180 ) + + -- incorporate new checkbox into the filter + SousChef.filter = PROVISIONER.DoesRecipePassFilter + PROVISIONER.DoesRecipePassFilter = + function(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) + if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end + return SousChef.filter(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) + end +end + +-- this is our "Mark Recipe" button definition +SousChef.ProvisioningButton= +{{ + name = "Mark Recipe", -- or function that returns a name + keybind = "SC_MARK_RECIPE", + control = self, + callback = function(descriptor) SousChef:MarkRecipe() end, + visible = function(descriptor) return PROVISIONER:GetSelectedRecipeIndex() ~= nil end, + alignment = KEYBIND_STRIP_ALIGN_RIGHT, +}} +local bGroup = SousChef.ProvisioningButton + +-- SousChef:HookRecipeTreeFunction() adds the "Mark Recipe" button to the keybind bar, and set the provisioning window to display checkmarks by marked recipes +function SousChef:HookRecipeTreeFunction() + if not KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then + KEYBIND_STRIP:AddKeybindButtonGroup(bGroup) + else + KEYBIND_STRIP:UpdateKeybindButtonGroup(bGroup) + end + + -- Hook the provisioning panel + if not SousChef.hookedProvisioningFunction then + local ref = PROVISIONER.recipeTree.templateInfo.ZO_ProvisionerNavigationEntry + if ref then + SousChef.hookedProvisioningFunction = ref.setupFunction + ref.setupFunction = + function(...) + local node, control, data, open, userRequested, enabled = ... + SousChef.hookedProvisioningFunction(...) + local link = zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(data.recipeListIndex, data.recipeIndex, LINK_STYLE_BRACKETS)) + if link then + SousChef:AddNotifier(control, type(SousChef.settings.shoppingList[link]) == "table" and u.TableKeyConcat(SousChef.settings.shoppingList[link])) + end + end + end + end + PROVISIONER:DirtyRecipeTree() +end + +-- SousChef:getMarkedIcon(row, marked) adds the checkmark next to each marked line in the provisioning window +function SousChef:getMarkedIcon(row, marked) + local rankIcon = SousChef.slotLines[row:GetName()] + -- first, if the control for the checkmark doesn't exist, create it + if(not rankIcon) then + rankIcon = WINDOW_MANAGER:CreateControl(row:GetName() .. "SousChef", row, CT_TEXTURE) + SousChef.slotLines[row:GetName()] = rankIcon + rankIcon:SetTexture(m.CANLEARN) + rankIcon:SetDimensions(20, 20) + rankIcon:SetAnchor(RIGHT, row, LEFT, -10) + rankIcon:SetMouseEnabled(true) + rankIcon:SetHandler("OnMouseExit", function() + ClearTooltip(InformationTooltip) + end) + end + -- then, if the recipe is marked by someone, show who, and set the checkmark's alpha accordingly + if marked then + rankIcon:SetHandler("OnMouseEnter", function() + InitializeTooltip(InformationTooltip, rankIcon, RIGHT, -15, 0) + InformationTooltip:AddLine("Marked by: " .. marked) + end) + if not marked:find(GetUnitName("player")) then + rankIcon:SetColor(1,1,1,0.2) + else + rankIcon:SetColor(1,1,1,1) + end + end + return rankIcon +end + +-- SousChef:AddNotifier(control, marked) shows or hides the checkmark next to each recipe according to whether it's marked by anyone +function SousChef:AddNotifier(control, marked) + local icon = self:getMarkedIcon(control, marked) + if marked then + icon:SetHidden(false) + else + icon:SetHidden(true) + end +end + +function SousChef:IsOnShoppingList(id) + for i,v in ipairs(SousChef.settings.ReverseCookbook[id]) do + if type(SousChef.settings.shoppingList[v]) == "table" and next(SousChef.settings.shoppingList[v]) then return SousChef.settings.shoppingList[v] end + end + return false +end + +function SousChef:MarkRecipe() + local link = zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(PROVISIONER:GetSelectedRecipeListIndex(), PROVISIONER:GetSelectedRecipeIndex(), LINK_STYLE_BRACKETS)) + + if type(SousChef.settings.shoppingList[link]) ~= "table" then SousChef.settings.shoppingList[link] = {} end + + if not SousChef.settings.shoppingList[link][GetUnitName("player")] then + SousChef.settings.shoppingList[link][GetUnitName("player")] = true -- we're now marked + else + SousChef.settings.shoppingList[link][GetUnitName("player")] = nil -- we're now unmarked + -- if that was the last mark we just got rid of, then nil out the entire recipe entry + if u.TableLength(SousChef.settings.shoppingList[link]) == 0 then + SousChef.settings.shoppingList[link] = nil + end + end + + PROVISIONER:DirtyRecipeTree() +end + +function SousChef:HookRecipeTree(...) + local eventId, craftingTable = ... + if craftingTable ~= CRAFTING_TYPE_PROVISIONING then return end + zo_callLater(function() SousChef:HookRecipeTreeFunction() end, 1000) +end + +function SousChef:UnhookRecipeTree() + if KEYBIND_STRIP:HasKeybindButtonGroup(bGroup) then + KEYBIND_STRIP:RemoveKeybindButtonGroup(bGroup) + end +end + +function SousChef:HookGetRecipeInfo() + + if SousChef.settings.sortProvisioningTable then + SousChef.OldRefreshRecipeTree = ZO_Provisioner.RefreshRecipeTree + ZO_Provisioner.RefreshRecipeTree = + function() + return SousChef.RefreshRecipeTree(PROVISIONER) + end + end + SousChef.OldZO_ProvisionerRow_GetTextColor = ZO_ProvisionerRow_GetTextColor + ZO_ProvisionerRow_GetTextColor = + function(self) + return SousChef.ZO_ProvisionerRow_GetTextColor(self) + end +end + +local function SortRecipe(a, b) + if a.provisionerLevelReq == b.provisionerLevelReq then + if a.qualityReq == b.qualityReq then + if a.name == b.name then + return a.recipeIndex < b.recipeIndex + end + return a.name < b.name + end + return a.qualityReq < b.qualityReq + end + return a.provisionerLevelReq < b.provisionerLevelReq +end + +local function CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients) + local minCount + + for ingredientIndex = 1, numIngredients do + local _, _, requiredQuantity = GetRecipeIngredientItemInfo(recipeListIndex, recipeIndex, ingredientIndex) + local ingredientCount = GetCurrentRecipeIngredientCount(recipeListIndex, recipeIndex, ingredientIndex) + + minCount = zo_min(zo_floor(ingredientCount / requiredQuantity), minCount or math.huge) + if minCount == 0 then + return 0 + end + end + + return minCount or 0 +end + +-- This is an almost direct clone of the existing function +-- Except for two parts. +-- 1) Storing the parent in the data (for each category of recipe) +-- 2) Putting them all in a table first, then sorting, then adding them to the tree +function SousChef:RefreshRecipeTree() + self.dirty = false + + self.recipeTree:Reset() + + local hasAnyRecipes = false + local RecipeLines = {} + for recipeListIndex = 1, GetNumRecipeLists() do + local recipeListName, numRecipes, upIcon, downIcon, overIcon, disabledIcon, createSound = GetRecipeListInfo(recipeListIndex) + local parent + + for recipeIndex = 1, numRecipes do + local known, recipeName, numIngredients, provisionerLevelReq, qualityReq, specialIngredientType = GetRecipeInfo(recipeListIndex, recipeIndex) + if known then + local numCreatable = CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients) + if self:DoesRecipePassFilter(specialIngredientType, numCreatable, provisionerLevelReq, qualityReq) then + parent = parent or self.recipeTree:AddNode("ZO_IconHeader", { recipeListIndex = recipeListIndex, name = recipeListName, upIcon = upIcon, downIcon = downIcon, overIcon = overIcon, disabledIcon = disabledIcon }, nil, SOUNDS.PROVISIONING_BLADE_SELECTED) + local data = { + recipeListIndex = recipeListIndex, + recipeIndex = recipeIndex, + name = recipeName, + provisionerLevelReq = provisionerLevelReq, + qualityReq = qualityReq, + specialIngredientType = specialIngredientType, + numIngredients = numIngredients, + numCreatable = numCreatable, + createSound = createSound, + parent = parent + } + + table.insert(RecipeLines, data) + hasAnyRecipes = true + end + end + end + end + + table.sort(RecipeLines, SortRecipe) + for i,data in ipairs(RecipeLines) do + self.recipeTree:AddNode("ZO_ProvisionerNavigationEntry", data, data.parent, SOUNDS.PROVISIONING_ENTRY_SELECTED) + end + + self.recipeTree:Commit() + + self.noRecipesLabel:SetHidden(hasAnyRecipes) + if not hasAnyRecipes then + self:RefreshRecipeDetails() + end +end + +local function Lighten(...) + r, g, b = ... + return r + 0.1, g + 0.1, b + 0.1 +end + +local function Lightest(...) + r, g, b = ... + return r + 0.3, g + 0.3, b + 0.3 +end + +function SousChef:ZO_ProvisionerRow_GetTextColor() + if not self.enabled then return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_DISABLED) end + + if self.selected then + if self.data.qualityReq > 1 then return Lightest(GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1)) end + return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_SELECTED) + end + + if self.mouseover then + if self.data.qualityReq > 1 then return Lighten(GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1)) end + return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_HIGHLIGHT) + end + + if self.meetsLevelReq and self.meetsQualityReq then + if self.data.qualityReq > 1 then return GetInterfaceColor(INTERFACE_COLOR_TYPE_ITEM_QUALITY_COLORS, self.data.qualityReq + 1) end + return GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_NORMAL) + end + + return ZO_ERROR_COLOR:UnpackRGBA() end \ No newline at end of file diff --git a/SousChef.lua b/SousChef.lua index b64472b..c930537 100644 --- a/SousChef.lua +++ b/SousChef.lua @@ -1,375 +1,375 @@ ---[[------------------------------------------------------------------ ---SousChef.lua ---Author: Wobin - -inspired by ingeniousclown's Research Assistant - -------------------------------------------------------------------]]-- - -SousChef = {} -SousChef.Utility = {} -SousChef.Media = {} - -local SousChef = SousChef -local u = SousChef.Utility - -local LAM = LibStub:GetLibrary("LibAddonMenu-2.0") - -local BACKPACK = ZO_PlayerInventoryBackpack -local BANK = ZO_PlayerBankBackpack -local GUILD_BANK = ZO_GuildBankBackpack - -SousChef.Pantry = {} -SousChef.Cookbook = {} -SousChef.CookbookIndex = {} -SousChef.ReverseCookbook = {} -SousChef.settings = nil -SousChef.slotLines = {} -SousChef.hookedFunctions = {} -SousChef.hookedDataFunction = nil - -local rowHandler = {} - -local typeIconLookup = { - ["Grilled"] = 9, - ["Bread and Pies"] = 10, - ["Soup and Stew"] = 11, - ["Beer"] = 12, - ["Spirits"] = 13, - ["Wine"] = 14 -} - - --- FUNCTIONS --- AddRecipe(Cookbook, link) adds the linked recipe to the player cookbook if it isn't there already. -local function AddRecipe(Cookbook, link) - for _,v in pairs(Cookbook) do - if v == link then return end - end - table.insert(Cookbook, link) -end - --- RefreshViews() incorporates changes to the rendered inventory if it is visible. -function SousChef:RefreshViews() - ZO_ScrollList_RefreshVisible(BACKPACK) - ZO_ScrollList_RefreshVisible(BANK) - ZO_ScrollList_RefreshVisible(GUILD_BANK) -end - --- ParseRecipes() goes through the player's known recipes and records their info. -function SousChef:ParseRecipes() - local lists = GetNumRecipeLists() - - for listIndex = 1, lists do - local name, count = GetRecipeListInfo(listIndex) - for recipeIndex = 1, count do - if GetRecipeInfo(listIndex, recipeIndex) then - -- Store the recipes known: - local recipeName = u.CleanString((GetRecipeResultItemInfo(listIndex, recipeIndex))) - -- in this character's cookbook - SousChef.Cookbook[recipeName] = true - -- and in the settings, so other characters can see what recipes this character knows - if not SousChef.settings.Cookbook[recipeName] then - SousChef.settings.Cookbook[recipeName] = {} - end - SousChef.settings.Cookbook[recipeName][GetUnitName("player")] = true - - -- now record information about the recipe's ingregients - local _, _, ingredientCount, level, _, specialType = GetRecipeInfo(listIndex, recipeIndex) - -- store the recipe's index numbers and number of ingredients - -- XXX: why does this table get indexed with the formatted item name, but the Pantry table uses the whole link? - SousChef.CookbookIndex[zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))] = - {listIndex = listIndex, recipeIndex = recipeIndex, numIngredients = ingredientCount} - -- now, for every ingredient in the current recipe... - for ingredientIndex = 1, ingredientCount do - local link = u.GetItemID(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex, LINK_STYLE_DEFAULT)) - -- Store the fact that the ingredient is used - if ingredientIndex < 3 or not SousChef.settings.showSpecialIngredients then - -- if this isn't a special ingredient, or if the user doesn't want special ingredients marked as special, just record the highest-tier recipe this ingredient appears in - -- for this character, - SousChef.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) - -- and across characters - SousChef.settings.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) - else - -- if this is a special ingredient, record: - -- type icon number if user wants type icons, 7 if ingredient is a flavoring, 8 otherwise (ie, ingredient is a spice) - SousChef.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 - SousChef.settings.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 - end - -- Store the recipe it's used in to the character reverseCookbook - if not SousChef.ReverseCookbook[link] then SousChef.ReverseCookbook[link] = {} end - AddRecipe(SousChef.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) - -- ...and to the account-wide reverseCookbook - if not SousChef.settings.ReverseCookbook[link] then SousChef.settings.ReverseCookbook[link] = {} end - AddRecipe(SousChef.settings.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) - end - end - end - end - SousChef:RefreshViews() -end - --- SousChefCreateSettings() creates the configuration menu for the add-on -local function SousChefCreateSettings() - local panelData = { - type = "panel", - name = "Sous Chef", - displayName = "Sous Chef", - author = "Wobin & KatKat42 & CrazyDutchGuy", - version = "1.18", - registerForRefresh = true, - } - - LAM:RegisterAddonPanel("SousChefSettings", panelData) - - local optionsMenu = { - [1] = { - type = "header", - name = "Recipe Options", - width = "full", - }, - - [2] = { - type = "checkbox", - name = "Have Sous Chef check for recipes", - tooltip = "Non English clients may want to untick this if the experimental matching isn't sufficient", - getFunc = function() return SousChef.settings.processRecipes end, - setFunc = function(value) - SousChef.settings.processRecipes = not SousChef.settings.processRecipes - end, - width = "full", - }, - - [3] = { - type = "dropdown", - name = "Mark if recipes are ", - tooltip = "How do you want Sous Chef to indicate your knowledge of a recipe?", - choices = {"known", "unknown"}, - getFunc = function() return SousChef.settings.checkKnown end, - setFunc = function(valueString) SousChef.settings.checkKnown = valueString end, - disabled = function() return not SousChef.settings.processRecipes end, - }, - - [4] = { - type = "checkbox", - name = "Alternate Character Check", - tooltip = "Indicate if an alt knows the recipe on unknown recipes. Will only work if the above setting is set to 'unknown'", - getFunc = function() return SousChef.settings.markAlt end, - setFunc = function(value) SousChef.settings.markAlt = not SousChef.settings.markAlt SousChef:RefreshViews() end, - disabled = function() return not SousChef.settings.processRecipes end, - }, - - [5] = { - type = "checkbox", - name = "Alternate Character Recipe Knowledge", - tooltip = "Show in tooltips which characters know a recipe", - getFunc = function() return SousChef.settings.showAltKnowledge end, - setFunc = function(value) SousChef.settings.showAltKnowledge = not SousChef.settings.showAltKnowledge SousChef:RefreshViews() end, - disabled = function() return not SousChef.settings.processRecipes end, - }, - - [6] = { - type = "checkbox", - name = "Use the Experimental Recipe Matcher", - tooltip = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)", - getFunc = function() return SousChef.settings.experimentalMatch end, - setFunc = function(value) SousChef.settings.experimentalMatch = not SousChef.settings.experimentalMatch end, - disabled = function() return not SousChef.settings.processRecipes end, - }, - - [7] = { - type = "checkbox", - name = "Sort the Provisioning Table", - tooltip = "Will sort the provisioning table by Rank, Quality, then Name (but not by required level)", - getFunc = function() return SousChef.settings.sortProvisioningTable end, - setFunc = function(value) SousChef.settings.sortProvisioningTable = not SousChef.settings.sortProvisioningTable end, - }, - - [8] = { - type = "header", - name = "Tooltip Options", - width = "full", - }, - - [9] = { - type = "checkbox", - name = "Show Sous Chef in Ingredient tooltips after Mouse Click", - tooltip = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space", - warning = "Requires UI Reload", - getFunc = function() return SousChef.settings.showOnClick end, - setFunc = function(value) SousChef.settings.showOnClick = not SousChef.settings.showOnClick end, - }, - - [10] = { - type = "checkbox", - name = "Show Recipe Result Counts", - tooltip = "Show how many of each recipe can be made in the Ingredient tooltip", - getFunc = function() return SousChef.settings.showCounts end, - setFunc = function(value) SousChef.settings.showCounts = not SousChef.settings.showCounts end, - }, - - [11] = { - type = "checkbox", - name = "Alternate Character Ingredient Knowledge", - tooltip = "Indicte if an alt uses the ingredients", - getFunc = function() return SousChef.settings.showAltIngredientKnowledge end, - setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = not SousChef.settings.showAltIngredientKnowledge SousChef:RefreshViews() end, - }, - - [12] = { - type = "header", - name = "Indicator Options", - width = "full", - }, - - [13] = { - type = "checkbox", - name = "Use bolder icons", - tooltip = "Swap out rank icons to a more flat display", - getFunc = function() return SousChef.settings.boldIcon end, - setFunc = function(value) SousChef.settings.boldIcon = not SousChef.settings.boldIcon SousChef:RefreshViews() end, - }, - - [14] = { - type = "checkbox", - name = "Show Special Ingredients", - tooltip = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it", - getFunc = function() return SousChef.settings.showSpecialIngredients end, - setFunc = function(value) - SousChef.settings.showSpecialIngredients = not SousChef.settings.showSpecialIngredients - SousChef.ParseRecipes() - end, - }, - - [15] = { - type = "checkbox", - name = "Show Special Ingredient Types", - tooltip = "Use the icon for the type of food it's a special ingredient for, eg Grilled", - getFunc = function() return SousChef.settings.typeIcon end, - setFunc = function(value) SousChef.settings.typeIcon = not SousChef.settings.typeIcon SousChef.ParseRecipes() SousChef:RefreshViews() end, - disabled = function() return not SousChef.settings.showSpecialIngredients end, - }, - - [16] = { - type = "colorpicker", - name = "Indicator Colour", - tooltip = "Allows you to set the colour of the recipe indicator", - getFunc = function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end, - setFunc = function(r,g,b) SousChef.settings.colour[1] = r; SousChef.settings.colour[2] = g; SousChef.settings.colour[3] = b; SousChef:RefreshViews() end, - }, - - [17] = { - type = "colorpicker", - name = "Shopping List Indicator Colour", - tooltip = "Allows you to set the colour of hte indicator for ingredients in your Shopping List", - getFunc = function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end, - setFunc = function(r,g,b) SousChef.settings.shoppingColour[1] = r; SousChef.settings.shoppingColour[2] = g; SousChef.settings.shoppingColour[3] = b; SousChef:RefreshViews() end, - }, - - [18] = { - type = "checkbox", - name = "Only Mark Shopping List Ingredients", - tooltip = "Only mark ingredients on your Shopping List", - getFunc = function() return SousChef.settings.onlyShowShopping end, - setFunc = function(value) SousChef.settings.onlyShowShopping = not SousChef.settings.onlyShowShopping SousChef:RefreshViews() end, - }, - - [19] = { - type = "checkbox", - name = "Sort Ingredients in Inventory", - tooltip = "Will sort known ingredients by rank", - getFunc = function() return SousChef.settings.sortKnownIngredients end, - setFunc = function(value) - SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients - if not SousChef.settings.sortKnownIngredients then - SousChef.UnregisterSort() - else - SousChef.SetupSort() - end - end, - }, - } - - LAM:RegisterOptionControls("SousChefSettings", optionsMenu) - - ZO_CreateStringId("SI_BINDING_NAME_SC_MARK_RECIPE", "Mark Recipe") -end - --- SousChef_Loaded(eventCode, addOnName) runs when the EVENT_ADD_ON_LOADED event fires. -local function SousChef_Loaded(eventCode, addOnName) - if(addOnName ~= "SousChef") then return end - - -- default config settings - local defaults = { - watching = true, - checkKnown = "unknown", - markAlt = false, - colour = {1, 1, 1}, - shoppingColour = {0,1,1}, - Cookbook = {}, - Pantry = {}, - ReverseCookbook = {}, - showAltKnowledge = false, - showAltIngredientKnowledge = false, - boldIcon = false, - typeIcon = true, - experimentalMatch = false, - processRecipes = true, - showSpecialIngredients = false, - ignoredRecipes = {}, - showOnClick = false, - showCounts = true, - shoppingList = {}, - onlyShowShopping = false, - qualityChecked = false, - sortProvisioningTable = true, - sortKnownIngredients = false - } - - -- Fetch the saved variables - SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 9, GetCVar("Language.2"), defaults) - - local function tablelength(T) - local count = 0 - for _ in pairs(T) do count = count + 1 end - return count - end - - -- define some slash commands - SLASH_COMMANDS['/scstats'] = function() - d("Number of recipes known: ".. tablelength(SousChef.settings.Cookbook)) - d("Number of ingredients tracked: "..tablelength(SousChef.settings.Pantry)) - end - SLASH_COMMANDS['/sciadd'] = SousChef.AddRecipeToIgnoreList - SLASH_COMMANDS['/sciremove'] = SousChef.RemoveRecipeFromIgnoreList - SLASH_COMMANDS['/scilist'] = SousChef.ListIgnoredRecipes - - -- initialize the configuration menu - SousChefCreateSettings() - - -- parse the recipes this character knows, in a second - zo_callLater(SousChef.ParseRecipes, 1000) - - SousChef:UpdateProvisioningTable() - SousChef:HookGetRecipeInfo() - - if SousChef.settings.sortKnownIngredients then SousChef.SetupSort() end - - -- Now we register for some events, and hook into the function that sets the details on the inventory slot - zo_callLater(SousChef.HookEvents, 3000) -end - --- HookEvents() registers the add-on for some events -function SousChef.HookEvents() - -- let us know if we're opening a trading house, so we can look at its contents - EVENT_MANAGER:RegisterForEvent("SousChefTrading", EVENT_TRADING_HOUSE_RESPONSE_RECEIVED, SousChef.HookTrading) - -- let us know if we've learned a new recipe, so we can integrate it into our cookbook - EVENT_MANAGER:RegisterForEvent("SousChefLearnt", EVENT_RECIPE_LEARNED, SousChef.ParseRecipes) - -- let us know when we open a crafting station, so we can sort the recipe tree - EVENT_MANAGER:RegisterForEvent("SousChefProvi", EVENT_CRAFTING_STATION_INTERACT, function(...) SousChef:HookRecipeTree(...) end) - EVENT_MANAGER:RegisterForEvent("SousChefProviEnd", EVENT_END_CRAFTING_STATION_INTERACT, function() SousChef:UnhookRecipeTree() end) - -- and finally, hook the opening of the inventory, bank, guild bank, and loot windows so we can add icons and hook the tooltips - SousChef.HookInventory() -end - +--[[------------------------------------------------------------------ +--SousChef.lua +--Author: Wobin + +inspired by ingeniousclown's Research Assistant + +------------------------------------------------------------------]]-- + +SousChef = {} +SousChef.Utility = {} +SousChef.Media = {} + +local SousChef = SousChef +local u = SousChef.Utility + +local LAM = LibStub:GetLibrary("LibAddonMenu-2.0") + +local BACKPACK = ZO_PlayerInventoryBackpack +local BANK = ZO_PlayerBankBackpack +local GUILD_BANK = ZO_GuildBankBackpack + +SousChef.Pantry = {} +SousChef.Cookbook = {} +SousChef.CookbookIndex = {} +SousChef.ReverseCookbook = {} +SousChef.settings = nil +SousChef.slotLines = {} +SousChef.hookedFunctions = {} +SousChef.hookedDataFunction = nil + +local rowHandler = {} + +local typeIconLookup = { + ["Grilled"] = 9, + ["Bread and Pies"] = 10, + ["Soup and Stew"] = 11, + ["Beer"] = 12, + ["Spirits"] = 13, + ["Wine"] = 14 +} + + +-- FUNCTIONS +-- AddRecipe(Cookbook, link) adds the linked recipe to the player cookbook if it isn't there already. +local function AddRecipe(Cookbook, link) + for _,v in pairs(Cookbook) do + if v == link then return end + end + table.insert(Cookbook, link) +end + +-- RefreshViews() incorporates changes to the rendered inventory if it is visible. +function SousChef:RefreshViews() + ZO_ScrollList_RefreshVisible(BACKPACK) + ZO_ScrollList_RefreshVisible(BANK) + ZO_ScrollList_RefreshVisible(GUILD_BANK) +end + +-- ParseRecipes() goes through the player's known recipes and records their info. +function SousChef:ParseRecipes() + local lists = GetNumRecipeLists() + + for listIndex = 1, lists do + local name, count = GetRecipeListInfo(listIndex) + for recipeIndex = 1, count do + if GetRecipeInfo(listIndex, recipeIndex) then + -- Store the recipes known: + local recipeName = u.CleanString((GetRecipeResultItemInfo(listIndex, recipeIndex))) + -- in this character's cookbook + SousChef.Cookbook[recipeName] = true + -- and in the settings, so other characters can see what recipes this character knows + if not SousChef.settings.Cookbook[recipeName] then + SousChef.settings.Cookbook[recipeName] = {} + end + SousChef.settings.Cookbook[recipeName][GetUnitName("player")] = true + + -- now record information about the recipe's ingregients + local _, _, ingredientCount, level, _, specialType = GetRecipeInfo(listIndex, recipeIndex) + -- store the recipe's index numbers and number of ingredients + -- XXX: why does this table get indexed with the formatted item name, but the Pantry table uses the whole link? + SousChef.CookbookIndex[zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))] = + {listIndex = listIndex, recipeIndex = recipeIndex, numIngredients = ingredientCount} + -- now, for every ingredient in the current recipe... + for ingredientIndex = 1, ingredientCount do + local link = u.GetItemID(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex, LINK_STYLE_DEFAULT)) + -- Store the fact that the ingredient is used + if ingredientIndex < 3 or not SousChef.settings.showSpecialIngredients then + -- if this isn't a special ingredient, or if the user doesn't want special ingredients marked as special, just record the highest-tier recipe this ingredient appears in + -- for this character, + SousChef.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) + -- and across characters + SousChef.settings.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) + else + -- if this is a special ingredient, record: + -- type icon number if user wants type icons, 7 if ingredient is a flavoring, 8 otherwise (ie, ingredient is a spice) + SousChef.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 + SousChef.settings.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 + end + -- Store the recipe it's used in to the character reverseCookbook + if not SousChef.ReverseCookbook[link] then SousChef.ReverseCookbook[link] = {} end + AddRecipe(SousChef.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) + -- ...and to the account-wide reverseCookbook + if not SousChef.settings.ReverseCookbook[link] then SousChef.settings.ReverseCookbook[link] = {} end + AddRecipe(SousChef.settings.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) + end + end + end + end + SousChef:RefreshViews() +end + +-- SousChefCreateSettings() creates the configuration menu for the add-on +local function SousChefCreateSettings() + local panelData = { + type = "panel", + name = "Sous Chef", + displayName = "Sous Chef", + author = "Wobin & KatKat42 & CrazyDutchGuy", + version = "1.18", + registerForRefresh = true, + } + + LAM:RegisterAddonPanel("SousChefSettings", panelData) + + local optionsMenu = { + [1] = { + type = "header", + name = "Recipe Options", + width = "full", + }, + + [2] = { + type = "checkbox", + name = "Have Sous Chef check for recipes", + tooltip = "Non English clients may want to untick this if the experimental matching isn't sufficient", + getFunc = function() return SousChef.settings.processRecipes end, + setFunc = function(value) + SousChef.settings.processRecipes = not SousChef.settings.processRecipes + end, + width = "full", + }, + + [3] = { + type = "dropdown", + name = "Mark if recipes are ", + tooltip = "How do you want Sous Chef to indicate your knowledge of a recipe?", + choices = {"known", "unknown"}, + getFunc = function() return SousChef.settings.checkKnown end, + setFunc = function(valueString) SousChef.settings.checkKnown = valueString end, + disabled = function() return not SousChef.settings.processRecipes end, + }, + + [4] = { + type = "checkbox", + name = "Alternate Character Check", + tooltip = "Indicate if an alt knows the recipe on unknown recipes. Will only work if the above setting is set to 'unknown'", + getFunc = function() return SousChef.settings.markAlt end, + setFunc = function(value) SousChef.settings.markAlt = not SousChef.settings.markAlt SousChef:RefreshViews() end, + disabled = function() return not SousChef.settings.processRecipes end, + }, + + [5] = { + type = "checkbox", + name = "Alternate Character Recipe Knowledge", + tooltip = "Show in tooltips which characters know a recipe", + getFunc = function() return SousChef.settings.showAltKnowledge end, + setFunc = function(value) SousChef.settings.showAltKnowledge = not SousChef.settings.showAltKnowledge SousChef:RefreshViews() end, + disabled = function() return not SousChef.settings.processRecipes end, + }, + + [6] = { + type = "checkbox", + name = "Use the Experimental Recipe Matcher", + tooltip = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)", + getFunc = function() return SousChef.settings.experimentalMatch end, + setFunc = function(value) SousChef.settings.experimentalMatch = not SousChef.settings.experimentalMatch end, + disabled = function() return not SousChef.settings.processRecipes end, + }, + + [7] = { + type = "checkbox", + name = "Sort the Provisioning Table", + tooltip = "Will sort the provisioning table by Rank, Quality, then Name (but not by required level)", + getFunc = function() return SousChef.settings.sortProvisioningTable end, + setFunc = function(value) SousChef.settings.sortProvisioningTable = not SousChef.settings.sortProvisioningTable end, + }, + + [8] = { + type = "header", + name = "Tooltip Options", + width = "full", + }, + + [9] = { + type = "checkbox", + name = "Show Sous Chef in Ingredient tooltips after Mouse Click", + tooltip = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space", + warning = "Requires UI Reload", + getFunc = function() return SousChef.settings.showOnClick end, + setFunc = function(value) SousChef.settings.showOnClick = not SousChef.settings.showOnClick end, + }, + + [10] = { + type = "checkbox", + name = "Show Recipe Result Counts", + tooltip = "Show how many of each recipe can be made in the Ingredient tooltip", + getFunc = function() return SousChef.settings.showCounts end, + setFunc = function(value) SousChef.settings.showCounts = not SousChef.settings.showCounts end, + }, + + [11] = { + type = "checkbox", + name = "Alternate Character Ingredient Knowledge", + tooltip = "Indicte if an alt uses the ingredients", + getFunc = function() return SousChef.settings.showAltIngredientKnowledge end, + setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = not SousChef.settings.showAltIngredientKnowledge SousChef:RefreshViews() end, + }, + + [12] = { + type = "header", + name = "Indicator Options", + width = "full", + }, + + [13] = { + type = "checkbox", + name = "Use bolder icons", + tooltip = "Swap out rank icons to a more flat display", + getFunc = function() return SousChef.settings.boldIcon end, + setFunc = function(value) SousChef.settings.boldIcon = not SousChef.settings.boldIcon SousChef:RefreshViews() end, + }, + + [14] = { + type = "checkbox", + name = "Show Special Ingredients", + tooltip = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it", + getFunc = function() return SousChef.settings.showSpecialIngredients end, + setFunc = function(value) + SousChef.settings.showSpecialIngredients = not SousChef.settings.showSpecialIngredients + SousChef.ParseRecipes() + end, + }, + + [15] = { + type = "checkbox", + name = "Show Special Ingredient Types", + tooltip = "Use the icon for the type of food it's a special ingredient for, eg Grilled", + getFunc = function() return SousChef.settings.typeIcon end, + setFunc = function(value) SousChef.settings.typeIcon = not SousChef.settings.typeIcon SousChef.ParseRecipes() SousChef:RefreshViews() end, + disabled = function() return not SousChef.settings.showSpecialIngredients end, + }, + + [16] = { + type = "colorpicker", + name = "Indicator Colour", + tooltip = "Allows you to set the colour of the recipe indicator", + getFunc = function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end, + setFunc = function(r,g,b) SousChef.settings.colour[1] = r; SousChef.settings.colour[2] = g; SousChef.settings.colour[3] = b; SousChef:RefreshViews() end, + }, + + [17] = { + type = "colorpicker", + name = "Shopping List Indicator Colour", + tooltip = "Allows you to set the colour of hte indicator for ingredients in your Shopping List", + getFunc = function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end, + setFunc = function(r,g,b) SousChef.settings.shoppingColour[1] = r; SousChef.settings.shoppingColour[2] = g; SousChef.settings.shoppingColour[3] = b; SousChef:RefreshViews() end, + }, + + [18] = { + type = "checkbox", + name = "Only Mark Shopping List Ingredients", + tooltip = "Only mark ingredients on your Shopping List", + getFunc = function() return SousChef.settings.onlyShowShopping end, + setFunc = function(value) SousChef.settings.onlyShowShopping = not SousChef.settings.onlyShowShopping SousChef:RefreshViews() end, + }, + + [19] = { + type = "checkbox", + name = "Sort Ingredients in Inventory", + tooltip = "Will sort known ingredients by rank", + getFunc = function() return SousChef.settings.sortKnownIngredients end, + setFunc = function(value) + SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients + if not SousChef.settings.sortKnownIngredients then + SousChef.UnregisterSort() + else + SousChef.SetupSort() + end + end, + }, + } + + LAM:RegisterOptionControls("SousChefSettings", optionsMenu) + + ZO_CreateStringId("SI_BINDING_NAME_SC_MARK_RECIPE", "Mark Recipe") +end + +-- SousChef_Loaded(eventCode, addOnName) runs when the EVENT_ADD_ON_LOADED event fires. +local function SousChef_Loaded(eventCode, addOnName) + if(addOnName ~= "SousChef") then return end + + -- default config settings + local defaults = { + watching = true, + checkKnown = "unknown", + markAlt = false, + colour = {1, 1, 1}, + shoppingColour = {0,1,1}, + Cookbook = {}, + Pantry = {}, + ReverseCookbook = {}, + showAltKnowledge = false, + showAltIngredientKnowledge = false, + boldIcon = false, + typeIcon = true, + experimentalMatch = false, + processRecipes = true, + showSpecialIngredients = false, + ignoredRecipes = {}, + showOnClick = false, + showCounts = true, + shoppingList = {}, + onlyShowShopping = false, + qualityChecked = false, + sortProvisioningTable = true, + sortKnownIngredients = false + } + + -- Fetch the saved variables + SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 9, GetCVar("Language.2"), defaults) + + local function tablelength(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count + end + + -- define some slash commands + SLASH_COMMANDS['/scstats'] = function() + d("Number of recipes known: ".. tablelength(SousChef.settings.Cookbook)) + d("Number of ingredients tracked: "..tablelength(SousChef.settings.Pantry)) + end + SLASH_COMMANDS['/sciadd'] = SousChef.AddRecipeToIgnoreList + SLASH_COMMANDS['/sciremove'] = SousChef.RemoveRecipeFromIgnoreList + SLASH_COMMANDS['/scilist'] = SousChef.ListIgnoredRecipes + + -- initialize the configuration menu + SousChefCreateSettings() + + -- parse the recipes this character knows, in a second + zo_callLater(SousChef.ParseRecipes, 1000) + + SousChef:UpdateProvisioningTable() + SousChef:HookGetRecipeInfo() + + if SousChef.settings.sortKnownIngredients then SousChef.SetupSort() end + + -- Now we register for some events, and hook into the function that sets the details on the inventory slot + zo_callLater(SousChef.HookEvents, 3000) +end + +-- HookEvents() registers the add-on for some events +function SousChef.HookEvents() + -- let us know if we're opening a trading house, so we can look at its contents + EVENT_MANAGER:RegisterForEvent("SousChefTrading", EVENT_TRADING_HOUSE_RESPONSE_RECEIVED, SousChef.HookTrading) + -- let us know if we've learned a new recipe, so we can integrate it into our cookbook + EVENT_MANAGER:RegisterForEvent("SousChefLearnt", EVENT_RECIPE_LEARNED, SousChef.ParseRecipes) + -- let us know when we open a crafting station, so we can sort the recipe tree + EVENT_MANAGER:RegisterForEvent("SousChefProvi", EVENT_CRAFTING_STATION_INTERACT, function(...) SousChef:HookRecipeTree(...) end) + EVENT_MANAGER:RegisterForEvent("SousChefProviEnd", EVENT_END_CRAFTING_STATION_INTERACT, function() SousChef:UnhookRecipeTree() end) + -- and finally, hook the opening of the inventory, bank, guild bank, and loot windows so we can add icons and hook the tooltips + SousChef.HookInventory() +end + EVENT_MANAGER:RegisterForEvent("SousChefLoaded", EVENT_ADD_ON_LOADED, SousChef_Loaded) \ No newline at end of file diff --git a/SousChef.txt b/SousChef.txt index 61618b7..dfe3aac 100644 --- a/SousChef.txt +++ b/SousChef.txt @@ -1,33 +1,33 @@ -## Title: |cFFFFB0Sous Chef|r by |c00C000Wobin & CrazyDutchGuy & KatKat42|r -## Author: Wobin & CrazyDutchGuy & KatKat42 -## Version: @project-version@ -## APIVersion: 100007 -## SavedVariables: SousChef_Settings -## OptionalDependsOn: LibStub LibSort LibAddonMenu-2.0 - -libs\LibStub\LibStub.lua - -libs\LibAddonMenu-2.0\LibAddonMenu-2.0.lua -libs\LibAddonMenu-2.0\controls\panel.lua -libs\LibAddonMenu-2.0\controls\submenu.lua -libs\LibAddonMenu-2.0\controls\button.lua -libs\LibAddonMenu-2.0\controls\checkbox.lua -libs\LibAddonMenu-2.0\controls\colorpicker.lua -libs\LibAddonMenu-2.0\controls\custom.lua -libs\LibAddonMenu-2.0\controls\description.lua -libs\LibAddonMenu-2.0\controls\dropdown.lua -libs\LibAddonMenu-2.0\controls\editbox.lua -libs\LibAddonMenu-2.0\controls\header.lua -libs\LibAddonMenu-2.0\controls\slider.lua -libs\LibAddonMenu-2.0\controls\texture.lua - -libs\LibSort-1.0\LibSort-1.0.lua - -SousChef.lua -Utility.lua -Common.lua -Inventory.lua -TradingHouse.lua -Provisioning.lua -SousChef.xml -Bindings.xml \ No newline at end of file +## Title: |cFFFFB0Sous Chef|r by |c00C000Wobin & CrazyDutchGuy & KatKat42|r +## Author: Wobin & CrazyDutchGuy & KatKat42 +## Version: @project-version@ +## APIVersion: 100008 +## SavedVariables: SousChef_Settings +## OptionalDependsOn: LibStub LibSort LibAddonMenu-2.0 + +libs\LibStub\LibStub.lua + +libs\LibAddonMenu-2.0\LibAddonMenu-2.0.lua +libs\LibAddonMenu-2.0\controls\panel.lua +libs\LibAddonMenu-2.0\controls\submenu.lua +libs\LibAddonMenu-2.0\controls\button.lua +libs\LibAddonMenu-2.0\controls\checkbox.lua +libs\LibAddonMenu-2.0\controls\colorpicker.lua +libs\LibAddonMenu-2.0\controls\custom.lua +libs\LibAddonMenu-2.0\controls\description.lua +libs\LibAddonMenu-2.0\controls\dropdown.lua +libs\LibAddonMenu-2.0\controls\editbox.lua +libs\LibAddonMenu-2.0\controls\header.lua +libs\LibAddonMenu-2.0\controls\slider.lua +libs\LibAddonMenu-2.0\controls\texture.lua + +libs\LibSort-1.0\LibSort-1.0.lua + +SousChef.lua +Utility.lua +Common.lua +Inventory.lua +TradingHouse.lua +Provisioning.lua +SousChef.xml +Bindings.xml diff --git a/Utility.lua b/Utility.lua index 51e253b..7596302 100644 --- a/Utility.lua +++ b/Utility.lua @@ -1,97 +1,97 @@ -local SousChef = SousChef - -local u = SousChef.Utility - -function u.GetItemID(link) - if link == "" or not link then return -1 end - local itemid = select(4,ZO_LinkHandler_ParseLink(link)) - return tonumber(itemid) -end - -function u.EndsWith(String,End) - return End=='' or string.sub(String,-string.len(End))==End -end - -function u.StartsWith(String,Start) - return Start=='' or string.sub(String, 1, string.len(Start))==Start -end - -local languageElements = {"de ", "à ", "la ", } -local separators = {"%^[%a:]+", "-", " " } - -function u.StripLanguageIdentifiers(entry) - if not entry or entry == "" then return "" end - for _,v in pairs(languageElements) do - entry = entry:gsub(v, "") - end - return entry -end - -function u.Compress(entry) - if not entry or entry == "" then return "" end - for _,v in pairs(separators) do - entry = entry:gsub(v, "") - end - return entry -end - -function u.CleanString(entry) - if not entry or entry == "" then return "" end - if SousChef.settings.experimentalMatch then - entry = u.StripLanguageIdentifiers(entry) - end - return u.Compress(entry):lower() -end - -function u.MatchesRecipe(entry) - return u.CleanString(entry):find(u.CleanString(GetString(SI_ITEMTYPE29))) -end - -function u.TableKeyConcat(t) - local tt = {} - for k in pairs(t) do tt[#tt+1]=k end - return table.concat(tt, ", ") -end - -function u.MatchInCookbook(name) - name = u.CleanString(name) - for recipe,known in pairs(SousChef.Cookbook) do - if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then - local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name) - if difference < 3 and difference > -3 then - return known - end - end - end - return nil -end - -function u.MatchInGlobalCookbook(name) - name = u.CleanString(name) - for recipe,known in pairs(SousChef.settings.Cookbook) do - if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then - local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name) - if difference < 3 and difference > - 3 then - return known - end - end - end - return nil -end - -function u.MatchInIgnoreList(name) - name = u.CleanString(name) - for recipe in pairs(SousChef.settings.ignoredRecipes) do - if u.CleanString(recipe) == name then return true end - end - return false -end - -function u.TableLength(t) - if type(t) ~= "table" then return #t end - local n = 0 - for k, v in pairs(t) do - n = n + 1 - end - return n +local SousChef = SousChef + +local u = SousChef.Utility + +function u.GetItemID(link) + if link == "" or not link then return -1 end + local itemid = select(4,ZO_LinkHandler_ParseLink(link)) + return tonumber(itemid) +end + +function u.EndsWith(String,End) + return End=='' or string.sub(String,-string.len(End))==End +end + +function u.StartsWith(String,Start) + return Start=='' or string.sub(String, 1, string.len(Start))==Start +end + +local languageElements = {"de ", "à ", "la ", } +local separators = {"%^[%a:]+", "-", " " } + +function u.StripLanguageIdentifiers(entry) + if not entry or entry == "" then return "" end + for _,v in pairs(languageElements) do + entry = entry:gsub(v, "") + end + return entry +end + +function u.Compress(entry) + if not entry or entry == "" then return "" end + for _,v in pairs(separators) do + entry = entry:gsub(v, "") + end + return entry +end + +function u.CleanString(entry) + if not entry or entry == "" then return "" end + if SousChef.settings.experimentalMatch then + entry = u.StripLanguageIdentifiers(entry) + end + return u.Compress(entry):lower() +end + +function u.MatchesRecipe(entry) + return u.CleanString(entry):find(u.CleanString(GetString(SI_ITEMTYPE29))) +end + +function u.TableKeyConcat(t) + local tt = {} + for k in pairs(t) do tt[#tt+1]=k end + return table.concat(tt, ", ") +end + +function u.MatchInCookbook(name) + name = u.CleanString(name) + for recipe,known in pairs(SousChef.Cookbook) do + if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then + local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name) + if difference < 3 and difference > -3 then + return known + end + end + end + return nil +end + +function u.MatchInGlobalCookbook(name) + name = u.CleanString(name) + for recipe,known in pairs(SousChef.settings.Cookbook) do + if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then + local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name) + if difference < 3 and difference > - 3 then + return known + end + end + end + return nil +end + +function u.MatchInIgnoreList(name) + name = u.CleanString(name) + for recipe in pairs(SousChef.settings.ignoredRecipes) do + if u.CleanString(recipe) == name then return true end + end + return false +end + +function u.TableLength(t) + if type(t) ~= "table" then return #t end + local n = 0 + for k, v in pairs(t) do + n = n + 1 + end + return n end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua b/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua index b68d516..6ec9c4e 100644 --- a/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua +++ b/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua @@ -1,299 +1,299 @@ --- LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah) -- --- All Rights Reserved -- --- Permission is granted to use Seerah's LibAddonMenu-2.0 -- --- in your project. Any modifications to LibAddonMenu-2.0 -- --- may not be redistributed. -- --------------------------------------------------------------- - - ---Register LAM with LibStub -local MAJOR, MINOR = "LibAddonMenu-2.0", 7 -local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR) -if not lam then return end --the same or newer version of this lib is already loaded into memory - - ---UPVALUES-- -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert -local optionsWindow = ZO_OptionsWindowSettingsScrollChild -local _ - -local addonsForList = {} -local addonToOptionsMap = {} -local optionsCreated = {} -local widgets = {} - - ---METHOD: REGISTER WIDGET-- ---each widget has its version checked before loading, ---so we only have the most recent one in memory ---Usage: --- widgetType = "string"; the type of widget being registered --- widgetVersion = integer; the widget's version number -LAMCreateControl = LAMCreateControl or {} -local lamcc = LAMCreateControl - -function lam:RegisterWidget(widgetType, widgetVersion) - if widgets[widgetType] and widgets[widgetType] >= widgetVersion then - return false - else - widgets[widgetType] = widgetVersion - return true - end -end - - ---METHOD: OPEN TO ADDON PANEL-- ---opens to a specific addon's option panel ---Usage: --- panel = userdata; the panel returned by the :RegisterOptionsPanel method ---local settings = {en = "Settings", de = "Einstellungen", fr = "Réglages"} ---local locSettings = settings[GetCVar("Language.2")] -local locSettings = GetString(SI_GAME_MENU_SETTINGS) -function lam:OpenToPanel(panel) - SCENE_MANAGER:Show("gameMenuInGame") - zo_callLater(function() - ZO_GameMenu_InGame.gameMenu.headerControls[locSettings]:SetOpen(true) - SCENE_MANAGER:AddFragment(OPTIONS_WINDOW_FRAGMENT) - ZO_OptionsWindow_ChangePanels(lam.panelID) - panel:SetHidden(false) - end, 200) -end - - ---INTERNAL FUNCTION ---creates controls when options panel is first shown ---controls anchoring of these controls in the panel -local function CreateOptionsControls(panel) - local addonID = panel:GetName() - local optionsTable = addonToOptionsMap[addonID] - - if optionsTable then - local lastAddedControl, lacAtHalfRow - for _, widgetData in ipairs(optionsTable) do - local widgetType = widgetData.type - if widgetType == "submenu" then - local submenu = LAMCreateControl[widgetType](panel, widgetData) - if lastAddedControl then - submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15) - else - submenu:SetAnchor(TOPLEFT) - end - lastAddedControl = submenu - lacAtHalfRow = false - - local lastAddedControlSub, lacAtHalfRowSub - for _, subWidgetData in ipairs(widgetData.controls) do - local subWidgetType = subWidgetData.type - local subWidget = LAMCreateControl[subWidgetType](submenu, subWidgetData) - local isHalf = subWidgetData.width == "half" - if lastAddedControlSub then - if lacAtHalfRowSub and isHalf then - subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, TOPRIGHT, 5, 0) - lacAtHalfRowSub = false - else - subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15) - lacAtHalfRowSub = isHalf and true or false - lastAddedControlSub = subWidget - end - else - subWidget:SetAnchor(TOPLEFT) - lacAtHalfRowSub = isHalf and true or false - lastAddedControlSub = subWidget - end - end - else - local widget = LAMCreateControl[widgetType](panel, widgetData) - local isHalf = widgetData.width == "half" - if lastAddedControl then - if lacAtHalfRow and isHalf then - widget:SetAnchor(TOPLEFT, lastAddedControl, TOPRIGHT, 10, 0) - lacAtHalfRow = false - else - widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15) - lacAtHalfRow = isHalf and true or false - lastAddedControl = widget - end - else - widget:SetAnchor(TOPLEFT) - lacAtHalfRow = isHalf and true or false - lastAddedControl = widget - end - end - end - end - - optionsCreated[addonID] = true - cm:FireCallbacks("LAM-PanelControlsCreated", panel) -end - - ---INTERNAL FUNCTION ---handles switching between panels -local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel - local currentlySelected = LAMAddonPanelsMenu.currentlySelected - if currentlySelected and currentlySelected ~= panel then - currentlySelected:SetHidden(true) - end - LAMAddonPanelsMenu.currentlySelected = panel - - if not optionsCreated[panel:GetName()] then --if this is the first time opening this panel, create these options - CreateOptionsControls(panel) - end - - cm:FireCallbacks("LAM-RefreshPanel", panel) -end - - ---METHOD: REGISTER ADDON PANEL ---registers your addon with LibAddonMenu and creates a panel ---Usage: --- addonID = "string"; unique ID which will be the global name of your panel --- panelData = table; data object for your panel - see controls\panel.lua -function lam:RegisterAddonPanel(addonID, panelData) - local panel = lamcc.panel(nil, panelData, addonID) --addonID==global name of panel - panel:SetHidden(true) - panel:SetAnchor(TOPLEFT, LAMAddonPanelsMenu, TOPRIGHT, 10, 0) - panel:SetAnchor(BOTTOMLEFT, LAMAddonPanelsMenu, BOTTOMRIGHT, 10, 0) - panel:SetWidth(549) - panel:SetDrawLayer(DL_OVERLAY) - tinsert(addonsForList, {panel = addonID, name = panelData.name}) - panel:SetHandler("OnShow", ToggleAddonPanels) - if panelData.slashCommand then - SLASH_COMMANDS[panelData.slashCommand] = function() - lam:OpenToPanel(panel) - end - end - - return panel --return for authors creating options manually -end - - ---METHOD: REGISTER OPTION CONTROLS ---registers the options you want shown for your addon ---these are stored in a table where each key-value pair is the order ---of the options in the panel and the data for that control, respectively ---see exampleoptions.lua for an example ---see controls\<widget>.lua for each widget type ---Usage: --- addonID = "string"; the same string passed to :RegisterAddonPanel --- optionsTable = table; the table containing all of the options controls and their data -function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sliderData, buttonData, etc} - addonToOptionsMap[addonID] = optionsTable -end - - ---INTERNAL FUNCTION ---handles switching between LAM's Addon Settings panel and other panels in the Settings menu -local oldDefaultButton = ZO_OptionsWindowResetToDefaultButton -local oldCallback = oldDefaultButton.callback -local dummyFunc = function() end -local panelWindow = ZO_OptionsWindow -local bgL = ZO_OptionsWindowBGLeft -local bgR = ZO_OptionsWindowBGLeftBGRight -local function HandlePanelSwitching(panel) - if panel == lam.panelID then --our addon settings panel - oldDefaultButton:SetCallback(dummyFunc) - oldDefaultButton:SetHidden(true) - oldDefaultButton:SetAlpha(0) --just because it still bugs out - panelWindow:SetDimensions(999, 960) - bgL:SetWidth(666) - bgR:SetWidth(333) - else - local shown = LAMAddonPanelsMenu.currentlySelected - if shown then shown:SetHidden(true) end - oldDefaultButton:SetCallback(oldCallback) - oldDefaultButton:SetHidden(false) - oldDefaultButton:SetAlpha(1) - panelWindow:SetDimensions(768, 914) - bgL:SetWidth(512) - bgR:SetWidth(256) - end -end - - ---INTERNAL FUNCTION ---creates LAM's Addon Settings panel -local function CreateAddonSettingsPanel() - if not LAMSettingsPanelCreated then - local controlPanelID = "LAM_ADDON_SETTINGS_PANEL" - local controlPanelNames = {en = "Addon Settings", fr = "Extensions", de = "Erweiterungen"} - - ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")]) - - lam.panelID = _G[controlPanelID] - - ZO_PreHook("ZO_OptionsWindow_ChangePanels", HandlePanelSwitching) - - LAMSettingsPanelCreated = true - end -end - - ---INTERNAL FUNCTION ---adds each registered addon to the menu in LAM's panel -local function CreateAddonButtons(list, addons) - for i = 1, #addons do - local button = wm:CreateControlFromVirtual("LAMAddonMenuButton"..i, list, "ZO_DefaultTextButton") - button.name = addons[i].name - button.panel = _G[addons[i].panel] - button:SetText(button.name) - button:SetHorizontalAlignment(TEXT_ALIGN_LEFT) - button:SetWidth(190) - if i == 1 then - button:SetAnchor(TOPLEFT, list, TOPLEFT, 5, 5) - else - button:SetAnchor(TOPLEFT, _G["LAMAddonMenuButton"..i-1], BOTTOMLEFT) - end - button:SetHandler("OnClicked", function(self) self.panel:SetHidden(false) end) - end -end - - ---INTERNAL FUNCTION ---creates the left-hand menu in LAM's panel -local function CreateAddonList() - local list - --check if an earlier loaded copy of LAM created it already - list = LAMAddonPanelsMenu or wm:CreateControlFromVirtual("LAMAddonPanelsMenu", optionsWindow, "ZO_ScrollContainer") - list:ClearAnchors() - list:SetAnchor(TOPLEFT) - list:SetHeight(675) - list:SetWidth(200) - - list.bg = list.bg or wm:CreateControl(nil, list, CT_BACKDROP) - local bg = list.bg - bg:SetAnchorFill() --offsets of 8? - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) - bg:SetCenterColor(0, 0, 0, 0) - - local generatedButtons - list:SetHandler("OnShow", function(self) - if not generatedButtons and #addonsForList > 0 then - --we're about to show our list for the first time - let's sort the buttons before creating them - table.sort(addonsForList, function(a, b) - return a.name < b.name - end) - CreateAddonButtons(list, addonsForList) - self.currentlySelected = LAMAddonMenuButton1 and LAMAddonMenuButton1.panel - --since our addon panels don't have a parent, let's make sure they hide when we're done with them - ZO_PreHookHandler(ZO_OptionsWindow, "OnHide", function() self.currentlySelected:SetHidden(true) end) - generatedButtons = true - end - if self.currentlySelected then self.currentlySelected:SetHidden(false) end - end) - - list.controlType = OPTIONS_CUSTOM - list.panel = lam.panelID - - ZO_OptionsWindow_InitializeControl(list) - - return list -end - - ---INITIALIZING -CreateAddonSettingsPanel() -CreateAddonList() - +-- LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah) -- +-- All Rights Reserved -- +-- Permission is granted to use Seerah's LibAddonMenu-2.0 -- +-- in your project. Any modifications to LibAddonMenu-2.0 -- +-- may not be redistributed. -- +-------------------------------------------------------------- + + +--Register LAM with LibStub +local MAJOR, MINOR = "LibAddonMenu-2.0", 7 +local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR) +if not lam then return end --the same or newer version of this lib is already loaded into memory + + +--UPVALUES-- +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert +local optionsWindow = ZO_OptionsWindowSettingsScrollChild +local _ + +local addonsForList = {} +local addonToOptionsMap = {} +local optionsCreated = {} +local widgets = {} + + +--METHOD: REGISTER WIDGET-- +--each widget has its version checked before loading, +--so we only have the most recent one in memory +--Usage: +-- widgetType = "string"; the type of widget being registered +-- widgetVersion = integer; the widget's version number +LAMCreateControl = LAMCreateControl or {} +local lamcc = LAMCreateControl + +function lam:RegisterWidget(widgetType, widgetVersion) + if widgets[widgetType] and widgets[widgetType] >= widgetVersion then + return false + else + widgets[widgetType] = widgetVersion + return true + end +end + + +--METHOD: OPEN TO ADDON PANEL-- +--opens to a specific addon's option panel +--Usage: +-- panel = userdata; the panel returned by the :RegisterOptionsPanel method +--local settings = {en = "Settings", de = "Einstellungen", fr = "Réglages"} +--local locSettings = settings[GetCVar("Language.2")] +local locSettings = GetString(SI_GAME_MENU_SETTINGS) +function lam:OpenToPanel(panel) + SCENE_MANAGER:Show("gameMenuInGame") + zo_callLater(function() + ZO_GameMenu_InGame.gameMenu.headerControls[locSettings]:SetOpen(true) + SCENE_MANAGER:AddFragment(OPTIONS_WINDOW_FRAGMENT) + ZO_OptionsWindow_ChangePanels(lam.panelID) + panel:SetHidden(false) + end, 200) +end + + +--INTERNAL FUNCTION +--creates controls when options panel is first shown +--controls anchoring of these controls in the panel +local function CreateOptionsControls(panel) + local addonID = panel:GetName() + local optionsTable = addonToOptionsMap[addonID] + + if optionsTable then + local lastAddedControl, lacAtHalfRow + for _, widgetData in ipairs(optionsTable) do + local widgetType = widgetData.type + if widgetType == "submenu" then + local submenu = LAMCreateControl[widgetType](panel, widgetData) + if lastAddedControl then + submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15) + else + submenu:SetAnchor(TOPLEFT) + end + lastAddedControl = submenu + lacAtHalfRow = false + + local lastAddedControlSub, lacAtHalfRowSub + for _, subWidgetData in ipairs(widgetData.controls) do + local subWidgetType = subWidgetData.type + local subWidget = LAMCreateControl[subWidgetType](submenu, subWidgetData) + local isHalf = subWidgetData.width == "half" + if lastAddedControlSub then + if lacAtHalfRowSub and isHalf then + subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, TOPRIGHT, 5, 0) + lacAtHalfRowSub = false + else + subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15) + lacAtHalfRowSub = isHalf and true or false + lastAddedControlSub = subWidget + end + else + subWidget:SetAnchor(TOPLEFT) + lacAtHalfRowSub = isHalf and true or false + lastAddedControlSub = subWidget + end + end + else + local widget = LAMCreateControl[widgetType](panel, widgetData) + local isHalf = widgetData.width == "half" + if lastAddedControl then + if lacAtHalfRow and isHalf then + widget:SetAnchor(TOPLEFT, lastAddedControl, TOPRIGHT, 10, 0) + lacAtHalfRow = false + else + widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15) + lacAtHalfRow = isHalf and true or false + lastAddedControl = widget + end + else + widget:SetAnchor(TOPLEFT) + lacAtHalfRow = isHalf and true or false + lastAddedControl = widget + end + end + end + end + + optionsCreated[addonID] = true + cm:FireCallbacks("LAM-PanelControlsCreated", panel) +end + + +--INTERNAL FUNCTION +--handles switching between panels +local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel + local currentlySelected = LAMAddonPanelsMenu.currentlySelected + if currentlySelected and currentlySelected ~= panel then + currentlySelected:SetHidden(true) + end + LAMAddonPanelsMenu.currentlySelected = panel + + if not optionsCreated[panel:GetName()] then --if this is the first time opening this panel, create these options + CreateOptionsControls(panel) + end + + cm:FireCallbacks("LAM-RefreshPanel", panel) +end + + +--METHOD: REGISTER ADDON PANEL +--registers your addon with LibAddonMenu and creates a panel +--Usage: +-- addonID = "string"; unique ID which will be the global name of your panel +-- panelData = table; data object for your panel - see controls\panel.lua +function lam:RegisterAddonPanel(addonID, panelData) + local panel = lamcc.panel(nil, panelData, addonID) --addonID==global name of panel + panel:SetHidden(true) + panel:SetAnchor(TOPLEFT, LAMAddonPanelsMenu, TOPRIGHT, 10, 0) + panel:SetAnchor(BOTTOMLEFT, LAMAddonPanelsMenu, BOTTOMRIGHT, 10, 0) + panel:SetWidth(549) + panel:SetDrawLayer(DL_OVERLAY) + tinsert(addonsForList, {panel = addonID, name = panelData.name}) + panel:SetHandler("OnShow", ToggleAddonPanels) + if panelData.slashCommand then + SLASH_COMMANDS[panelData.slashCommand] = function() + lam:OpenToPanel(panel) + end + end + + return panel --return for authors creating options manually +end + + +--METHOD: REGISTER OPTION CONTROLS +--registers the options you want shown for your addon +--these are stored in a table where each key-value pair is the order +--of the options in the panel and the data for that control, respectively +--see exampleoptions.lua for an example +--see controls\<widget>.lua for each widget type +--Usage: +-- addonID = "string"; the same string passed to :RegisterAddonPanel +-- optionsTable = table; the table containing all of the options controls and their data +function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sliderData, buttonData, etc} + addonToOptionsMap[addonID] = optionsTable +end + + +--INTERNAL FUNCTION +--handles switching between LAM's Addon Settings panel and other panels in the Settings menu +local oldDefaultButton = ZO_OptionsWindowResetToDefaultButton +local oldCallback = oldDefaultButton.callback +local dummyFunc = function() end +local panelWindow = ZO_OptionsWindow +local bgL = ZO_OptionsWindowBGLeft +local bgR = ZO_OptionsWindowBGLeftBGRight +local function HandlePanelSwitching(panel) + if panel == lam.panelID then --our addon settings panel + oldDefaultButton:SetCallback(dummyFunc) + oldDefaultButton:SetHidden(true) + oldDefaultButton:SetAlpha(0) --just because it still bugs out + panelWindow:SetDimensions(999, 960) + bgL:SetWidth(666) + bgR:SetWidth(333) + else + local shown = LAMAddonPanelsMenu.currentlySelected + if shown then shown:SetHidden(true) end + oldDefaultButton:SetCallback(oldCallback) + oldDefaultButton:SetHidden(false) + oldDefaultButton:SetAlpha(1) + panelWindow:SetDimensions(768, 914) + bgL:SetWidth(512) + bgR:SetWidth(256) + end +end + + +--INTERNAL FUNCTION +--creates LAM's Addon Settings panel +local function CreateAddonSettingsPanel() + if not LAMSettingsPanelCreated then + local controlPanelID = "LAM_ADDON_SETTINGS_PANEL" + local controlPanelNames = {en = "Addon Settings", fr = "Extensions", de = "Erweiterungen"} + + ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")]) + + lam.panelID = _G[controlPanelID] + + ZO_PreHook("ZO_OptionsWindow_ChangePanels", HandlePanelSwitching) + + LAMSettingsPanelCreated = true + end +end + + +--INTERNAL FUNCTION +--adds each registered addon to the menu in LAM's panel +local function CreateAddonButtons(list, addons) + for i = 1, #addons do + local button = wm:CreateControlFromVirtual("LAMAddonMenuButton"..i, list, "ZO_DefaultTextButton") + button.name = addons[i].name + button.panel = _G[addons[i].panel] + button:SetText(button.name) + button:SetHorizontalAlignment(TEXT_ALIGN_LEFT) + button:SetWidth(190) + if i == 1 then + button:SetAnchor(TOPLEFT, list, TOPLEFT, 5, 5) + else + button:SetAnchor(TOPLEFT, _G["LAMAddonMenuButton"..i-1], BOTTOMLEFT) + end + button:SetHandler("OnClicked", function(self) self.panel:SetHidden(false) end) + end +end + + +--INTERNAL FUNCTION +--creates the left-hand menu in LAM's panel +local function CreateAddonList() + local list + --check if an earlier loaded copy of LAM created it already + list = LAMAddonPanelsMenu or wm:CreateControlFromVirtual("LAMAddonPanelsMenu", optionsWindow, "ZO_ScrollContainer") + list:ClearAnchors() + list:SetAnchor(TOPLEFT) + list:SetHeight(675) + list:SetWidth(200) + + list.bg = list.bg or wm:CreateControl(nil, list, CT_BACKDROP) + local bg = list.bg + bg:SetAnchorFill() --offsets of 8? + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) + bg:SetCenterColor(0, 0, 0, 0) + + local generatedButtons + list:SetHandler("OnShow", function(self) + if not generatedButtons and #addonsForList > 0 then + --we're about to show our list for the first time - let's sort the buttons before creating them + table.sort(addonsForList, function(a, b) + return a.name < b.name + end) + CreateAddonButtons(list, addonsForList) + self.currentlySelected = LAMAddonMenuButton1 and LAMAddonMenuButton1.panel + --since our addon panels don't have a parent, let's make sure they hide when we're done with them + ZO_PreHookHandler(ZO_OptionsWindow, "OnHide", function() self.currentlySelected:SetHidden(true) end) + generatedButtons = true + end + if self.currentlySelected then self.currentlySelected:SetHidden(false) end + end) + + list.controlType = OPTIONS_CUSTOM + list.panel = lam.panelID + + ZO_OptionsWindow_InitializeControl(list) + + return list +end + + +--INITIALIZING +CreateAddonSettingsPanel() +CreateAddonList() + diff --git a/libs/LibAddonMenu-2.0/controls/button.lua b/libs/LibAddonMenu-2.0/controls/button.lua index 9954a1e..8033833 100644 --- a/libs/LibAddonMenu-2.0/controls/button.lua +++ b/libs/LibAddonMenu-2.0/controls/button.lua @@ -1,87 +1,87 @@ ---[[buttonData = { - type = "button", - name = "My Button", - tooltip = "Button's tooltip text.", - func = function() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - icon = "icon\\path.dds", --(optional) - warning = "Will need to reload the UI.", --(optional) - reference = "MyAddonButton" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("button", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - control.button:SetEnabled(not disable) -end - - ---controlName is optional -function LAMCreateControl.button(parent, buttonData, controlName) - local control = wm:CreateTopLevelWindow(controlName or buttonData.reference) - control:SetParent(parent.scroll) - - local isHalfWidth = buttonData.width == "half" - control:SetDimensions(isHalfWidth and 250 or 510, isHalfWidth and 55 or 28) - control:SetMouseEnabled(true) - - if buttonData.icon then - control.button = wm:CreateControl(nil, control, CT_BUTTON) - control.button:SetDimensions(26, 26) - control.button:SetNormalTexture(buttonData.icon) - control.button:SetPressedOffset(2, 2) - else - --control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton") - control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton") - control.button:SetWidth(isHalfWidth and 180 or 200) - control.button:SetText(buttonData.name) - end - local button = control.button - button:SetAnchor(isHalfWidth and CENTER or RIGHT) - button:SetClickSound("Click") - button.tooltipText = buttonData.tooltip - button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - button:SetHandler("OnClicked", function(self, ...) - buttonData.func(self, ...) - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - end) - - if buttonData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0) - control.warning.tooltipText = buttonData.warning - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = buttonData - - if buttonData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - - --this is here because buttons don't have an UpdateValue method - if control.panel.data.registerForRefresh then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - end - - return control +--[[buttonData = { + type = "button", + name = "My Button", + tooltip = "Button's tooltip text.", + func = function() end, + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + icon = "icon\\path.dds", --(optional) + warning = "Will need to reload the UI.", --(optional) + reference = "MyAddonButton" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("button", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + control.button:SetEnabled(not disable) +end + + +--controlName is optional +function LAMCreateControl.button(parent, buttonData, controlName) + local control = wm:CreateTopLevelWindow(controlName or buttonData.reference) + control:SetParent(parent.scroll) + + local isHalfWidth = buttonData.width == "half" + control:SetDimensions(isHalfWidth and 250 or 510, isHalfWidth and 55 or 28) + control:SetMouseEnabled(true) + + if buttonData.icon then + control.button = wm:CreateControl(nil, control, CT_BUTTON) + control.button:SetDimensions(26, 26) + control.button:SetNormalTexture(buttonData.icon) + control.button:SetPressedOffset(2, 2) + else + --control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton") + control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton") + control.button:SetWidth(isHalfWidth and 180 or 200) + control.button:SetText(buttonData.name) + end + local button = control.button + button:SetAnchor(isHalfWidth and CENTER or RIGHT) + button:SetClickSound("Click") + button.tooltipText = buttonData.tooltip + button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + button:SetHandler("OnClicked", function(self, ...) + buttonData.func(self, ...) + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + end) + + if buttonData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0) + control.warning.tooltipText = buttonData.warning + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = buttonData + + if buttonData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + + --this is here because buttons don't have an UpdateValue method + if control.panel.data.registerForRefresh then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/checkbox.lua b/libs/LibAddonMenu-2.0/controls/checkbox.lua index 8432109..43ab28c 100644 --- a/libs/LibAddonMenu-2.0/controls/checkbox.lua +++ b/libs/LibAddonMenu-2.0/controls/checkbox.lua @@ -1,170 +1,170 @@ ---[[checkboxData = { - type = "checkbox", - name = "My Checkbox", - tooltip = "Checkbox's tooltip text.", - getFunc = function() return db.var end, - setFunc = function(value) db.var = value doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonCheckbox" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 4 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("checkbox", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert ---label -local enabledColor = ZO_DEFAULT_ENABLED_COLOR -local enabledHLcolor = ZO_HIGHLIGHT_TEXT -local disabledColor = ZO_DEFAULT_DISABLED_COLOR -local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR ---checkbox -local checkboxColor = ZO_NORMAL_TEXT -local checkboxHLcolor = ZO_HIGHLIGHT_TEXT - - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA()) - control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA()) - --control:SetMouseEnabled(not disable) - --control:SetMouseEnabled(true) - - control.isDisabled = disable -end - -local function ToggleCheckbox(control) - if control.value then - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.checkbox:SetText(control.checkedText) - else - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.checkbox:SetText(control.uncheckedText) - end -end - -local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - elseif value ~= nil then --our value could be false - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - end - control.value = value - - ToggleCheckbox(control) -end - -local function OnMouseEnter(control) - ZO_Options_OnMouseEnter(control) - - if control.isDisabled then return end - - local label = control.label - if control.value then - label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) - else - label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - end - control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) -end - -local function OnMouseExit(control) - ZO_Options_OnMouseExit(control) - - if control.isDisabled then return end - - local label = control.label - if control.value then - label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - else - label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - end - control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) -end - - ---controlName is optional -function LAMCreateControl.checkbox(parent, checkboxData, controlName) - local control = wm:CreateTopLevelWindow(controlName or checkboxData.reference) - control:SetParent(parent.scroll) - control:SetMouseEnabled(true) - control.tooltipText = checkboxData.tooltip - control:SetHandler("OnMouseEnter", OnMouseEnter) - control:SetHandler("OnMouseExit", OnMouseExit) - control:SetHandler("OnMouseUp", function(control) - if control.isDisabled then return end - PlaySound(SOUNDS.DEFAULT_CLICK) - control.value = not control.value - control:UpdateValue(false, control.value) - end) - - control.label = wm:CreateControl(nil, control, CT_LABEL) - local label = control.label - label:SetFont("ZoFontWinH4") - label:SetText(checkboxData.name) - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetHeight(26) - - control.checkbox = wm:CreateControl(nil, control, CT_LABEL) - local checkbox = control.checkbox - checkbox:SetFont("ZoFontGameBold") - checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) - control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper() - control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper() - - local isHalfWidth = checkboxData.width == "half" - if isHalfWidth then - control:SetDimensions(250, 55) - checkbox:SetDimensions(100, 26) - checkbox:SetAnchor(BOTTOMRIGHT) - label:SetAnchor(TOPLEFT) - label:SetAnchor(TOPRIGHT) - else - control:SetDimensions(510, 30) - checkbox:SetDimensions(200, 26) - checkbox:SetAnchor(RIGHT) - label:SetAnchor(LEFT) - label:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) - end - - if checkboxData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) - control.warning.tooltipText = checkboxData.warning - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = checkboxData - - if checkboxData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - - return control +--[[checkboxData = { + type = "checkbox", + name = "My Checkbox", + tooltip = "Checkbox's tooltip text.", + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", --(optional) + default = defaults.var, --(optional) + reference = "MyAddonCheckbox" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 4 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("checkbox", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert +--label +local enabledColor = ZO_DEFAULT_ENABLED_COLOR +local enabledHLcolor = ZO_HIGHLIGHT_TEXT +local disabledColor = ZO_DEFAULT_DISABLED_COLOR +local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR +--checkbox +local checkboxColor = ZO_NORMAL_TEXT +local checkboxHLcolor = ZO_HIGHLIGHT_TEXT + + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA()) + control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA()) + --control:SetMouseEnabled(not disable) + --control:SetMouseEnabled(true) + + control.isDisabled = disable +end + +local function ToggleCheckbox(control) + if control.value then + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.checkbox:SetText(control.checkedText) + else + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.checkbox:SetText(control.uncheckedText) + end +end + +local function UpdateValue(control, forceDefault, value) + if forceDefault then --if we are forcing defaults + value = control.data.default + control.data.setFunc(value) + elseif value ~= nil then --our value could be false + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + else + value = control.data.getFunc() + end + control.value = value + + ToggleCheckbox(control) +end + +local function OnMouseEnter(control) + ZO_Options_OnMouseEnter(control) + + if control.isDisabled then return end + + local label = control.label + if control.value then + label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) + else + label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + end + control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) +end + +local function OnMouseExit(control) + ZO_Options_OnMouseExit(control) + + if control.isDisabled then return end + + local label = control.label + if control.value then + label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + else + label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + end + control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) +end + + +--controlName is optional +function LAMCreateControl.checkbox(parent, checkboxData, controlName) + local control = wm:CreateTopLevelWindow(controlName or checkboxData.reference) + control:SetParent(parent.scroll) + control:SetMouseEnabled(true) + control.tooltipText = checkboxData.tooltip + control:SetHandler("OnMouseEnter", OnMouseEnter) + control:SetHandler("OnMouseExit", OnMouseExit) + control:SetHandler("OnMouseUp", function(control) + if control.isDisabled then return end + PlaySound(SOUNDS.DEFAULT_CLICK) + control.value = not control.value + control:UpdateValue(false, control.value) + end) + + control.label = wm:CreateControl(nil, control, CT_LABEL) + local label = control.label + label:SetFont("ZoFontWinH4") + label:SetText(checkboxData.name) + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetHeight(26) + + control.checkbox = wm:CreateControl(nil, control, CT_LABEL) + local checkbox = control.checkbox + checkbox:SetFont("ZoFontGameBold") + checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) + control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper() + control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper() + + local isHalfWidth = checkboxData.width == "half" + if isHalfWidth then + control:SetDimensions(250, 55) + checkbox:SetDimensions(100, 26) + checkbox:SetAnchor(BOTTOMRIGHT) + label:SetAnchor(TOPLEFT) + label:SetAnchor(TOPRIGHT) + else + control:SetDimensions(510, 30) + checkbox:SetDimensions(200, 26) + checkbox:SetAnchor(RIGHT) + label:SetAnchor(LEFT) + label:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) + end + + if checkboxData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) + control.warning.tooltipText = checkboxData.warning + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = checkboxData + + if checkboxData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + control.UpdateValue = UpdateValue + control:UpdateValue() + + if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/colorpicker.lua b/libs/LibAddonMenu-2.0/controls/colorpicker.lua index af645ba..5b58ca1 100644 --- a/libs/LibAddonMenu-2.0/controls/colorpicker.lua +++ b/libs/LibAddonMenu-2.0/controls/colorpicker.lua @@ -1,138 +1,138 @@ ---[[colorpickerData = { - type = "colorpicker", - name = "My Color Picker", - tooltip = "Color Picker's tooltip text.", - getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional) - setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, --(alpha is optional) - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = {defaults.r, defaults.g, defaults.b, defaults.a}, --(optional) table of default color values - reference = "MyAddonColorpicker" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end - - control.isDisabled = disable -end - -local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA) - if forceDefault then --if we are forcing defaults - local color = control.data.default - valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a - control.data.setFunc(valueR, valueG, valueB, valueA) - elseif valueR and valueG and valueB then - control.data.setFunc(valueR, valueG, valueB, valueA or 1) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - valueR, valueG, valueB, valueA = control.data.getFunc() - end - - control.thumb:SetColor(valueR, valueG, valueB, valueA or 1) -end - - -function LAMCreateControl.colorpicker(parent, colorpickerData, controlName) - local control = wm:CreateTopLevelWindow(controlName or colorpickerData.reference) - control:SetParent(parent.scroll) - control:SetMouseEnabled(true) - control.tooltipText = colorpickerData.tooltip - control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - - control.label = wm:CreateControl(nil, control, CT_LABEL) - local label = control.label - label:SetDimensions(300, 26) - label:SetAnchor(TOPLEFT) - label:SetFont("ZoFontWinH4") - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(colorpickerData.name) - - control.color = wm:CreateControl(nil, control, CT_CONTROL) - local color = control.color - - local isHalfWidth = colorpickerData.width == "half" - if isHalfWidth then - control:SetDimensions(250, 55) - label:SetDimensions(250, 26) - color:SetDimensions(100, 24) - color:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) - else - control:SetDimensions(510, 30) - label:SetDimensions(300, 26) - color:SetDimensions(200, 24) - color:SetAnchor(TOPRIGHT) - end - - control.thumb = wm:CreateControl(nil, color, CT_TEXTURE) - local thumb = control.thumb - thumb:SetDimensions(36, 18) - thumb:SetAnchor(LEFT, color, LEFT, 4, 0) - - color.border = wm:CreateControl(nil, color, CT_TEXTURE) - local border = color.border - border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds") - border:SetTextureCoords(0, .625, 0, .8125) - border:SetDimensions(40, 22) - border:SetAnchor(CENTER, thumb, CENTER, 0, 0) - - local function ColorPickerCallback(r, g, b, a) - control:UpdateValue(false, r, g, b, a) - end - - control:SetHandler("OnMouseUp", function(self, btn, upInside) - if self.isDisabled then return end - - if upInside then - local r, g, b, a = colorpickerData.getFunc() - COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name) - end - end) - - if colorpickerData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0) - control.warning.tooltipText = colorpickerData.warning - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = colorpickerData - - if colorpickerData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - - return control +--[[colorpickerData = { + type = "colorpicker", + name = "My Color Picker", + tooltip = "Color Picker's tooltip text.", + getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional) + setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, --(alpha is optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", --(optional) + default = {defaults.r, defaults.g, defaults.b, defaults.a}, --(optional) table of default color values + reference = "MyAddonColorpicker" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert + + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end + + control.isDisabled = disable +end + +local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA) + if forceDefault then --if we are forcing defaults + local color = control.data.default + valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a + control.data.setFunc(valueR, valueG, valueB, valueA) + elseif valueR and valueG and valueB then + control.data.setFunc(valueR, valueG, valueB, valueA or 1) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + else + valueR, valueG, valueB, valueA = control.data.getFunc() + end + + control.thumb:SetColor(valueR, valueG, valueB, valueA or 1) +end + + +function LAMCreateControl.colorpicker(parent, colorpickerData, controlName) + local control = wm:CreateTopLevelWindow(controlName or colorpickerData.reference) + control:SetParent(parent.scroll) + control:SetMouseEnabled(true) + control.tooltipText = colorpickerData.tooltip + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + + control.label = wm:CreateControl(nil, control, CT_LABEL) + local label = control.label + label:SetDimensions(300, 26) + label:SetAnchor(TOPLEFT) + label:SetFont("ZoFontWinH4") + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(colorpickerData.name) + + control.color = wm:CreateControl(nil, control, CT_CONTROL) + local color = control.color + + local isHalfWidth = colorpickerData.width == "half" + if isHalfWidth then + control:SetDimensions(250, 55) + label:SetDimensions(250, 26) + color:SetDimensions(100, 24) + color:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) + else + control:SetDimensions(510, 30) + label:SetDimensions(300, 26) + color:SetDimensions(200, 24) + color:SetAnchor(TOPRIGHT) + end + + control.thumb = wm:CreateControl(nil, color, CT_TEXTURE) + local thumb = control.thumb + thumb:SetDimensions(36, 18) + thumb:SetAnchor(LEFT, color, LEFT, 4, 0) + + color.border = wm:CreateControl(nil, color, CT_TEXTURE) + local border = color.border + border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds") + border:SetTextureCoords(0, .625, 0, .8125) + border:SetDimensions(40, 22) + border:SetAnchor(CENTER, thumb, CENTER, 0, 0) + + local function ColorPickerCallback(r, g, b, a) + control:UpdateValue(false, r, g, b, a) + end + + control:SetHandler("OnMouseUp", function(self, btn, upInside) + if self.isDisabled then return end + + if upInside then + local r, g, b, a = colorpickerData.getFunc() + COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name) + end + end) + + if colorpickerData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0) + control.warning.tooltipText = colorpickerData.warning + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = colorpickerData + + if colorpickerData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + control.UpdateValue = UpdateValue + control:UpdateValue() + + if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/custom.lua b/libs/LibAddonMenu-2.0/controls/custom.lua index ae7cdb2..1dd48ba 100644 --- a/libs/LibAddonMenu-2.0/controls/custom.lua +++ b/libs/LibAddonMenu-2.0/controls/custom.lua @@ -1,31 +1,31 @@ ---[[customData = { - type = "custom", - reference = "MyAddonCustomControl", --unique name for your control to use as reference - width = "full", --or "half" (optional) -} ]] - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("custom", widgetVersion) then return end - -local wm = WINDOW_MANAGER - -function LAMCreateControl.custom(parent, customData, controlName) - local control = wm:CreateTopLevelWindow(controlName or customData.reference) - control:SetResizeToFitDescendents(true) - control:SetParent(parent.scroll) - - local isHalfWidth = customData.width == "half" - if isHalfWidth then --note these restrictions - control:SetDimensionConstraints(250, 55, 250, 100) - control:SetDimensions(250, 55) - else - control:SetDimensionConstraints(510, 30, 510, 100) - control:SetDimensions(510, 30) - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = customData - - return control +--[[customData = { + type = "custom", + reference = "MyAddonCustomControl", --unique name for your control to use as reference + width = "full", --or "half" (optional) +} ]] + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("custom", widgetVersion) then return end + +local wm = WINDOW_MANAGER + +function LAMCreateControl.custom(parent, customData, controlName) + local control = wm:CreateTopLevelWindow(controlName or customData.reference) + control:SetResizeToFitDescendents(true) + control:SetParent(parent.scroll) + + local isHalfWidth = customData.width == "half" + if isHalfWidth then --note these restrictions + control:SetDimensionConstraints(250, 55, 250, 100) + control:SetDimensions(250, 55) + else + control:SetDimensionConstraints(510, 30, 510, 100) + control:SetDimensions(510, 30) + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = customData + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/description.lua b/libs/LibAddonMenu-2.0/controls/description.lua index 2db253b..bd6fe1d 100644 --- a/libs/LibAddonMenu-2.0/controls/description.lua +++ b/libs/LibAddonMenu-2.0/controls/description.lua @@ -1,53 +1,53 @@ ---[[descriptionData = { - type = "description", - title = "My Title", --(optional) - text = "My description text to display.", - width = "full", --or "half" (optional) - reference = "MyAddonDescription" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("description", widgetVersion) then return end - -local wm = WINDOW_MANAGER - -function LAMCreateControl.description(parent, descriptionData, controlName) - local control = wm:CreateTopLevelWindow(controlName or descriptionData.reference) - control:SetResizeToFitDescendents(true) - control:SetParent(parent.scroll) - local isHalfWidth = descriptionData.width == "half" - if isHalfWidth then - control:SetDimensionConstraints(250, 55, 250, 100) - control:SetDimensions(250, 55) - else - control:SetDimensionConstraints(510, 40, 510, 100) - control:SetDimensions(510, 30) - end - - control.desc = wm:CreateControl(nil, control, CT_LABEL) - local desc = control.desc - desc:SetVerticalAlignment(TEXT_ALIGN_TOP) - desc:SetFont("ZoFontGame") - desc:SetText(descriptionData.text) - desc:SetWidth(isHalfWidth and 250 or 510) - - if descriptionData.title then - control.title = wm:CreateControl(nil, control, CT_LABEL) - local title = control.title - title:SetWidth(isHalfWidth and 250 or 510) - title:SetAnchor(TOPLEFT, control, TOPLEFT) - title:SetFont("ZoFontWinH4") - title:SetText(descriptionData.title) - desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT) - else - desc:SetAnchor(TOPLEFT) - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = descriptionData - - return control - +--[[descriptionData = { + type = "description", + title = "My Title", --(optional) + text = "My description text to display.", + width = "full", --or "half" (optional) + reference = "MyAddonDescription" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("description", widgetVersion) then return end + +local wm = WINDOW_MANAGER + +function LAMCreateControl.description(parent, descriptionData, controlName) + local control = wm:CreateTopLevelWindow(controlName or descriptionData.reference) + control:SetResizeToFitDescendents(true) + control:SetParent(parent.scroll) + local isHalfWidth = descriptionData.width == "half" + if isHalfWidth then + control:SetDimensionConstraints(250, 55, 250, 100) + control:SetDimensions(250, 55) + else + control:SetDimensionConstraints(510, 40, 510, 100) + control:SetDimensions(510, 30) + end + + control.desc = wm:CreateControl(nil, control, CT_LABEL) + local desc = control.desc + desc:SetVerticalAlignment(TEXT_ALIGN_TOP) + desc:SetFont("ZoFontGame") + desc:SetText(descriptionData.text) + desc:SetWidth(isHalfWidth and 250 or 510) + + if descriptionData.title then + control.title = wm:CreateControl(nil, control, CT_LABEL) + local title = control.title + title:SetWidth(isHalfWidth and 250 or 510) + title:SetAnchor(TOPLEFT, control, TOPLEFT) + title:SetFont("ZoFontWinH4") + title:SetText(descriptionData.title) + desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT) + else + desc:SetAnchor(TOPLEFT) + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = descriptionData + + return control + end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/dropdown.lua b/libs/LibAddonMenu-2.0/controls/dropdown.lua index e338db6..36610b8 100644 --- a/libs/LibAddonMenu-2.0/controls/dropdown.lua +++ b/libs/LibAddonMenu-2.0/controls/dropdown.lua @@ -1,153 +1,153 @@ ---[[dropdownData = { - type = "dropdown", - name = "My Dropdown", - tooltip = "Dropdown's tooltip text.", - choices = {"table", "of", "choices"}, - sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted - getFunc = function() return db.var end, - setFunc = function(var) db.var = var doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonDropdown" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 3 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("dropdown", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - control.dropdown:SetEnabled(not disable) - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end -end - -local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - control.dropdown:SetSelectedItem(value) - elseif value then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - control.dropdown:SetSelectedItem(value) - end -end - -local function DropdownCallback(choice, choiceText, choice) - choice.control:UpdateValue(false, choiceText) -end - -local function UpdateChoices(control, choices) - control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?) - - --build new list of choices - local choices = choices or control.data.choices - for i = 1, #choices do - local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback) - entry.control = control - control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort - end -end - -local function GrabSortingInfo(sortInfo) - local t, i = {}, 1 - for info in string.gmatch(sortInfo, "([^%-]+)") do - t[i] = info - i = i + 1 - end - - return t -end - - -local comboboxCount = 1 -function LAMCreateControl.dropdown(parent, dropdownData, controlName) - local control = wm:CreateTopLevelWindow(controlName or dropdownData.reference) - control:SetParent(parent.scroll) - control:SetMouseEnabled(true) - control.tooltipText = dropdownData.tooltip - control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - - control.label = wm:CreateControl(nil, control, CT_LABEL) - local label = control.label - label:SetAnchor(TOPLEFT) - label:SetFont("ZoFontWinH4") - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(dropdownData.name) - - control.combobox = wm:CreateControlFromVirtual(parent:GetName().."Combobox"..comboboxCount, control, "ZO_ComboBox") - comboboxCount = comboboxCount + 1 - local combobox = control.combobox - combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox) - local dropdown = control.dropdown - if dropdownData.sort then - local sortInfo = GrabSortingInfo(dropdownData.sort) - local sortType, sortOrder = sortInfo[1], sortInfo[2] - dropdown:SetSortOrder(sortOrder == "up" and ZO_SORT_ORDER_UP or ZO_SORT_ORDER_DOWN, sortType == "name" and ZO_SORT_BY_NAME or ZO_SORT_BY_NAME_NUMERIC) - end - - local isHalfWidth = dropdownData.width == "half" - if isHalfWidth then - control:SetDimensions(250, 55) - label:SetDimensions(250, 26) - combobox:SetDimensions(240, 26) - --dropdown:SetWidth(240) - combobox:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) - else - control:SetDimensions(510, 30) - label:SetDimensions(300, 26) - combobox:SetDimensions(200, 26) - --dropdown:SetWidth(200) - combobox:SetAnchor(TOPRIGHT) - end - - if warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0) - control.warning.tooltipText = warningText - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = dropdownData - - if dropdownData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateChoices = UpdateChoices - control:UpdateChoices(dropdownData.choices) - control.UpdateValue = UpdateValue - control:UpdateValue() - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - - return control +--[[dropdownData = { + type = "dropdown", + name = "My Dropdown", + tooltip = "Dropdown's tooltip text.", + choices = {"table", "of", "choices"}, + sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted + getFunc = function() return db.var end, + setFunc = function(var) db.var = var doStuff() end, + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", --(optional) + default = defaults.var, --(optional) + reference = "MyAddonDropdown" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 3 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("dropdown", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert + + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + control.dropdown:SetEnabled(not disable) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end +end + +local function UpdateValue(control, forceDefault, value) + if forceDefault then --if we are forcing defaults + value = control.data.default + control.data.setFunc(value) + control.dropdown:SetSelectedItem(value) + elseif value then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + else + value = control.data.getFunc() + control.dropdown:SetSelectedItem(value) + end +end + +local function DropdownCallback(choice, choiceText, choice) + choice.control:UpdateValue(false, choiceText) +end + +local function UpdateChoices(control, choices) + control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?) + + --build new list of choices + local choices = choices or control.data.choices + for i = 1, #choices do + local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback) + entry.control = control + control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort + end +end + +local function GrabSortingInfo(sortInfo) + local t, i = {}, 1 + for info in string.gmatch(sortInfo, "([^%-]+)") do + t[i] = info + i = i + 1 + end + + return t +end + + +local comboboxCount = 1 +function LAMCreateControl.dropdown(parent, dropdownData, controlName) + local control = wm:CreateTopLevelWindow(controlName or dropdownData.reference) + control:SetParent(parent.scroll) + control:SetMouseEnabled(true) + control.tooltipText = dropdownData.tooltip + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + + control.label = wm:CreateControl(nil, control, CT_LABEL) + local label = control.label + label:SetAnchor(TOPLEFT) + label:SetFont("ZoFontWinH4") + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(dropdownData.name) + + control.combobox = wm:CreateControlFromVirtual(parent:GetName().."Combobox"..comboboxCount, control, "ZO_ComboBox") + comboboxCount = comboboxCount + 1 + local combobox = control.combobox + combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) + control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox) + local dropdown = control.dropdown + if dropdownData.sort then + local sortInfo = GrabSortingInfo(dropdownData.sort) + local sortType, sortOrder = sortInfo[1], sortInfo[2] + dropdown:SetSortOrder(sortOrder == "up" and ZO_SORT_ORDER_UP or ZO_SORT_ORDER_DOWN, sortType == "name" and ZO_SORT_BY_NAME or ZO_SORT_BY_NAME_NUMERIC) + end + + local isHalfWidth = dropdownData.width == "half" + if isHalfWidth then + control:SetDimensions(250, 55) + label:SetDimensions(250, 26) + combobox:SetDimensions(240, 26) + --dropdown:SetWidth(240) + combobox:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) + else + control:SetDimensions(510, 30) + label:SetDimensions(300, 26) + combobox:SetDimensions(200, 26) + --dropdown:SetWidth(200) + combobox:SetAnchor(TOPRIGHT) + end + + if warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0) + control.warning.tooltipText = warningText + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = dropdownData + + if dropdownData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + control.UpdateChoices = UpdateChoices + control:UpdateChoices(dropdownData.choices) + control.UpdateValue = UpdateValue + control:UpdateValue() + + if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/editbox.lua b/libs/LibAddonMenu-2.0/controls/editbox.lua index f2b4ded..0b97ae1 100644 --- a/libs/LibAddonMenu-2.0/controls/editbox.lua +++ b/libs/LibAddonMenu-2.0/controls/editbox.lua @@ -1,153 +1,153 @@ ---[[editboxData = { - type = "editbox", - name = "My Editbox", - tooltip = "Editbox's tooltip text.", - getFunc = function() return db.text end, - setFunc = function(text) db.text = text doStuff() end, - isMultiline = true, --boolean - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.text, --(optional) - reference = "MyAddonEditbox" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 3 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("editbox", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end - --control.editbox:SetEditEnabled(not disable) - control.editbox:SetMouseEnabled(not disable) -end - -local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - control.editbox:SetText(value) - elseif value then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - control.editbox:SetText(value) - end -end - - -function LAMCreateControl.editbox(parent, editboxData, controlName) - local control = wm:CreateTopLevelWindow(controlName or editboxData.reference) - control:SetParent(parent.scroll) - control:SetMouseEnabled(true) - control:SetResizeToFitDescendents(true) - control.tooltipText = editboxData.tooltip - control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - - control.label = wm:CreateControl(nil, control, CT_LABEL) - local label = control.label - label:SetAnchor(TOPLEFT) - label:SetFont("ZoFontWinH4") - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(editboxData.name) - - control.bg = wm:CreateControlFromVirtual(nil, control, "ZO_EditBackdrop") - local bg = control.bg - - if editboxData.isMultiline then - control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop") - control.editbox:SetHandler("OnMouseWheel", function(self, delta) - if self:HasFocus() then --only set focus to new spots if the editbox is currently in use - local cursorPos = self:GetCursorPosition() - local text = self:GetText() - local textLen = text:len() - local newPos - if delta > 0 then --scrolling up - local reverseText = text:reverse() - local revCursorPos = textLen - cursorPos - local revPos = reverseText:find("\n", revCursorPos+1) - newPos = revPos and textLen - revPos - else --scrolling down - newPos = text:find("\n", cursorPos+1) - end - if newPos then --if we found a new line, then scroll, otherwise don't - self:SetCursorPosition(newPos) - end - end - end) - else - control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop") - end - local editbox = control.editbox - editbox:SetText(editboxData.getFunc()) - editbox:SetMaxInputChars(3000) - editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end) - editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end) - editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - - local isHalfWidth = editboxData.width == "half" - if isHalfWidth then - control:SetDimensions(250, 55) - label:SetDimensions(250, 26) - bg:SetDimensions(225, editboxData.isMultiline and 74 or 24) - bg:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) - if editboxData.isMultiline then - editbox:SetDimensionConstraints(210, 74, 210, 500) - end - else - control:SetDimensions(510, 30) - label:SetDimensions(300, 26) - bg:SetDimensions(200, editboxData.isMultiline and 100 or 24) - bg:SetAnchor(TOPRIGHT) - if editboxData.isMultiline then - editbox:SetDimensionConstraints(185, 100, 185, 500) - end - end - - if editboxData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0) - control.warning.tooltipText = editboxData.warning - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = editboxData - - if editboxData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - - return control +--[[editboxData = { + type = "editbox", + name = "My Editbox", + tooltip = "Editbox's tooltip text.", + getFunc = function() return db.text end, + setFunc = function(text) db.text = text doStuff() end, + isMultiline = true, --boolean + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", --(optional) + default = defaults.text, --(optional) + reference = "MyAddonEditbox" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 3 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("editbox", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local tinsert = table.insert + + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end + --control.editbox:SetEditEnabled(not disable) + control.editbox:SetMouseEnabled(not disable) +end + +local function UpdateValue(control, forceDefault, value) + if forceDefault then --if we are forcing defaults + value = control.data.default + control.data.setFunc(value) + control.editbox:SetText(value) + elseif value then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + else + value = control.data.getFunc() + control.editbox:SetText(value) + end +end + + +function LAMCreateControl.editbox(parent, editboxData, controlName) + local control = wm:CreateTopLevelWindow(controlName or editboxData.reference) + control:SetParent(parent.scroll) + control:SetMouseEnabled(true) + control:SetResizeToFitDescendents(true) + control.tooltipText = editboxData.tooltip + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + + control.label = wm:CreateControl(nil, control, CT_LABEL) + local label = control.label + label:SetAnchor(TOPLEFT) + label:SetFont("ZoFontWinH4") + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(editboxData.name) + + control.bg = wm:CreateControlFromVirtual(nil, control, "ZO_EditBackdrop") + local bg = control.bg + + if editboxData.isMultiline then + control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop") + control.editbox:SetHandler("OnMouseWheel", function(self, delta) + if self:HasFocus() then --only set focus to new spots if the editbox is currently in use + local cursorPos = self:GetCursorPosition() + local text = self:GetText() + local textLen = text:len() + local newPos + if delta > 0 then --scrolling up + local reverseText = text:reverse() + local revCursorPos = textLen - cursorPos + local revPos = reverseText:find("\n", revCursorPos+1) + newPos = revPos and textLen - revPos + else --scrolling down + newPos = text:find("\n", cursorPos+1) + end + if newPos then --if we found a new line, then scroll, otherwise don't + self:SetCursorPosition(newPos) + end + end + end) + else + control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop") + end + local editbox = control.editbox + editbox:SetText(editboxData.getFunc()) + editbox:SetMaxInputChars(3000) + editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end) + editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end) + editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) + + local isHalfWidth = editboxData.width == "half" + if isHalfWidth then + control:SetDimensions(250, 55) + label:SetDimensions(250, 26) + bg:SetDimensions(225, editboxData.isMultiline and 74 or 24) + bg:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT) + if editboxData.isMultiline then + editbox:SetDimensionConstraints(210, 74, 210, 500) + end + else + control:SetDimensions(510, 30) + label:SetDimensions(300, 26) + bg:SetDimensions(200, editboxData.isMultiline and 100 or 24) + bg:SetAnchor(TOPRIGHT) + if editboxData.isMultiline then + editbox:SetDimensionConstraints(185, 100, 185, 500) + end + end + + if editboxData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0) + control.warning.tooltipText = editboxData.warning + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = editboxData + + if editboxData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + control.UpdateValue = UpdateValue + control:UpdateValue() + + if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/header.lua b/libs/LibAddonMenu-2.0/controls/header.lua index 46250ca..ce6f463 100644 --- a/libs/LibAddonMenu-2.0/controls/header.lua +++ b/libs/LibAddonMenu-2.0/controls/header.lua @@ -1,36 +1,36 @@ ---[[headerData = { - type = "header", - name = "My Header", - width = "full", --or "half" (optional) - reference = "MyAddonHeader" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("header", widgetVersion) then return end - -local wm = WINDOW_MANAGER - -function LAMCreateControl.header(parent, headerData, controlName) - local control = wm:CreateTopLevelWindow(controlName or headerData.reference) - control:SetParent(parent.scroll) - local isHalfWidth = headerData.width == "half" - control:SetDimensions(isHalfWidth and 250 or 510, 30) - - control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider") - local divider = control.divider - divider:SetWidth(isHalfWidth and 250 or 510) - divider:SetAnchor(TOPLEFT) - - control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local header = control.header - header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT) - header:SetAnchor(BOTTOMRIGHT) - header:SetText(headerData.name) - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = headerData - - return control +--[[headerData = { + type = "header", + name = "My Header", + width = "full", --or "half" (optional) + reference = "MyAddonHeader" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("header", widgetVersion) then return end + +local wm = WINDOW_MANAGER + +function LAMCreateControl.header(parent, headerData, controlName) + local control = wm:CreateTopLevelWindow(controlName or headerData.reference) + control:SetParent(parent.scroll) + local isHalfWidth = headerData.width == "half" + control:SetDimensions(isHalfWidth and 250 or 510, 30) + + control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider") + local divider = control.divider + divider:SetWidth(isHalfWidth and 250 or 510) + divider:SetAnchor(TOPLEFT) + + control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local header = control.header + header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT) + header:SetAnchor(BOTTOMRIGHT) + header:SetText(headerData.name) + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = headerData + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/panel.lua b/libs/LibAddonMenu-2.0/controls/panel.lua index de1beb1..7de8da4 100644 --- a/libs/LibAddonMenu-2.0/controls/panel.lua +++ b/libs/LibAddonMenu-2.0/controls/panel.lua @@ -1,136 +1,136 @@ ---[[panelData = { - type = "panel", - name = "Window Title", - displayName = "My Longer Window Title", --(optional) (can be useful for long addon names or if you want to colorize it) - author = "Seerah", --(optional) - version = "2.0", --(optional) - slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel (don't forget to include the slash!) - registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) - registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) - resetFunc = function() print("defaults reset") end, --(optional) custom function to run after settings are reset to defaults -} ]] - - -local widgetVersion = 4 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("panel", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER - -local function RefreshPanel(control) - local panel = control.panel or control --callback can be fired by a single control or by the panel showing - local panelControls = panel.controlsToRefresh - - for i = 1, #panelControls do - local updateControl = panelControls[i] - if updateControl ~= control then - if updateControl.UpdateValue then - updateControl:UpdateValue() - end - if updateControl.UpdateDisabled then - updateControl:UpdateDisabled() - end - end - end -end - -local function ForceDefaults(panel) - local panelControls = panel.controlsToRefresh - - for i = 1, #panelControls do - local updateControl = panelControls[i] - if updateControl.UpdateValue and updateControl.data.default ~= nil then - updateControl:UpdateValue(true) - end - end - - if panel.data.resetFunc then - panel.data.resetFunc() - end - - cm:FireCallbacks("LAM-RefreshPanel", panel) -end -ESO_Dialogs["LAM_DEFAULTS"] = { - title = { - text = SI_OPTIONS_RESET_TITLE, - }, - mainText = { - text = SI_OPTIONS_RESET_PROMPT, - align = TEXT_ALIGN_CENTER, - }, - buttons = { - [1] = { - text = SI_OPTIONS_RESET, - callback = function(dialog) ForceDefaults(dialog.data[1]) end, - }, - [2] = { - text = SI_DIALOG_CANCEL, - }, - }, -} - -local scrollCount = 1 -function LAMCreateControl.panel(parent, panelData, controlName) - local control = wm:CreateTopLevelWindow(controlName) - control:SetParent(parent) - - control.bg = wm:CreateControl(nil, control, CT_BACKDROP) - local bg = control.bg - bg:SetAnchorFill() - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) - bg:SetCenterColor(0, 0, 0, 0) - - control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local label = control.label - label:SetAnchor(TOPLEFT, control, TOPLEFT, 10, 10) - label:SetText(panelData.displayName and panelData.displayName or panelData.name) - - if panelData.author or panelData.version then - control.info = wm:CreateControl(nil, control, CT_LABEL) - local info = control.info - info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin") - info:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) - info:SetHeight(13) - info:SetAnchor(TOPRIGHT, control, BOTTOMRIGHT, -5, 2) - if panelData.author and panelData.version then - --info:SetText("Version: "..panelData.version.." - "..GetString(SI_ADDON_MANAGER_AUTHOR)..": "..panelData.author) - info:SetText(string.format("Version: %s - %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) - elseif panelData.author then - info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) - else - info:SetText("Version: "..panelData.version) - end - end - - control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..scrollCount, control, "ZO_ScrollContainer") - scrollCount = scrollCount + 1 - local container = control.container - container:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 20) - container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3) - control.scroll = GetControl(control.container, "ScrollChild") - control.scroll:SetResizeToFitPadding(0, 20) - - if panelData.registerForDefaults then - control.defaultButton = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultTextButton") - local defaultButton = control.defaultButton - defaultButton:SetFont("ZoFontDialogKeybindDescription") - defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT) - --defaultButton:SetText("Reset To Defaults") - defaultButton:SetText(GetString(SI_OPTIONS_RESET_TITLE)) - defaultButton:SetDimensions(200, 30) - defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2) - defaultButton:SetHandler("OnClicked", function() - ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control}) - end) - end - - if panelData.registerForRefresh then - cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel) - end - - control.data = panelData - control.controlsToRefresh = {} - - return control +--[[panelData = { + type = "panel", + name = "Window Title", + displayName = "My Longer Window Title", --(optional) (can be useful for long addon names or if you want to colorize it) + author = "Seerah", --(optional) + version = "2.0", --(optional) + slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel (don't forget to include the slash!) + registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) + registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) + resetFunc = function() print("defaults reset") end, --(optional) custom function to run after settings are reset to defaults +} ]] + + +local widgetVersion = 4 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("panel", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER + +local function RefreshPanel(control) + local panel = control.panel or control --callback can be fired by a single control or by the panel showing + local panelControls = panel.controlsToRefresh + + for i = 1, #panelControls do + local updateControl = panelControls[i] + if updateControl ~= control then + if updateControl.UpdateValue then + updateControl:UpdateValue() + end + if updateControl.UpdateDisabled then + updateControl:UpdateDisabled() + end + end + end +end + +local function ForceDefaults(panel) + local panelControls = panel.controlsToRefresh + + for i = 1, #panelControls do + local updateControl = panelControls[i] + if updateControl.UpdateValue and updateControl.data.default ~= nil then + updateControl:UpdateValue(true) + end + end + + if panel.data.resetFunc then + panel.data.resetFunc() + end + + cm:FireCallbacks("LAM-RefreshPanel", panel) +end +ESO_Dialogs["LAM_DEFAULTS"] = { + title = { + text = SI_OPTIONS_RESET_TITLE, + }, + mainText = { + text = SI_OPTIONS_RESET_PROMPT, + align = TEXT_ALIGN_CENTER, + }, + buttons = { + [1] = { + text = SI_OPTIONS_RESET, + callback = function(dialog) ForceDefaults(dialog.data[1]) end, + }, + [2] = { + text = SI_DIALOG_CANCEL, + }, + }, +} + +local scrollCount = 1 +function LAMCreateControl.panel(parent, panelData, controlName) + local control = wm:CreateTopLevelWindow(controlName) + control:SetParent(parent) + + control.bg = wm:CreateControl(nil, control, CT_BACKDROP) + local bg = control.bg + bg:SetAnchorFill() + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) + bg:SetCenterColor(0, 0, 0, 0) + + control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local label = control.label + label:SetAnchor(TOPLEFT, control, TOPLEFT, 10, 10) + label:SetText(panelData.displayName and panelData.displayName or panelData.name) + + if panelData.author or panelData.version then + control.info = wm:CreateControl(nil, control, CT_LABEL) + local info = control.info + info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin") + info:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) + info:SetHeight(13) + info:SetAnchor(TOPRIGHT, control, BOTTOMRIGHT, -5, 2) + if panelData.author and panelData.version then + --info:SetText("Version: "..panelData.version.." - "..GetString(SI_ADDON_MANAGER_AUTHOR)..": "..panelData.author) + info:SetText(string.format("Version: %s - %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) + elseif panelData.author then + info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) + else + info:SetText("Version: "..panelData.version) + end + end + + control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..scrollCount, control, "ZO_ScrollContainer") + scrollCount = scrollCount + 1 + local container = control.container + container:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 20) + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3) + control.scroll = GetControl(control.container, "ScrollChild") + control.scroll:SetResizeToFitPadding(0, 20) + + if panelData.registerForDefaults then + control.defaultButton = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultTextButton") + local defaultButton = control.defaultButton + defaultButton:SetFont("ZoFontDialogKeybindDescription") + defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT) + --defaultButton:SetText("Reset To Defaults") + defaultButton:SetText(GetString(SI_OPTIONS_RESET_TITLE)) + defaultButton:SetDimensions(200, 30) + defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2) + defaultButton:SetHandler("OnClicked", function() + ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control}) + end) + end + + if panelData.registerForRefresh then + cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel) + end + + control.data = panelData + control.controlsToRefresh = {} + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/slider.lua b/libs/LibAddonMenu-2.0/controls/slider.lua index b28e1b8..e58c623 100644 --- a/libs/LibAddonMenu-2.0/controls/slider.lua +++ b/libs/LibAddonMenu-2.0/controls/slider.lua @@ -1,182 +1,182 @@ ---[[sliderData = { - type = "slider", - name = "My Slider", - tooltip = "Slider's tooltip text.", - min = 0, - max = 20, - step = 1, --(optional) - getFunc = function() return db.var end, - setFunc = function(value) db.var = value doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonSlider" --(optional) unique global reference to control -} ]] - - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("slider", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local round = zo_round -local strformat = string.format -local tinsert = table.insert - -local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - control.slider:SetEnabled(not disable) - control.slidervalue:SetEditEnabled(not disable) - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end -end - -local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - elseif value and value >= control.data.min and value <= control.data.max then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - end - - control.slider:SetValue(value) - control.slidervalue:SetText(value) -end - - -function LAMCreateControl.slider(parent, sliderData, controlName) - local control = wm:CreateTopLevelWindow(controlName or sliderData.reference) - control:SetParent(parent.scroll) - local isHalfWidth = sliderData.width == "half" - if isHalfWidth then - control:SetDimensions(250, 55) - else - control:SetDimensions(510, 40) - end - control:SetMouseEnabled(true) - control.tooltipText = sliderData.tooltip - control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - - control.label = wm:CreateControl(nil, control, CT_LABEL) - local label = control.label - label:SetFont("ZoFontWinH4") - label:SetDimensions(isHalfWidth and 250 or 300, 26) - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetAnchor(isHalfWidth and TOPLEFT or LEFT) - label:SetText(sliderData.name) - - --skipping creating the backdrop... Is this the actual slider texture? - control.slider = wm:CreateControl(nil, control, CT_SLIDER) - local slider = control.slider - slider:SetDimensions(190, 14) - if isHalfWidth then - slider:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT, -5, 2) - else - slider:SetAnchor(RIGHT, control, RIGHT, -5, -5) - end - slider:SetMouseEnabled(true) - slider:SetOrientation(ORIENTATION_HORIZONTAL) - --put nil for highlighted texture file path, and what look to be texture coords - slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16) - local minValue = sliderData.min - local maxValue = sliderData.max - slider:SetMinMax(minValue, maxValue) - slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end) - - slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP) - local bg = slider.bg - bg:SetCenterColor(0, 0, 0) - bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4) - bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4) - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4) - - control.minText = wm:CreateControl(nil, slider, CT_LABEL) - local minText = control.minText - minText:SetFont("ZoFontGameSmall") - minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT) - minText:SetText(sliderData.min) - - control.maxText = wm:CreateControl(nil, slider, CT_LABEL) - local maxText = control.maxText - maxText:SetFont("ZoFontGameSmall") - maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT) - maxText:SetText(sliderData.max) - - control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop") - control.slidervalueBG:SetDimensions(50, 16) - control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0) - control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop") - local slidervalue = control.slidervalue - slidervalue:ClearAnchors() - slidervalue:SetAnchor(TOPLEFT, slidervaluebg, TOPLEFT, 3, 1) - slidervalue:SetAnchor(BOTTOMRIGHT, slidervaluebg, BOTTOMRIGHT, -3, -1) - slidervalue:SetTextType(TEXT_TYPE_NUMERIC) - slidervalue:SetFont("ZoFontGameSmall") - slidervalue:SetHandler("OnEscape", function(self) - self:LoseFocus() - control:UpdateValue() - end) - slidervalue:SetHandler("OnEnter", function(self) - self:LoseFocus() - control:UpdateValue(false, tonumber(self:GetText())) - end) - - local range = maxValue - minValue - slider:SetValueStep(sliderData.step or 1) - slider:SetHandler("OnValueChanged", function(self, value, eventReason) - if eventReason == EVENT_REASON_SOFTWARE then return end - self:SetValue(value) --do we actually need this line? - slidervalue:SetText(value) - end) - slider:SetHandler("OnSliderReleased", function(self, value) - --sliderData.setFunc(value) - control:UpdateValue(false, value) --does this work here instead? - end) - - if sliderData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0) - control.warning.tooltipText = sliderData.warning - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = sliderData - - if sliderData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - - return control +--[[sliderData = { + type = "slider", + name = "My Slider", + tooltip = "Slider's tooltip text.", + min = 0, + max = 20, + step = 1, --(optional) + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", --(optional) + default = defaults.var, --(optional) + reference = "MyAddonSlider" --(optional) unique global reference to control +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("slider", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local cm = CALLBACK_MANAGER +local round = zo_round +local strformat = string.format +local tinsert = table.insert + +local function UpdateDisabled(control) + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end + + control.slider:SetEnabled(not disable) + control.slidervalue:SetEditEnabled(not disable) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end +end + +local function UpdateValue(control, forceDefault, value) + if forceDefault then --if we are forcing defaults + value = control.data.default + control.data.setFunc(value) + elseif value and value >= control.data.min and value <= control.data.max then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + if control.panel.data.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + else + value = control.data.getFunc() + end + + control.slider:SetValue(value) + control.slidervalue:SetText(value) +end + + +function LAMCreateControl.slider(parent, sliderData, controlName) + local control = wm:CreateTopLevelWindow(controlName or sliderData.reference) + control:SetParent(parent.scroll) + local isHalfWidth = sliderData.width == "half" + if isHalfWidth then + control:SetDimensions(250, 55) + else + control:SetDimensions(510, 40) + end + control:SetMouseEnabled(true) + control.tooltipText = sliderData.tooltip + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + + control.label = wm:CreateControl(nil, control, CT_LABEL) + local label = control.label + label:SetFont("ZoFontWinH4") + label:SetDimensions(isHalfWidth and 250 or 300, 26) + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetAnchor(isHalfWidth and TOPLEFT or LEFT) + label:SetText(sliderData.name) + + --skipping creating the backdrop... Is this the actual slider texture? + control.slider = wm:CreateControl(nil, control, CT_SLIDER) + local slider = control.slider + slider:SetDimensions(190, 14) + if isHalfWidth then + slider:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT, -5, 2) + else + slider:SetAnchor(RIGHT, control, RIGHT, -5, -5) + end + slider:SetMouseEnabled(true) + slider:SetOrientation(ORIENTATION_HORIZONTAL) + --put nil for highlighted texture file path, and what look to be texture coords + slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16) + local minValue = sliderData.min + local maxValue = sliderData.max + slider:SetMinMax(minValue, maxValue) + slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end) + + slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP) + local bg = slider.bg + bg:SetCenterColor(0, 0, 0) + bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4) + bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4) + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4) + + control.minText = wm:CreateControl(nil, slider, CT_LABEL) + local minText = control.minText + minText:SetFont("ZoFontGameSmall") + minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT) + minText:SetText(sliderData.min) + + control.maxText = wm:CreateControl(nil, slider, CT_LABEL) + local maxText = control.maxText + maxText:SetFont("ZoFontGameSmall") + maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT) + maxText:SetText(sliderData.max) + + control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop") + control.slidervalueBG:SetDimensions(50, 16) + control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0) + control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop") + local slidervalue = control.slidervalue + slidervalue:ClearAnchors() + slidervalue:SetAnchor(TOPLEFT, slidervaluebg, TOPLEFT, 3, 1) + slidervalue:SetAnchor(BOTTOMRIGHT, slidervaluebg, BOTTOMRIGHT, -3, -1) + slidervalue:SetTextType(TEXT_TYPE_NUMERIC) + slidervalue:SetFont("ZoFontGameSmall") + slidervalue:SetHandler("OnEscape", function(self) + self:LoseFocus() + control:UpdateValue() + end) + slidervalue:SetHandler("OnEnter", function(self) + self:LoseFocus() + control:UpdateValue(false, tonumber(self:GetText())) + end) + + local range = maxValue - minValue + slider:SetValueStep(sliderData.step or 1) + slider:SetHandler("OnValueChanged", function(self, value, eventReason) + if eventReason == EVENT_REASON_SOFTWARE then return end + self:SetValue(value) --do we actually need this line? + slidervalue:SetText(value) + end) + slider:SetHandler("OnSliderReleased", function(self, value) + --sliderData.setFunc(value) + control:UpdateValue(false, value) --does this work here instead? + end) + + if sliderData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0) + control.warning.tooltipText = sliderData.warning + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = sliderData + + if sliderData.disabled then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + control.UpdateValue = UpdateValue + control:UpdateValue() + + if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list + tinsert(control.panel.controlsToRefresh, control) + end + + return control end \ No newline at end of file diff --git a/libs/LibAddonMenu-2.0/controls/submenu.lua b/libs/LibAddonMenu-2.0/controls/submenu.lua index b2b399d..fc5a325 100644 --- a/libs/LibAddonMenu-2.0/controls/submenu.lua +++ b/libs/LibAddonMenu-2.0/controls/submenu.lua @@ -1,97 +1,97 @@ ---[[submenuData = { - type = "submenu", - name = "Submenu Title", - tooltip = "My submenu tooltip", --(optional) - controls = {sliderData, buttonData} --(optional) used by LAM - reference = "MyAddonSubmenu" --(optional) unique global reference to control -} ]] - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("submenu", widgetVersion) then return end - -local wm = WINDOW_MANAGER -local am = ANIMATION_MANAGER - - -local function AnimateSubmenu(label) - local control = label:GetParent() - control.open = not control.open - - if control.open then - control.animation:PlayFromStart() - else - control.animation:PlayFromEnd() - end -end - - -function LAMCreateControl.submenu(parent, submenuData, controlName) - local control = wm:CreateTopLevelWindow(controlName or submenuData.reference) - control:SetParent(parent.scroll) - control.panel = parent - control:SetDimensions(523, 40) - - control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local label = control.label - label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5) - label:SetDimensions(520, 30) - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(submenuData.name) - label:SetMouseEnabled(true) - if submenuData.tooltip then - label.tooltipText = submenuData.tooltip - label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - end - - control.scroll = wm:CreateControl(nil, control, CT_SCROLL) - local scroll = control.scroll - scroll:SetParent(control) - scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10) - scroll:SetDimensionConstraints(525, 0, 525, 1500) - - control.bg = wm:CreateControl(nil, label, CT_BACKDROP) - local bg = control.bg - bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5) - bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0) - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) - bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") - bg:SetInsets(16, 16, -16, -16) - - control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE) - local arrow = control.arrow - arrow:SetDimensions(28, 28) - arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way - arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5) - - --figure out the cool animation later... - control.animation = am:CreateTimeline() - local animation = control.animation - animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count - --animation:SetDuration(1) - --animation:SetEasingFunction(ZO_LinearEase) --is this needed? - --animation:SetHeightStartAndEnd(40, 80) --SetStartAndEndHeight - --animation:SetStartAndEndHeight(40, 80) --SetStartAndEndHeight - --animation:SetAnimatedControl(control) - - control:SetResizeToFitDescendents(true) - control.open = false - label:SetHandler("OnMouseUp", AnimateSubmenu) - animation:SetHandler("OnStop", function(self, completedPlaying) - scroll:SetResizeToFitDescendents(control.open) - if control.open then - control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds") - scroll:SetResizeToFitPadding(5, 20) - else - control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") - scroll:SetResizeToFitPadding(5, 0) - scroll:SetHeight(0) - end - end) - - control.data = submenuData - - return control -end - +--[[submenuData = { + type = "submenu", + name = "Submenu Title", + tooltip = "My submenu tooltip", --(optional) + controls = {sliderData, buttonData} --(optional) used by LAM + reference = "MyAddonSubmenu" --(optional) unique global reference to control +} ]] + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("submenu", widgetVersion) then return end + +local wm = WINDOW_MANAGER +local am = ANIMATION_MANAGER + + +local function AnimateSubmenu(label) + local control = label:GetParent() + control.open = not control.open + + if control.open then + control.animation:PlayFromStart() + else + control.animation:PlayFromEnd() + end +end + + +function LAMCreateControl.submenu(parent, submenuData, controlName) + local control = wm:CreateTopLevelWindow(controlName or submenuData.reference) + control:SetParent(parent.scroll) + control.panel = parent + control:SetDimensions(523, 40) + + control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local label = control.label + label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5) + label:SetDimensions(520, 30) + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(submenuData.name) + label:SetMouseEnabled(true) + if submenuData.tooltip then + label.tooltipText = submenuData.tooltip + label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + end + + control.scroll = wm:CreateControl(nil, control, CT_SCROLL) + local scroll = control.scroll + scroll:SetParent(control) + scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10) + scroll:SetDimensionConstraints(525, 0, 525, 1500) + + control.bg = wm:CreateControl(nil, label, CT_BACKDROP) + local bg = control.bg + bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5) + bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0) + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) + bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") + bg:SetInsets(16, 16, -16, -16) + + control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE) + local arrow = control.arrow + arrow:SetDimensions(28, 28) + arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way + arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5) + + --figure out the cool animation later... + control.animation = am:CreateTimeline() + local animation = control.animation + animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count + --animation:SetDuration(1) + --animation:SetEasingFunction(ZO_LinearEase) --is this needed? + --animation:SetHeightStartAndEnd(40, 80) --SetStartAndEndHeight + --animation:SetStartAndEndHeight(40, 80) --SetStartAndEndHeight + --animation:SetAnimatedControl(control) + + control:SetResizeToFitDescendents(true) + control.open = false + label:SetHandler("OnMouseUp", AnimateSubmenu) + animation:SetHandler("OnStop", function(self, completedPlaying) + scroll:SetResizeToFitDescendents(control.open) + if control.open then + control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds") + scroll:SetResizeToFitPadding(5, 20) + else + control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") + scroll:SetResizeToFitPadding(5, 0) + scroll:SetHeight(0) + end + end) + + control.data = submenuData + + return control +end + diff --git a/libs/LibAddonMenu-2.0/controls/texture.lua b/libs/LibAddonMenu-2.0/controls/texture.lua index fc4be69..4729bbc 100644 --- a/libs/LibAddonMenu-2.0/controls/texture.lua +++ b/libs/LibAddonMenu-2.0/controls/texture.lua @@ -1,50 +1,50 @@ ---[[textureData = { - type = "texture", - image = "file/path.dds", - imageWidth = 64, --max of 250 for half width, 510 for full - imageHeight = 32, --max of 100 - tooltip = "Image's tooltip text.", --(optional) - width = "full", --or "half" (optional) - reference = "MyAddonTexture" --(optional) unique global reference to control -} ]] - ---add texture coords support? - -local widgetVersion = 2 -local LAM = LibStub("LibAddonMenu-2.0") -if not LAM:RegisterWidget("texture", widgetVersion) then return end - -local wm = WINDOW_MANAGER - -function LAMCreateControl.texture(parent, textureData, controlName) - local control = wm:CreateTopLevelWindow(controlName or textureData.reference) - control:SetResizeToFitDescendents(true) - control:SetParent(parent.scroll) - - local isHalfWidth = textureData.width == "half" - if isHalfWidth then - control:SetDimensionConstraints(250, 55, 250, 100) - control:SetDimensions(250, 55) - else - control:SetDimensionConstraints(510, 30, 510, 100) - control:SetDimensions(510, 30) - end - - control.texture = wm:CreateControl(nil, control, CT_TEXTURE) - local texture = control.texture - texture:SetAnchor(CENTER) - texture:SetDimensions(textureData.imageWidth, textureData.imageHeight) - texture:SetTexture(textureData.image) - - if textureData.tooltip then - texture:SetMouseEnabled(true) - texture.tooltipText = textureData.tooltip - texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit) - end - - control.panel = parent.panel or parent --if this is in a submenu, panel is its parent - control.data = textureData - - return control +--[[textureData = { + type = "texture", + image = "file/path.dds", + imageWidth = 64, --max of 250 for half width, 510 for full + imageHeight = 32, --max of 100 + tooltip = "Image's tooltip text.", --(optional) + width = "full", --or "half" (optional) + reference = "MyAddonTexture" --(optional) unique global reference to control +} ]] + +--add texture coords support? + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("texture", widgetVersion) then return end + +local wm = WINDOW_MANAGER + +function LAMCreateControl.texture(parent, textureData, controlName) + local control = wm:CreateTopLevelWindow(controlName or textureData.reference) + control:SetResizeToFitDescendents(true) + control:SetParent(parent.scroll) + + local isHalfWidth = textureData.width == "half" + if isHalfWidth then + control:SetDimensionConstraints(250, 55, 250, 100) + control:SetDimensions(250, 55) + else + control:SetDimensionConstraints(510, 30, 510, 100) + control:SetDimensions(510, 30) + end + + control.texture = wm:CreateControl(nil, control, CT_TEXTURE) + local texture = control.texture + texture:SetAnchor(CENTER) + texture:SetDimensions(textureData.imageWidth, textureData.imageHeight) + texture:SetTexture(textureData.image) + + if textureData.tooltip then + texture:SetMouseEnabled(true) + texture.tooltipText = textureData.tooltip + texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit) + end + + control.panel = parent.panel or parent --if this is in a submenu, panel is its parent + control.data = textureData + + return control end \ No newline at end of file