Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Formats for Name Text #39

Merged
merged 11 commits into from
Aug 30, 2024
1 change: 1 addition & 0 deletions Cell_UnitFrames.toc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

Locales/LoadLocales.xml
Core/Init.lua
Core/Events.lua

Data/Constants.lua
Data/Defaults.lua
Expand Down
67 changes: 67 additions & 0 deletions Core/Events.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---@class CUF
local CUF = select(2, ...)

-------------------------------------------------
-- MARK: Callbacks
-------------------------------------------------

---@alias Callbacks
---| "UpdateMenu"
---| "UpdateWidget"
---| "LoadPageDB"
---| "UpdateVisibility"
---| "UpdateUnitButtons"
---| "UpdateLayout"
---| "ShowOptionsTab"
---| "UpdatePixelPerfect"
---| "UpdateAppearance"
---| "AddonLoaded"
local callbacks = {}

---@param eventName Callbacks
---@param onEventFuncName string
---@param onEventFunc function
function CUF:RegisterCallback(eventName, onEventFuncName, onEventFunc)
if not callbacks[eventName] then callbacks[eventName] = {} end
callbacks[eventName][onEventFuncName] = onEventFunc
end

---@param eventName Callbacks
---@param onEventFuncName string
function CUF:UnregisterCallback(eventName, onEventFuncName)
if not callbacks[eventName] then return end
callbacks[eventName][onEventFuncName] = nil
end

---@param eventName Callbacks
function CUF:UnregisterAllCallbacks(eventName)
if not callbacks[eventName] then return end
callbacks[eventName] = nil
end

---@param eventName Callbacks
---@param ... any
function CUF:Fire(eventName, ...)
if not callbacks[eventName] then return end

for onEventFuncName, onEventFunc in pairs(callbacks[eventName]) do
onEventFunc(...)
end
end

-- Borrowed from XephCD
---@param event WowEvent
---@param callback fun(ownerId: number, ...: any): boolean
---@return number
function CUF:AddEventListener(event, callback)
local function wrappedFn(...)
local unregister = callback(...)

if unregister then
local id = select(1, ...)
EventRegistry:UnregisterFrameEventAndCallback(event, id)
end
end

return EventRegistry:RegisterFrameEventAndCallback(event, wrappedFn)
end
2 changes: 2 additions & 0 deletions Core/OnLoad.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ local function OnAddonLoaded(owner, loadedAddonName)

Cell:RegisterCallback("UpdateLayout", "CUF_Initial_UpdateLayout", OnCellInitialUpdateLayout)

CUF:Fire("AddonLoaded")

return true
end

Expand Down
21 changes: 20 additions & 1 deletion Data/Constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ local CUF = select(2, ...)
---@class CUF.constants
local const = CUF.constants

local Util = CUF.Util

--- Called when the addon is loaded
---
--- Used for initializing constants that require Util functions
local function OnAddonLoaded()
const.NameFormatArray = Util.DictionaryToArray(const.NameFormat)
end

CUF:RegisterCallback("AddonLoaded", "CUF_Constants_OnAddonLoaded", OnAddonLoaded)

