---@diagnostic disable: duplicate-set-field --[[ -- ************************************************************************** -- * TitanClock.lua -- * -- * By: The Titan Panel Development Team -- ************************************************************************** --]] -- ******************************** Constants ******************************* TITAN_CLOCK_ID = "Clock"; local TITAN_BUTTON = "TitanPanel" .. TITAN_CLOCK_ID .. "Button" local TITAN_CLOCK_FORMAT_12H = "12H"; local TITAN_CLOCK_FORMAT_24H = "24H"; local TITAN_CLOCK_FRAME_SHOW_TIME = 0.5; local _G = getfenv(0); -- ******************************** Variables ******************************* local AceTimer = LibStub("AceTimer-3.0") local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true) local ClockTimer = {} local ClockTimerRunning = false local updateTable = { TITAN_CLOCK_ID, TITAN_PANEL_UPDATE_ALL }; local realmName = GetRealmName(); -- ******************************** Functions ******************************* local function SetColor(text) local label = ""; if (TitanGetVar(TITAN_CLOCK_ID, "ShowColoredText")) then label = TitanUtils_GetGreenText(text) else label = TitanUtils_GetHighlightText(text) end return label; end ---@param displaytype string Server | Local ---@param offset number User selected offset ---@return nil ---@return string formatted_time local function FormatTime(displaytype, offset) -- Calculate the hour/minutes considering the offset local hour, minute = GetGameTime(); local twentyfour = ""; local offsettime = string.format("%s", offset); local offsethour = 0; local hour_str = "" local offsetmin = 0; local min_str = "" local s, e, id = string.find(offsettime, '%.5'); if displaytype == "Server" then if (s ~= nil) then hour_str = string.sub(offsettime, 1, s); min_str = string.sub(offsettime, s + 1); if min_str == "" or min_str == nil then min_str = "0"; end if hour_str == "" or hour_str == nil then hour_str = "0"; end offsethour = tonumber(hour_str); if (tonumber(offsettime) < 0) then offsetmin = tonumber("-" .. min_str); end minute = minute + (offsetmin * 6); if (minute > 59) then minute = minute - 60; offsethour = offsethour + 1; elseif (minute < 0) then minute = 60 + minute; offsethour = offsethour - 1; end else offsethour = offset; end else -- no offset for local time hour, minute = tonumber(date("%H")), tonumber(date("%M")); offsethour = 0; end hour = hour + offsethour; if (hour > 23) then hour = hour - 24; elseif (hour < 0) then hour = 24 + hour; end -- Calculate the display text based on format 12H/24H if (TitanGetVar(TITAN_CLOCK_ID, "Format") == TITAN_CLOCK_FORMAT_12H) then local isAM; if (hour >= 12) then isAM = false; hour = hour - 12; else isAM = true; end if (hour == 0) then hour = 12; end if (isAM) then return nil, format(TIME_TWELVEHOURAM, hour, minute); else return nil, format(TIME_TWELVEHOURPM, hour, minute); end else twentyfour = format(TIME_TWENTYFOURHOURS, hour, minute); if (hour < 10) then twentyfour = "0" .. twentyfour end return nil, twentyfour; end end --- local Display time on button based on user settings local function GetButtonText() local clocktime = ""; local labeltext = ""; local clocktime2 = nil; local labeltext2 = nil; local _ = nil if TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "Server" then _, clocktime = FormatTime("Server", 0) labeltext = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(S) ") or "" elseif TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerAdjusted" then _, clocktime = FormatTime("Server", TitanGetVar(TITAN_CLOCK_ID, "OffsetHour")) labeltext = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(A) ") or "" elseif TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "Local" then _, clocktime = FormatTime("Local", 0) labeltext = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(L) ") or "" elseif TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerLocal" then local _, s = FormatTime("Server", 0) local _, l = FormatTime("Local", 0) local sl = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(S) ") or "" local ll = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(L) ") or "" clocktime = s labeltext = sl clocktime2 = l labeltext2 = ll elseif TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerAdjustedLocal" then local _, s = FormatTime("Server", TitanGetVar(TITAN_CLOCK_ID, "OffsetHour")) local _, l = FormatTime("Local", 0) local sl = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(A) ") or "" local ll = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(L) ") or "" clocktime = s labeltext = sl clocktime2 = l labeltext2 = ll elseif TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "Local" then _, clocktime = FormatTime("Local", 0) labeltext = TitanGetVar(TITAN_CLOCK_ID, "ShowLabelText") and SetColor("(L) ") or "" end return labeltext, clocktime, labeltext2, clocktime2 end ---@param offset number User selected offset ---@return string formatted_offset local function GetOffsetText(offset) if (offset > 0) then return TitanUtils_GetGreenText("+" .. tostring(offset)); elseif (offset < 0) then return TitanUtils_GetRedText(tostring(offset)); else return TitanUtils_GetHighlightText(tostring(offset)); end end ---local Return the tool tip text based on user settings ---@return string formatted_text local function GetTooltipText() local _, clockTimeLocal = FormatTime("Local", 0) local _, clockTimeServer = FormatTime("Server", 0) local _, clockTimeServerAdjusted = FormatTime("Server", TitanGetVar(TITAN_CLOCK_ID, "OffsetHour")) local clockTimeLocalLabel = L["TITAN_CLOCK_TOOLTIP_LOCAL_TIME"] .. "\t" .. TitanUtils_GetHighlightText(clockTimeLocal) local clockTimeServerLabel = L["TITAN_CLOCK_TOOLTIP_SERVER_TIME"] .. "\t" .. TitanUtils_GetHighlightText(clockTimeServer) local clockTimeServerAdjustedLabel = ""; if TitanGetVar(TITAN_CLOCK_ID, "OffsetHour") ~= 0 then clockTimeServerAdjustedLabel = L["TITAN_CLOCK_TOOLTIP_SERVER_ADJUSTED_TIME"] .. "\t" .. TitanUtils_GetHighlightText(clockTimeServerAdjusted) .. "\n" end local clockText = GetOffsetText(TitanGetVar(TITAN_CLOCK_ID, "OffsetHour")); return "" .. clockTimeLocalLabel .. "\n" .. clockTimeServerLabel .. "\n" .. clockTimeServerAdjustedLabel .. L["TITAN_CLOCK_TOOLTIP_VALUE"] .. "\t" .. TitanUtils_GetHighlightText(clockText) .. "\n" .. TitanUtils_GetGreenText(L["TITAN_CLOCK_TOOLTIP_HINT1"]) .. "\n" .. TitanUtils_GetGreenText(L["TITAN_CLOCK_TOOLTIP_HINT2"]) .. "\n" .. TitanUtils_GetGreenText(L["TITAN_CLOCK_TOOLTIP_HINT3"]); end local function ToggleGameTimeFrameShown() TitanToggleVar(TITAN_CLOCK_ID, "HideGameTimeMinimap"); if GameTimeFrame and GameTimeFrame:GetName() then if TitanGetVar(TITAN_CLOCK_ID, "HideGameTimeMinimap") then GameTimeFrame:Hide() else GameTimeFrame:Show() end end end local function ToggleMapTime() TitanToggleVar(TITAN_CLOCK_ID, "HideMapTime"); if TimeManagerClockButton and TimeManagerClockButton:GetName() then if TitanGetVar(TITAN_CLOCK_ID, "HideMapTime") then TimeManagerClockButton:Hide() else TimeManagerClockButton:Show() end else print("TitanClock: no time widget") end end ---local Build the right click menu local function CreateMenu() TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_CLOCK_ID].menuText); local info = {}; info.text = L["TITAN_CLOCK_MENU_LOCAL_TIME"]; info.func = function() TitanSetVar(TITAN_CLOCK_ID, "TimeMode", "Local") TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() return TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "Local" end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; info.text = L["TITAN_CLOCK_MENU_SERVER_TIME"]; info.func = function() TitanSetVar(TITAN_CLOCK_ID, "TimeMode", "Server") TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() return TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "Server" end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; info.text = L["TITAN_CLOCK_MENU_SERVER_ADJUSTED_TIME"]; info.func = function() TitanSetVar(TITAN_CLOCK_ID, "TimeMode", "ServerAdjusted") TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() return TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerAdjusted" end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; info.text = L["TITAN_CLOCK_MENU_SERVER_TIME"] .. " & " .. L["TITAN_CLOCK_MENU_LOCAL_TIME"] info.func = function() TitanSetVar(TITAN_CLOCK_ID, "TimeMode", "ServerLocal") TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() return TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerLocal" end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; info.text = L["TITAN_CLOCK_MENU_SERVER_ADJUSTED_TIME"] .. " & " .. L["TITAN_CLOCK_MENU_LOCAL_TIME"] info.func = function() TitanSetVar(TITAN_CLOCK_ID, "TimeMode", "ServerAdjustedLocal") TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() return TitanGetVar(TITAN_CLOCK_ID, "TimeMode") == "ServerAdjustedLocal" end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; -- 12 or 24 hour format info.text = L["TITAN_CLOCK_CHECKBUTTON"] info.func = function() if (TitanGetVar(TITAN_CLOCK_ID, "Format") == TITAN_CLOCK_FORMAT_12H) then TitanSetVar(TITAN_CLOCK_ID, "Format", TITAN_CLOCK_FORMAT_24H); else TitanSetVar(TITAN_CLOCK_ID, "Format", TITAN_CLOCK_FORMAT_12H); end if (ServerHourFormat[realmName]) then ServerHourFormat[realmName] = TitanGetVar(TITAN_CLOCK_ID, "Format"); end TitanPanelButton_UpdateButton(TITAN_CLOCK_ID) end info.checked = function() if (TitanGetVar(TITAN_CLOCK_ID, "Format") == TITAN_CLOCK_FORMAT_24H) then return true else return false end end TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); TitanPanelRightClickMenu_AddSpacer(); info = {}; info.text = L["TITAN_CLOCK_MENU_HIDE_MAPTIME"]; info.func = ToggleMapTime; info.checked = TitanGetVar(TITAN_CLOCK_ID, "HideMapTime"); info.keepShownOnClick = 1; TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); info = {}; info.text = L["TITAN_CLOCK_MENU_HIDE_CALENDAR"]; info.func = ToggleGameTimeFrameShown; info.checked = TitanGetVar(TITAN_CLOCK_ID, "HideGameTimeMinimap"); info.keepShownOnClick = 1; TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); TitanPanelRightClickMenu_AddControlVars(TITAN_CLOCK_ID) end ---local Build the plugin .registry and register events ---@param self Button plugin frame local function OnLoad(self) local notes = "" .. "Adds a clock to Titan Panel.\n" .. "- Select server time / local time / both server and local time.\n" self.registry = { id = TITAN_CLOCK_ID, category = "Built-ins", version = TITAN_VERSION, menuText = L["TITAN_CLOCK_MENU_TEXT"], menuTextFunction = CreateMenu, buttonTextFunction = GetButtonText, tooltipTitle = L["TITAN_CLOCK_TOOLTIP"], tooltipTextFunction = GetTooltipText, notes = notes, controlVariables = { ShowIcon = false, ShowLabelText = true, ShowColoredText = true, DisplayOnRightSide = true, }, savedVariables = { OffsetHour = 0, Format = TITAN_CLOCK_FORMAT_12H, TimeMode = "Server", ShowIcon = true, ShowLabelText = false, ShowColoredText = false, DisplayOnRightSide = 1, HideGameTimeMinimap = false, HideMapTime = false, } }; self:RegisterEvent("PLAYER_ENTERING_WORLD"); end ---local Start the timer for advancing the clock time ---@param self Button plugin frame local function OnShow(self) if ClockTimerRunning then -- Do not create a new one else ClockTimer = AceTimer:ScheduleRepeatingTimer(TitanPanelPluginHandle_OnUpdate, 30, updateTable) ClockTimerRunning = true end end ---local Stop the timer for advancing the clock time ---@param self Button plugin frame local function OnHide(self) AceTimer:CancelTimer(ClockTimer) ClockTimerRunning = false end ---local Handle events the clock plugin is interested in. ---@param self Button plugin frame ---@param event string Event ---@param ... any Event parameters local function OnEvent(self, event, ...) if (event == "PLAYER_ENTERING_WORLD") then -- If the user wants the minimap clock or calendar hidden then hide them if TitanGetVar(TITAN_CLOCK_ID, "HideGameTimeMinimap") then if GameTimeFrame then GameTimeFrame:Hide() end end if TimeManagerClockButton and TimeManagerClockButton:GetName() then if TitanGetVar(TITAN_CLOCK_ID, "HideMapTime") then TimeManagerClockButton:Hide() else TimeManagerClockButton:Show() end end end end ---local Handle mouse events the clock plugin is interested in. ---@param self Button plugin frame ---@param button string Button pushed with any modifiers local function OnClick(self, button) if button == "LeftButton" and IsShiftKeyDown() then TitanUtils_CloseAllControlFrames(); if (TitanPanelRightClickMenu_IsVisible()) then TitanPanelRightClickMenu_Close(); end ToggleCalendar() elseif button == "LeftButton" then else TitanPanelButton_OnClick(self, button); end end -- === Slider routines ---local Generate slider tooltip. ---@param self Slider plugin slider frame local function Slider_GetTooltip(self) local slider_tooltip = TitanOptionSlider_TooltipText(L["TITAN_CLOCK_CONTROL_TOOLTIP"], GetOffsetText(TitanGetVar(TITAN_CLOCK_ID, "OffsetHour"))); GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT"); GameTooltip:SetText(slider_tooltip, nil, nil, nil, nil, 1); end ---local Display slider tooltip on mouse over. ---@param self Slider plugin slider frame local function Slider_OnEnter(self) Slider_GetTooltip(self) TitanUtils_StopFrameCounting(self:GetParent()); end ---local Remove slider tooltip on mouse over leaving. ---@param self Slider plugin slider frame local function Slider_OnLeave(self) GameTooltip:Hide(); TitanUtils_StartFrameCounting(self:GetParent(), TITAN_CLOCK_FRAME_SHOW_TIME); end ---local Display slider tooltip options ---@param self Slider plugin slider frame local function Slider_OnShow(self) _G[self:GetName() .. "Text"]:SetText(GetOffsetText(TitanGetVar(TITAN_CLOCK_ID, "OffsetHour"))); _G[self:GetName() .. "High"]:SetText(L["TITAN_CLOCK_CONTROL_LOW"]); _G[self:GetName() .. "Low"]:SetText(L["TITAN_CLOCK_CONTROL_HIGH"]); -- self:SetThumbTexture("Interface\Buttons\UI-SliderBar-Button-Vertical") self:SetMinMaxValues(-12, 12); self:SetValueStep(0.5); self:SetObeyStepOnDrag(true) -- since 5.4.2 (Mists of Pandaria) self:SetValue(0 - TitanGetVar(TITAN_CLOCK_ID, "OffsetHour")); end ---local Display slider tooltip text ---@param self Slider plugin slider frame ---@param a1 number positive or negative change to apply local function Slider_OnValueChangedWheel(self, a1) _G[self:GetName() .. "Text"]:SetText(GetOffsetText(0 - self:GetValue())); local tempval = self:GetValue(); if a1 == -1 then self:SetValue(tempval + 0.5); end if a1 == 1 then self:SetValue(tempval - 0.5); end TitanSetVar(TITAN_CLOCK_ID, "OffsetHour", 0 - self:GetValue()); if (ServerTimeOffsets[realmName]) then ServerTimeOffsets[realmName] = TitanGetVar(TITAN_CLOCK_ID, "OffsetHour"); end TitanPanelButton_UpdateButton(TITAN_CLOCK_ID); -- Update GameTooltip Slider_GetTooltip(self) end ---local Display slider tooltip text ---@param self Slider plugin slider frame ---@param a1 number positive or negative change to apply local function Slider_OnValueChanged(self, a1) local step = self:GetValue() _G[self:GetName() .. "Text"]:SetText(GetOffsetText(0 - step)); TitanSetVar(TITAN_CLOCK_ID, "OffsetHour", 0 - step); if (ServerTimeOffsets[realmName]) then ServerTimeOffsets[realmName] = TitanGetVar(TITAN_CLOCK_ID, "OffsetHour"); end TitanPanelButton_UpdateButton(TITAN_CLOCK_ID); -- Update GameTooltip Slider_GetTooltip(self) end -- === Option menu routines ---local Create clock option frame ---@param self Frame Plugin option menu frame local function TitanPanelClockControlFrame_OnLoad(self) _G[self:GetName() .. "Title"]:SetText(L["TITAN_CLOCK_CONTROL_TITLE"]); --[[ Blizzard decided to remove direct Backdrop API in 9.0 (Shadowlands) so inherit the template (XML) and set the values in the code (Lua) 9.5 The tooltip template was removed from the GameTooltip. --]] TitanPanelRightClickMenu_SetCustomBackdrop(self) end ---If dropdown is visible, see if its timer has expired. If expired, hide frame. ---@param self Frame Plugin option menu frame ---@param elapsed number portion of second since last OnUpdate local function Control_OnUpdate(self, elapsed) TitanUtils_CheckFrameCounting(self, elapsed); end -- ====== Create needed frames local function Create_Frames() if _G[TITAN_BUTTON] then return -- if already created end -- general container frame local f = CreateFrame("Frame", nil, UIParent) -- f:Hide() -- Titan plugin button local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelTextTemplate") window:SetFrameStrata("FULLSCREEN") -- Using SetScript("OnLoad", does not work OnLoad(window); -- TitanPanelButton_OnLoad(window); -- Titan XML template calls this... window:SetScript("OnShow", function(self) OnShow(self) TitanPanelButton_OnShow(self) end) window:SetScript("OnHide", function(self) OnHide(self) end) window:SetScript("OnEvent", function(self, event, ...) OnEvent(self, event, ...) end) window:SetScript("OnClick", function(self, button) OnClick(self, button) TitanPanelButton_OnClick(self, button) end) ---[===[ -- Config screen local cname = "TitanPanelClockControlFrame" local config = CreateFrame("Frame", cname, f, BackdropTemplateMixin and "BackdropTemplate") config:SetFrameStrata("FULLSCREEN") -- FULLSCREEN config:Hide() -- config:SetWidth(90) config:SetHeight(200) config:SetScript("OnShow", function(self) end) config:SetScript("OnEnter", function(self) TitanUtils_StopFrameCounting(self) end) config:SetScript("OnLeave", function(self) TitanUtils_StartFrameCounting(self, 0.5) end) config:SetScript("OnUpdate", function(self, elapsed) Control_OnUpdate(self, elapsed) end) -- Config Title local str = nil local style = "GameFontNormalSmall" str = config:CreateFontString(cname .. "Title", "ARTWORK", style) str:SetPoint("TOP", config, 0, -10) -- Config slider sections local slider = nil -- Hours offset local inherit = "TitanOptionsSliderTemplate" local offset = CreateFrame("Slider", "TitanPanelClockControlSlider", config, inherit) offset:SetPoint("TOP", config, 0, -40) offset:SetScript("OnShow", function(self) Slider_OnShow(self) end) offset:SetScript("OnValueChanged", function(self, value, userInput) Slider_OnValueChanged(self, value) end) offset:SetScript("OnMouseWheel", function(self, delta) Slider_OnValueChangedWheel(self, delta) end) offset:SetScript("OnEnter", function(self) Slider_OnEnter(self) end) offset:SetScript("OnLeave", function(self) Slider_OnLeave(self) end) -- Now that the parts exist, initialize TitanPanelClockControlFrame_OnLoad(config) --]===] end Create_Frames() -- do the work