Files
TurtleMail/Calendar.lua
T
2025-04-02 14:36:04 +02:00

293 lines
7.6 KiB
Lua

TurtleMail = TurtleMail or {}
local m = TurtleMail
if m.Calendar then return end
---@class Calendar
---@field show fun( data: table, date: number, anchor: table, on_select: function )
---@field hide fun()
---@field is_visible fun():boolean
local M = {}
function M.new()
local BTN_WIDTH = 25
local BTN_HEIGHT = 20
local calendar
local set_year, set_month
local year_dd, month_dd
local date_data = {}
local months = {}
local days = {}
local select_func
for i = 1, 12 do
local timestamp = time( { year = 2025, month = i, day = 1 } )
months[ i ] = date( "%B", timestamp )
end
local function get_end_day_of_month( year, month )
if month == 2 then
if (mod( year, 4 ) == 0 and mod( year, 100 ) ~= 0) or mod( year, 400 ) == 0 then
return 29
else
return 28
end
elseif month == 4 or month == 6 or month == 9 or month == 11 then
return 30
else
return 31
end
end
---@alias DatePart
---| "Year"
---| "Month"
---| "Day"
---@param part DatePart
local function get_valid_dates( part )
local valid = {}
for i, v in ipairs( date_data ) do
local year = tonumber( date( "%Y", v.timestamp ) )
local month = tonumber( date( "%m", v.timestamp ) )
local day = tonumber( date( "%d", v.timestamp ) )
if year and month and day then
if part == "Day" and year == set_year and month == set_month then
valid[ day ] = valid[ day ] and valid[ day ] + 1 or 1
elseif part == "Month" and year == set_year then
valid[ month ] = true
elseif part == "Year" then
valid[ year ] = true
end
end
end
return valid
end
local function refresh()
local current_month = { year = set_year, month = set_month, day = "01" }
local skip_days = date( "%w", time( current_month ) )
local end_day = get_end_day_of_month( tonumber( set_year ), tonumber( set_month ) )
for i = 1, 42 do
days[ i ]:SetText( "" )
days[ i ]:Disable()
days[ i ]:Hide()
end
local valid_days = get_valid_dates( "Day" )
for i = 1, end_day do
local day = days[ i + skip_days ]
local d = i
day:SetText( i )
if valid_days[ i ] then
day.mails = valid_days[ i ]
day:Enable()
end
day:Show()
day:SetScript( "OnClick", function()
local timestamp = time( { year = set_year, month = set_month, day = d } )
if select_func then
select_func( timestamp )
end
calendar:Hide()
end )
end
if tonumber( skip_days + end_day ) < 36 then
calendar:SetHeight( 150 )
else
calendar:SetHeight( 170 )
end
m.api.UIDropDownMenu_SetText( months[ set_month ], month_dd )
m.api.UIDropDownMenu_SetText( set_year, year_dd )
end
local function pfui_skin()
if m.pfui_skin_enabled then
m.api.pfUI.api.SkinDropDown( year_dd, nil, nil, nil, true )
year_dd:SetPoint( "TOPLEFT", -5, -5 )
m.api.pfUI.api.SkinDropDown( month_dd, nil, nil, nil, true )
month_dd:SetPoint( "TOPLEFT", 79, -5 )
m.api.UIDropDownMenu_SetWidth( 70, month_dd )
for i = 1, 42 do
local button = days[ i ]
m.api.pfUI.api.SkinButton( button )
button:SetWidth( BTN_WIDTH - 1 )
button:SetHeight( BTN_HEIGHT - 1 )
end
end
end
---@param parent table
---@param index number
local function create_date_button( parent, index )
local button = m.api.CreateFrame( "Button", "TurtleMailCalendarDay" .. index .. "Button", parent, "UIPanelButtonTemplate" )
button:SetWidth( BTN_WIDTH )
button:SetHeight( BTN_HEIGHT )
button:GetFontString():SetFont( m.pfui_skin_enabled and m.api.pfUI.font_default or "Fonts/FRIZQT__.TTF", 9 )
button:GetFontString():SetTextColor( 1, 1, 1, 1 )
local orig_disable = button.Disable
button.Disable = function( self )
orig_disable( self )
button:GetFontString():SetTextColor( 0.5, 0.5, 0.5, 1 )
end
local orig_enable = button.Enable
button.Enable = function( self )
orig_enable( self )
button:GetFontString():SetTextColor( 1, 1, 1, 1 )
end
button:SetScript( "OnEnter", function()
m.api.GameTooltip:SetOwner( this, "ANCHOR_RIGHT" )
m.api.GameTooltip:SetText( button.mails .. " mail" .. (button.mails > 1 and "s" or ""), 1, 1, 1, 1, true )
m.api.GameTooltip:Show()
end )
button:SetScript( "OnLeave", function()
m.api.GameTooltip:Hide()
end )
return button
end
---@param parent table
---@param name DatePart
---@param on_select function
---@return table
local function create_dropdown( parent, name, on_select )
local dropdown = m.api.CreateFrame( "Frame", "TurtleMailDropdown" .. name, parent, "UIDropDownMenuTemplate" )
m.api.UIDropDownMenu_Initialize( dropdown, function()
local valid_dates = get_valid_dates( name )
local info = {}
for i in pairs( valid_dates ) do
info.arg1 = i
info.arg2 = name == "Month" and months[ i ] or i
info.value = info.arg1
info.text = info.arg2
info.func = function( index, value )
m.api.UIDropDownMenu_SetText( value, dropdown )
m.api.CloseDropDownMenus()
on_select( index, value )
end
m.api.UIDropDownMenu_AddButton( info )
end
end )
return dropdown
end
local function create_calendar()
local frame = m.api.CreateFrame( "Frame", "TurtleMailCalendarFrame" )
frame:SetFrameStrata( "FULLSCREEN_DIALOG" )
frame:SetWidth( 195 )
frame:SetHeight( 170 )
frame:SetBackdrop( {
bgFile = "Interface/Buttons/WHITE8x8",
edgeFile = "Interface/Buttons/WHITE8x8",
tile = false,
tileSize = 0,
edgeSize = 0.5,
insets = { left = 0, right = 0, top = 0, bottom = 0 }
} )
frame:SetBackdropColor( 0, 0, 0, 0.9 )
frame:SetBackdropBorderColor( .4, .4, .4, 0.9 )
frame:EnableMouse( true )
frame:Hide()
m.api.tinsert( m.api.UISpecialFrames, frame:GetName() )
frame:SetScript( "OnLeave", function()
if m.api.MouseIsOver( frame ) then
return
end
calendar:Hide()
end )
year_dd = create_dropdown( frame, "Year", function( _, v )
set_year = v
refresh()
end )
year_dd:SetPoint( "TOPLEFT", -12, -5 )
m.api.UIDropDownMenu_SetWidth( 55, year_dd )
month_dd = create_dropdown( frame, "Month", function( v )
set_month = v
refresh()
end )
month_dd:SetPoint( "TOPLEFT", 70, -5 )
m.api.UIDropDownMenu_SetWidth( 85, month_dd )
for i = 1, 42 do
table.insert( days, create_date_button( frame, i ) )
end
for i = 1, 6 do
for j = 1, 7 do
days[ (i - 1) * 7 + j ]:SetPoint( "TOPLEFT", frame, 10 + (j - 1) * BTN_WIDTH, -40 - (i - 1) * BTN_HEIGHT )
days[ (i - 1) * 7 + j ]:Disable()
end
end
pfui_skin()
return frame
end
local function show( data, current_date, anchor, on_select )
date_data = data
set_year = tonumber( date( "%Y", current_date ) )
set_month = tonumber( date( "%m", current_date ) )
select_func = on_select
if not calendar then
calendar = create_calendar()
end
if m.pfui_skin_enabled then
calendar:SetPoint( "TOPRIGHT", anchor, "BOTTOMRIGHT", 125, -4 )
else
calendar:SetPoint( "TOPRIGHT", anchor, "BOTTOMRIGHT", 100, 1 )
end
refresh()
calendar:Show()
end
local function hide()
if calendar then
calendar:Hide()
end
end
local function is_visible()
if calendar then
return calendar:IsVisible()
end
return false
end
---@type Calendar
return {
show = show,
hide = hide,
is_visible = is_visible
}
end
m.Calendar = M
return M