-- Library of common/shared methods local Grid2 = Grid2 local Grid2Options = Grid2Options local L = Grid2Options.L -- Default values for new or morphed indicators Grid2Options.indicatorDefaultValues = { icon = {size = 16, fontSize = 8}, square = {size = 5}, shape = {size = 5}, text = {duration = true, stack = false, textlength = 12, fontSize = 8, font = "Friz Quadrata TT"} } -- Grid2Options:MakeIndicatorCurrentStatusOptions() -- Grid2Options:MakeIndicatorStatusOptions() -- Grid2Options:MakeStatusIndicatorOptions() do local function GetIndexOfValue(map, status) for i, s in ipairs(map) do if s == status then return i end end end local function GetIndicatorNewPriority(indicator) local priority = 50 local map = Grid2:DbGetValue("statusMap", indicator.name) if map then for _, p in pairs(map) do p = tonumber(p) if p and p >= priority then priority = p + 1 end end end return priority end local function RegisterIndicatorStatus(indicator, status, value) if value then local priority = GetIndicatorNewPriority(indicator) Grid2:DbSetMap(indicator.name, status.name, priority) indicator:RegisterStatus(status, priority) status:Refresh() else Grid2:DbSetMap(indicator.name, status.name, nil) indicator:UnregisterStatus(status) end Grid2Options:RefreshIndicator(indicator, "Layout") end local function RefreshIndicatorCurrentStatusOptions(info) wipe(info.arg.options) Grid2Options:MakeIndicatorCurrentStatusOptions(info.arg.indicator, info.arg.options) end local function SetIndicatorStatus(info, statusKey, value) for key, status in Grid2:IterateStatuses() do if key == statusKey then RegisterIndicatorStatus(info.arg.indicator, status, value) RefreshIndicatorCurrentStatusOptions(info) return end end end local function SetIndicatorStatusCurrent(info, value) SetIndicatorStatus(info, info[#info], value) end local function SetStatusPriority(info, map, indicator, status, priority, index) Grid2:DbSetMap(indicator.name, status.name, priority) indicator:SetStatusPriority(status, priority) map[index], map[status] = status, priority local key, opt = status.name, info.arg.options opt[key].order = 500 - priority opt[key .. "U"].order = 500.1 - priority opt[key .. "D"].order = 500.2 - priority opt[key .. "S"].order = 500.3 - priority end local function StatusSwapPriorities(info, map, indicator, index1, index2) local status1 = map[index1] local status2 = map[index2] local priority1 = map[status1] local priority2 = map[status2] SetStatusPriority(info, map, indicator, status1, priority2, index2) SetStatusPriority(info, map, indicator, status2, priority1, index1) end local function StatusShiftUp(info, map, indicator, lowerStatus) local index = GetIndexOfValue(map, lowerStatus) if index then local newIndex = index > 1 and index - 1 or #map StatusSwapPriorities(info, map, indicator, index, newIndex) Grid2Options:RefreshIndicator(indicator, "Layout") end end local function StatusShiftDown(info, map, indicator, higherStatus) local index = GetIndexOfValue(map, higherStatus) if index then local newIndex = index < #map and index + 1 or 1 StatusSwapPriorities(info, map, indicator, index, newIndex) Grid2Options:RefreshIndicator(indicator, "Layout") end end local function LoadStatusMap(indicator) local map = {} local dbx = Grid2:DbGetValue("statusMap", indicator.name) if dbx then for statusKey, priority in pairs(dbx) do local status = Grid2:GetStatusByName(statusKey) if status then map[#map + 1] = status map[status] = priority end end end table.sort( map, function(a, b) return map[a] > map[b] end ) return map end -- Grid2Options:MakeIndicatorCurrentStatusOptions(indicator, options) function Grid2Options:MakeIndicatorCurrentStatusOptions(indicator, options) if indicator.statuses then local map = LoadStatusMap(indicator) local hide = #map <= 1 or nil local arg = {indicator = indicator, options = options} for _, status in ipairs(map) do local priority = map[status] options[status.name] = { type = "toggle", order = 500 - map[status], width = "double", name = Grid2Options.LocalizeStatus(status), desc = L["Select statuses to display with the indicator"], get = function() return true end, set = SetIndicatorStatusCurrent, arg = arg } options[status.name .. "U"] = { type = "execute", order = 500.1 - map[status], width = "half", image = "Interface\\Addons\\Grid2Options\\media\\arrow-up", imageWidth = 16, imageHeight = 14, name = "", desc = L["Move the status higher in priority"], func = function(info) StatusShiftUp(info, map, indicator, status) end, arg = arg, hidden = hide } options[status.name .. "D"] = { type = "execute", order = 500.2 - map[status], width = "half", image = "Interface\\Addons\\Grid2Options\\media\\arrow-down", imageWidth = 16, imageHeight = 14, name = "", desc = L["Move the status lower in priority"], func = function(info) StatusShiftDown(info, map, indicator, status) end, arg = arg, hidden = hide } options[status.name .. "S"] = { type = "description", name = "", order = 500.3 - map[status], hidden = hide } end end end -- Grid2Options:MakeIndicatorStatusOptions() function Grid2Options:MakeIndicatorStatusOptions(indicator, options) local curOptions = {} self:MakeIndicatorCurrentStatusOptions(indicator, curOptions) options.statusesCurrent = { type = "group", order = 100, inline = true, name = L["Current Statuses"], desc = L["Current statuses in order of priority"], args = curOptions } options.statusesAvailable = { type = "multiselect", order = 200, name = L["Available Statuses"], desc = L["Available statuses you may add"], values = function() return self:GetAvailableStatusValues(indicator) end, get = false, set = SetIndicatorStatus, arg = {indicator = indicator, options = curOptions} } end -- Grid2Options:MakeStatusIndicatorOptions() function Grid2Options:MakeStatusIndicatorsOptions(status, options) options.indicators = { type = "multiselect", order = 10, name = L["Assigned indicators"], values = function() return self:GetAvailableIndicatorValues(status) end, get = function(info, key) local dbx = Grid2:DbGetValue("statusMap", key) return dbx and dbx[status.name] ~= nil end, set = function(info, key, value) local indicator = Grid2.indicators[key] if indicator.dbx.type ~= "multibar" then RegisterIndicatorStatus(indicator, status, value) self:RefreshIndicatorOptions(indicator) end end, confirm = function(info, key) return Grid2.indicators[key].dbx.type == "multibar" and L["This indicator cannot be changed from here: go to indicators section to assign/unassign statuses to this indicator."] end } return options end end -- Grid2Options:MakeIndicatorDeleteOptions() do local function DeleteIndicator(info) local indicator = info.arg Grid2Frame:WithAllFrames(indicator, "Disable") Grid2:DbSetIndicator(indicator.name, nil) if indicator.dbx.sideKick then Grid2:DbSetIndicator(indicator.dbx.sideKick.name, nil) end Grid2:UnregisterIndicator(indicator) Grid2Frame:UpdateIndicators() Grid2Options:DeleteIndicatorOptions(indicator) end local function Disabled(info) local indicator = info.arg return #indicator.statuses > 0 or (indicator.sideKick and #indicator.sideKick.statuses > 0) end function Grid2Options:MakeIndicatorDeleteOptions(indicator, options) self:MakeHeaderOptions(options, "Delete") options.delete = { type = "execute", order = 255, width = "half", name = L["Delete"], desc = L["Delete this element"], confirm = function() return L["Are you sure you want to delete this indicator?"] end, func = DeleteIndicator, arg = indicator, disabled = Disabled } options.deletemsg = { type = "description", name = L["There are status linked to this indicator."], fontSize = "small", order = 265, width = "double", hidden = function() return next(indicator.statuses) == nil end } end end -- Grid2Options:MakeIndicatorSizeOptions() function Grid2Options:MakeIndicatorSizeOptions(indicator, options, optionParams) options.size = { type = "range", order = 10, name = L["Size"], desc = L["Adjust the size of the indicator."], min = 5, max = 50, step = 1, get = function() return indicator.dbx.size end, set = function(_, v) indicator.dbx.size = v self:RefreshIndicator(indicator, "Layout") end } end -- Grid2Options:MakeIndicatorBorderSizeOptions() function Grid2Options:MakeIndicatorBorderSizeOptions(indicator, options, optionParams) options.borderSize = { type = "range", order = 20, name = L["Border Size"], desc = L["Adjust the border size of the indicator."], min = 0, max = 20, step = 1, get = function() return indicator.dbx.borderSize or 0 end, set = function(_, v) if v == 0 then v = nil end indicator.dbx.borderSize = v self:RefreshIndicator(indicator, "Layout", "Update") end } end -- Grid2Options:MakeIndicatorTextureOptions() function Grid2Options:MakeIndicatorTextureOptions(indicator, options, optionParams) options.texture = { type = "select", dialogControl = "LSM30_Statusbar", order = 11, name = L["Frame Texture"], desc = L["Adjust the texture of the indicator."], get = function(info) return indicator.dbx.texture or "Grid2 Flat" end, set = function(info, v) indicator.dbx.texture = v self:RefreshIndicator(indicator, "Layout") end, values = AceGUIWidgetLSMlists.statusbar } end -- Grid2Options:MakeIndicatorBorderOptions() function Grid2Options:MakeIndicatorBorderOptions(indicator, options, optionParams) optionParams = optionParams or {} optionParams.color1 = L["Border Color"] optionParams.colorDesc1 = L["Adjust border color and alpha."] self:MakeHeaderOptions(options, "Border") self:MakeIndicatorColorOptions(indicator, options, optionParams) self:MakeIndicatorBorderSizeOptions(indicator, options, optionParams) end -- Grid2Options:MakeIndicatorColorOptions() do local function GetIndicatorColor(info) local indicator = info.arg.indicator local colorKey = "color" .. info.arg.colorIndex local c = indicator.dbx[colorKey] if c then return c.r, c.g, c.b, c.a end return 0, 0, 0, 0 end local function SetIndicatorColor(info, r, g, b, a) local colorKey = "color" .. info.arg.colorIndex local indicator = info.arg.indicator local dbx = indicator.dbx local c = dbx[colorKey] if not c then c = {} dbx[colorKey] = c end c.r, c.g, c.b, c.a = r, g, b, a if indicator.UpdateDB then indicator:UpdateDB() end Grid2Frame:UpdateIndicators() end function Grid2Options:MakeIndicatorColorOptions(indicator, options, optionParams) local colorCount = indicator.dbx.colorCount or 1 local name = L["Color"] local desc = L["Color for %s."]:format(indicator.name) for i = 1, colorCount, 1 do local colorKey = "color" .. i if (optionParams and optionParams[colorKey]) then name = optionParams[colorKey] elseif (colorCount > 1) then name = L["Color %d"]:format(i) end local colorDescKey = "colorDesc" .. i if (optionParams and optionParams[colorDescKey]) then desc = optionParams[colorDescKey] elseif (colorCount > 1) then desc = name end options[colorKey] = { type = "color", order = (20 + i), name = name, desc = desc, get = GetIndicatorColor, set = SetIndicatorColor, hasAlpha = true, arg = {indicator = indicator, colorIndex = i} } end end end -- Grid2Options:MakeIndicatorTypeOptions() do local typeMorphValue = {} local typeMorphValues = {icon = L["icon"], square = L["square"], text = L["text"]} local function RegisterIndicatorStatusesFromDatabase(indicator) if indicator then local map = Grid2:DbGetValue("statusMap", indicator.name) if map then for statusKey, priority in pairs(map) do local status = Grid2.statuses[statusKey] if (status and tonumber(priority)) then indicator:RegisterStatus(status, priority) end end end end end local function GetIndicatorTypeValues(info) local typeKey = info.arg.dbx.type if not typeMorphValues[typeKey] then wipe(typeMorphValue) typeMorphValue[typeKey] = L[typeKey] return typeMorphValue end return typeMorphValues end local function GetIndicatorTypeDisabled(info) return not typeMorphValues[info.arg.dbx.type] end local function GetIndicatorType(info) return info.arg.dbx.type end local function SetIndicatorType(info, value) local indicator = info.arg local baseKey = indicator.name local dbx = indicator.dbx local colorKey = baseKey .. "-color" local oldType = dbx.type if dbx.type == value then return end -- Set new fields width defaults values dbx.type = value for k, v in pairs(Grid2Options.indicatorDefaultValues[value]) do if (not dbx[k]) then indicator.dbx[k] = v dbx[k] = v end end -- Remove old indicator Grid2:UnregisterIndicator(indicator) -- Create new indicator local setupFunc = Grid2.setupFunc[dbx.type] local newIndicator = setupFunc(baseKey, dbx) -- Remove incompatible statuses from database local map = Grid2:DbGetValue("statusMap", baseKey) if map then for statusKey, priority in pairs(map) do local status = Grid2.statuses[statusKey] if (not status) or (not Grid2Options:IsCompatiblePair(newIndicator, status)) then map[statusKey] = nil end end end -- Register indicator statuses from database RegisterIndicatorStatusesFromDatabase(newIndicator) RegisterIndicatorStatusesFromDatabase(newIndicator.sideKick) -- Recreate indicators in frame units Grid2Frame:WithAllFrames(function(f) newIndicator:Create(f) newIndicator:Layout(f) end) -- Delete or Create associated text-color indicator in database if oldType == "text" then Grid2:DbSetIndicator(colorKey, nil) elseif value == "text" then Grid2:DbSetIndicator(colorKey, {type = "text-color"}) end -- Update unit frames Grid2Frame:UpdateIndicators() -- Create new indicator options Grid2Options:MakeIndicatorOptions(newIndicator) end function Grid2Options:MakeIndicatorTypeOptions(indicator, options, optionParams) options.indicatorType = { type = "select", order = 1.91, name = L["Type of indicator"], desc = L["Change the indicator type"], values = GetIndicatorTypeValues, get = GetIndicatorType, set = SetIndicatorType, confirm = true, confirmText = L["Are you sure do you want to convert the indicator to the new selected type?"], arg = indicator } end end -- Grid2Options:MakeIndicatorLevelOptions() do local levelValues = {1, 2, 3, 4, 5, 6, 7, 8, 9} function Grid2Options:MakeIndicatorLevelOptions(indicator, options) options.frameLevel = { type = "select", order = 6, name = L["Frame Level"], desc = L["Bars with higher numbers always show up on top of lower numbers."], get = function() return indicator.dbx.level or 1 end, set = function(_, v) indicator.dbx.level = v self:RefreshIndicator(indicator, "Layout") end, values = levelValues } end end -- Grid2Options:MakeIndicatorTypeLevelOptions() function Grid2Options:MakeIndicatorTypeLevelOptions(indicator, options) self:MakeHeaderOptions(options, "General") self:MakeIndicatorTypeOptions(indicator, options) self:MakeIndicatorLevelOptions(indicator, options) end -- Grid2Options:MakeIndicatorLocationOptions() function Grid2Options:MakeIndicatorLocationOptions(indicator, options) local location = indicator.dbx.location self:MakeHeaderOptions(options, "Location") options.relPoint = { type = "select", order = 4, name = L["Location"], desc = L["Align my align point relative to"], values = self.pointValueList, get = function() return self.pointMap[location.relPoint] end, set = function(_, v) location.relPoint = self.pointMap[v] location.point = location.relPoint self:RefreshIndicator(indicator, "Layout") end } options.point = { type = "select", order = 5, name = L["Align Point"], desc = L["Align this point on the indicator"], values = self.pointValueList, get = function() return self.pointMap[location.point] end, set = function(_, v) location.point = self.pointMap[v] self:RefreshIndicator(indicator, "Layout") end } options.x = { type = "range", order = 7, name = L["X Offset"], desc = L["X - Horizontal Offset"], min = -50, max = 50, step = 1, bigStep = 1, get = function() return location.x end, set = function(_, v) location.x = v self:RefreshIndicator(indicator, "Layout") end } options.y = { type = "range", order = 8, name = L["Y Offset"], desc = L["Y - Vertical Offset"], min = -50, max = 50, step = 1, bigStep = 1, get = function() return location.y end, set = function(_, v) location.y = v self:RefreshIndicator(indicator, "Layout") end } self:MakeIndicatorLevelOptions(indicator, options) end -- Grid2Options:MakeIndicatorAnimationOptions() function Grid2Options:MakeIndicatorAnimationOptions(indicator, options) self:MakeHeaderOptions(options, "Animation") options.animEnabled = { type = "toggle", order = 155, name = L["Enable animation"], desc = L["Turn on/off zoom animation of icons."], tristate = false, get = function() return indicator.dbx.animEnabled end, set = function(_, v) indicator.dbx.animEnabled = v or nil if not v then indicator.dbx.animScale = nil indicator.dbx.animDuration = nil indicator.dbx.animOrigin = nil end indicator:UpdateDB() end } options.animOnEnabled = { type = "toggle", order = 157, name = L["Only on Activation"], desc = L["Start the animation only when the indicator is activated, not on updates."], tristate = false, get = function() return indicator.dbx.animOnEnabled end, set = function(_, v) indicator.dbx.animOnEnabled = v or nil indicator:UpdateDB() end, hidden = function() return not indicator.dbx.animEnabled end } options.animDuration = { type = "range", order = 160, name = L["Duration"], desc = L["Sets the duration in seconds."], min = 0.1, max = 2, step = 0.1, get = function() return indicator.dbx.animDuration or 0.7 end, set = function(_, v) indicator.dbx.animDuration = v Grid2Frame:WithAllFrames(function(f) local anim = indicator:GetBlinkFrame(f).scaleAnim if anim then anim.grow:SetDuration(v / 2) anim.shrink:SetDuration(v / 2) end end) end, hidden = function() return not indicator.dbx.animEnabled end } options.animScale = { type = "range", order = 164, name = L["Scale"], desc = L["Sets the zoom factor."], min = 1.1, max = 3, step = 0.1, get = function() return indicator.dbx.animScale or 1.5 end, set = function(_, v) indicator.dbx.animScale = v Grid2Frame:WithAllFrames(function(f) local anim = indicator:GetBlinkFrame(f).scaleAnim if anim then anim.grow:SetScale(v, v) anim.shrink:SetScale(1 / v, 1 / v) end end) end, hidden = function() return not indicator.dbx.animEnabled end } options.animOrigin = { type = "select", order = 165, name = L["Origin"], desc = L["Zoom origin point"], values = self.pointValueList, get = function() return self.pointMap[indicator.dbx.animOrigin or "CENTER"] end, set = function(_, v) local point = self.pointMap[v] indicator.dbx.animOrigin = point ~= "CENTER" and point or nil Grid2Frame:WithAllFrames(function(f) local anim = indicator:GetBlinkFrame(f).scaleAnim if anim then anim.grow:SetOrigin(point, 0, 0) anim.shrink:SetOrigin(point, 0, 0) end end) end, hidden = function() return not indicator.dbx.animEnabled end } end