---@enum Unit
const.UNIT = {
PLAYER = "player",
Expand All @@ -13,7 +24,6 @@ const.UNIT = {
TARGET_TARGET = "targettarget",
}


---@enum TitleCasedUnits
-- Used for frame titles
const.TITLE_CASED_UNITS = {
Expand Down Expand Up @@ -212,3 +222,12 @@ const.CastBarTimerFormat = {
DURATION = "duration",
DURATION_AND_MAX = "duration-and-max",
}

---@enum NameFormat
const.NameFormat = {
FULL_NAME = "fullName",
LAST_NAME = "lastName",
FIRST_NAME = "firstName",
FIRST_NAME_LAST_INITIAL = "firstNameLastInitial",
FIRST_INITIAL_LAST_NAME = "firstInitialLastName",
}
1 change: 1 addition & 0 deletions Data/Defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Defaults.Widgets = {
offsetX = 2,
relativePoint = "CENTER",
},
format = CUF.constants.NameFormat.FULL_NAME,
},
---@type HealthTextWidgetTable
healthText = {
Expand Down
15 changes: 15 additions & 0 deletions Locales/enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ L.Zoom = "Zoom"
L.UseFullyChargedTooltip = "Use fully charged color for the final stage"
L.ShowEmpowerNameTooltip = "Show the spell name for Empowers"

-- Name Format
L.NameFormats = "Name Formats"

L.fullName = "Full Name"
L.lastName = "Last Name"
L.firstName = "First Name"
L.firstNameLastInitial = "First Name Last Initial"
L.firstInitialLastName = "First Initial Last Name"

L.fullName_Example = "Cleave Training Dummy"
L.lastName_Example = "Dummy"
L.firstName_Example = "Cleave"
L.firstNameLastInitial_Example = "Cleave D."
L.firstInitialLastName_Example = "C. Dummy"

-- Widgets
L.Widgets = "Widgets"
L.nameText = "Name Text"
Expand Down
30 changes: 30 additions & 0 deletions Menu/Builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Builder.MenuOptions = {
CastBarEmpower = 26,
CastBarBorder = 27,
CastBarIcon = 28,
NameFormat = 29,
}

-------------------------------------------------
Expand Down Expand Up @@ -929,6 +930,34 @@ function Builder:CreatePowerFormatOptions(parent, widgetName)
return f
end

-------------------------------------------------
-- MARK: Name Format
-------------------------------------------------

---@param parent Frame
---@param widgetName WIDGET_KIND
---@return NameFormatOptions
function Builder:CreateNameFormatOptions(parent, widgetName)
---@class NameFormatOptions: OptionsFrame
local f = CUF:CreateFrame(nil, parent, 1, 1, true, true)
f.optionHeight = 20
f.id = "NameFormatOptions"

local tooltips = {}
for _, format in ipairs(const.NameFormatArray) do
local tooltip = L[format] .. ": " .. L[format .. "_Example"]
table.insert(tooltips, tooltip)
end

f.formatDropdown = self:CreateDropdown(f, widgetName, "Format", 200, const.NameFormatArray,
const.OPTION_KIND.FORMAT)
f.formatDropdown:SetPoint("TOPLEFT", f)

Cell:SetTooltips(f.formatDropdown, "ANCHOR_TOPLEFT", 0, 3, L.NameFormats, unpack(tooltips))

return f
end

-------------------------------------------------
-- MARK: Size
-------------------------------------------------
Expand Down Expand Up @@ -1573,6 +1602,7 @@ Builder.MenuFuncs = {
[Builder.MenuOptions.Font] = Builder.CreateFontOptions,
[Builder.MenuOptions.HealthFormat] = Builder.CreateHealthFormatOptions,
[Builder.MenuOptions.PowerFormat] = Builder.CreatePowerFormatOptions,
[Builder.MenuOptions.NameFormat] = Builder.CreateNameFormatOptions,
[Builder.MenuOptions.AuraIconOptions] = Builder.CreateAuraIconOptions,
[Builder.MenuOptions.Orientation] = Builder.CreateOrientationOptions,
[Builder.MenuOptions.AuraStackFontOptions] = Builder.CreateAuraStackFontOptions,
Expand Down
96 changes: 39 additions & 57 deletions Util/Utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@ function Util:GetUnitClassColor(unit, class, guid)
return unpack(CUF.constants.COLORS.NEUTRAL)
end

--- Converts a dictionary table to an array eg.
---
--- { ["key"] = "value", ["key2"] = "value2" }
---
--- becomes { "value", "value2" }
---@param dictionary table
---@return table array
function Util.DictionaryToArray(dictionary)
local array = {}
for _, value in pairs(dictionary) do
table.insert(array, value)
end
return array
end

-------------------------------------------------
-- MARK: Frames
-------------------------------------------------
Expand Down Expand Up @@ -337,68 +352,35 @@ function Util:trim(string)
return string:match '^()%s*$' and '' or string:match '^%s*(.*%S)'
end

-------------------------------------------------
-- MARK: Callbacks
-------------------------------------------------

---@alias Callbacks
---| "UpdateMenu"
---| "UpdateWidget"
---| "LoadPageDB"
---| "UpdateVisibility"
---| "UpdateUnitButtons"
---| "UpdateLayout"
---| "ShowOptionsTab"
---| "UpdatePixelPerfect"
---| "UpdateAppearance"
local callbacks = {}

---@param eventName Callbacks
---@param onEventFuncName string
---@param onEventFunc function
function CUF:RegisterCallback(eventName, onEventFuncName, onEventFunc)
if not callbacks[eventName] then callbacks[eventName] = {} end
callbacks[eventName][onEventFuncName] = onEventFunc
end

---@param eventName Callbacks
---@param onEventFuncName string
function CUF:UnregisterCallback(eventName, onEventFuncName)
if not callbacks[eventName] then return end
callbacks[eventName][onEventFuncName] = nil
end
--- Splits a full name string into the specified format.
--- @param fullName string The full name (e.g., "Lars Erik Olsen Larsen")
--- @param format NameFormat
--- @return string
function Util.FormatName(fullName, format)
if not fullName then return "Unknown" end

---@param eventName Callbacks
function CUF:UnregisterAllCallbacks(eventName)
if not callbacks[eventName] then return end
callbacks[eventName] = nil
end

---@param eventName Callbacks
---@param ... any
function CUF:Fire(eventName, ...)
if not callbacks[eventName] then return end

for onEventFuncName, onEventFunc in pairs(callbacks[eventName]) do
onEventFunc(...)
local nameParts = {}
for name in fullName:gmatch("%S+") do
table.insert(nameParts, name)
end
end

-- Borrowed from XephCD
---@param event WowEvent
---@param callback fun(ownerId: number, ...: any): boolean
---@return number
function CUF:AddEventListener(event, callback)
local function wrappedFn(...)
local unregister = callback(...)

if unregister then
local id = select(1, ...)
EventRegistry:UnregisterFrameEventAndCallback(event, id)
end
local firstName = nameParts[1] or ""
local lastName = nameParts[#nameParts] or ""
if lastName == "" then return fullName end

if format == CUF.constants.NameFormat.FULL_NAME then
return fullName
elseif format == CUF.constants.NameFormat.LAST_NAME then
return lastName
elseif format == CUF.constants.NameFormat.FIRST_NAME then
return firstName
elseif format == CUF.constants.NameFormat.FIRST_NAME_LAST_INITIAL then
return string.format("%s %s.", firstName, lastName:sub(1, 1))
elseif format == CUF.constants.NameFormat.FIRST_INITIAL_LAST_NAME then
return string.format("%s. %s", firstName:sub(1, 1), lastName)
end

return EventRegistry:RegisterFrameEventAndCallback(event, wrappedFn)
return fullName
end

-------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions WidgetAnnotations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
---@field color ColorOpt
---@field width FontWidthOpt
---@field position PositionOpt
---@field format NameFormat

---@class HealthTextWidgetTable
---@field enabled boolean
Expand Down
17 changes: 15 additions & 2 deletions Widgets/Texts/NameText.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ end
menu:AddWidget(const.WIDGET_KIND.NAME_TEXT,
Builder.MenuOptions.TextColor,
Builder.MenuOptions.TextWidth,
Builder.MenuOptions.NameFormat,
Builder.MenuOptions.Anchor,
Builder.MenuOptions.Font,
Builder.MenuOptions.FrameLevel)
Expand All @@ -38,9 +39,13 @@ menu:AddWidget(const.WIDGET_KIND.NAME_TEXT,
---@param subSetting string
function W.UpdateNameTextWidget(button, unit, setting, subSetting)
local widget = button.widgets.nameText
local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.NAME_TEXT, unit) --[[@as NameTextWidgetTable]]

if not setting or setting == const.OPTION_KIND.WIDTH then
widget.width = DB.GetWidgetTable(const.WIDGET_KIND.NAME_TEXT, unit).width
widget.width = styleTable.width
end
if not setting or setting == const.OPTION_KIND.FORMAT then
widget.format = styleTable.format
end

widget.Update(button)
Expand Down Expand Up @@ -93,6 +98,7 @@ function W:CreateNameText(button)
button.widgets.nameText = nameText

nameText.width = CUF.Defaults.Options.fontWidth
nameText.format = CUF.Defaults.Widgets.nameText.format

function nameText:UpdateName()
local name
Expand All @@ -102,12 +108,19 @@ function W:CreateNameText(button)
end
name = name or F:GetNickname(button.states.name, button.states.fullName)

Util.UpdateTextWidth(nameText.text, name, nameText.width, button)
if self.format ~= CUF.constants.NameFormat.FULL_NAME then
name = self.FormatName(name, self.format)
end

self.UpdateTextWidth(nameText.text, name, nameText.width, button)
end

nameText.Update = Update
nameText.Enable = Enable
nameText.Disable = Disable

nameText.FormatName = Util.FormatName
nameText.UpdateTextWidth = Util.UpdateTextWidth
end

W:RegisterCreateWidgetFunc(const.WIDGET_KIND.NAME_TEXT, W.CreateNameText)