minetest_calendar/gui.lua

294 lines
8.6 KiB
Lua

local S = calendar._get_translator("calendar")
local F = minetest.formspec_escape
local player_current_calendars = {}
-- Colors
local COLOR_HOLIDAY = "#00FF00"
local COLOR_DAYBOX_HOLIDAY = "#00940FFF"
local COLOR_DAYBOX = "#1A1A1AFF"
local COLOR_DAYBOX_TODAY = "#FFF508FF"
local COLOR_TOOLTIP_TODAY = COLOR_DAYBOX_TODAY
-- Default settings
local ORDINAL = true
local SHOW_WEEKDAYS = true
local SHOW_TODAY = true
local SHOW_HOLIDAYS = true
local CHANGABLE = "full"
local TODAY_BUTTON = true
local DEFAULT_SETTINGS = {
ordinal = ORDINAL,
show_weekdays = SHOW_WEEKDAYS,
show_today = SHOW_TODAY,
show_holidays = SHOW_HOLIDAYS,
changable = CHANGABLE,
today_button = TODAY_BUTTON,
}
-- Offset between dayboxes
local DAYBOX_OFFSET
if minetest.features.formspec_version_element then
DAYBOX_OFFSET = 0.1
else
DAYBOX_OFFSET = 0
end
-- Check if area tooltips are supported.
-- minetest.features, doesn't tell us that directly, but
-- the formspec version element was added after area tooltips,
-- so if those are present, area tooltips have to be supported as well.
local SHOW_AREA_TOOLTIPS = minetest.features.formspec_version_element
function calendar.show_calendar(player_name, settings, wanted_months, wanted_years, caption_format)
-- Get settings, use defaults if needed
if not settings then
settings = DEFAULT_SETTINGS
end
for k,v in pairs(DEFAULT_SETTINGS) do
if settings[k] == nil then
settings[k] = v
end
end
local days, months, years = calendar.get_date()
local total_days = minetest.get_day_count()
local wanted_dyears
if not wanted_months then
wanted_months = months
end
if not wanted_years then
wanted_years = years
end
wanted_dyears = wanted_years
if settings.ordinal then
wanted_dyears = wanted_dyears + 1
end
local tdays = 0
tdays = tdays + wanted_years * (calendar.MONTHS * calendar.MONTH_DAYS)
tdays = tdays + wanted_months * calendar.MONTH_DAYS
-- Render caption
local formspec = ""
local caption = ""
if caption_format then
local args = {}
if caption_format[3] then
for a=3, #caption_format do
table.insert(args, calendar.get_date_string(caption_format[a], tdays))
end
end
caption = calendar._translate(caption_format[2], caption_format[1], unpack(args))
else
if settings.ordinal then
caption = S("@1, year @2", S(calendar.month_names[wanted_months+1]), wanted_dyears)
else
caption = S("@1, @2 years", S(calendar.month_names[wanted_months+1]), wanted_dyears)
end
end
if caption ~= "" then
formspec = formspec .. "label[0.5,0.5;"..F(caption).."]"
end
-- Render weekday names
local tdays_start = tdays
local weekday, x, y
if settings.show_weekdays then
weekday = calendar.get_weekday(tdays)
x, y = 0.75, 1.2
for w=1, #calendar.weekday_names_short do
formspec = formspec .. "label["..x..","..y..";"..F(S(calendar.weekday_names_short[w])).."]"
x = x + 1 + DAYBOX_OFFSET
end
else
weekday = 0
end
-- Render day boxes, day numbers and highlights
x, y = 0.5, 1.7
for iday=0, calendar.MONTH_DAYS - 1 do
weekday = weekday + 1
if weekday > calendar.WEEK_DAYS then
weekday = 1
y = y + 1 + DAYBOX_OFFSET
end
x = (weekday * (1 + DAYBOX_OFFSET)) - 0.5
local pday = iday
if settings.ordinal then
pday = iday + 1
end
local day_str = tostring(pday)
local holiday_color
local box_color = COLOR_DAYBOX
local holidays = calendar.get_holidays(tdays)
local tooltip_lines = {}
-- Highlight holiday
local is_holiday = false
if settings.show_holidays and #holidays > 0 then
is_holiday = true
local text_color = COLOR_HOLIDAY
for h=1, #holidays do
if holidays[h].text_color then
text_color = holidays[h].text_color
else
text_color = COLOR_HOLIDAY
end
table.insert(tooltip_lines, minetest.colorize(text_color, holidays[h].name))
end
holiday_color = holidays[1].text_color or COLOR_HOLIDAY
day_str = minetest.colorize(holiday_color, day_str)
box_color = holidays[1].daybox_color or COLOR_DAYBOX_HOLIDAY
end
day_str = F(day_str)
-- Highlight today
if settings.show_today and tdays == total_days then
if SHOW_AREA_TOOLTIPS then
formspec = formspec .. "box["..(x-0.05)..","..(y-0.05)..";1.1,1.1;"..COLOR_DAYBOX_TODAY.."]"
else
formspec = formspec .. "box["..(x-0.075)..","..(y-0.075)..";0.95,1.05;"..COLOR_DAYBOX_TODAY.."]"
end
table.insert(tooltip_lines, minetest.colorize(COLOR_TOOLTIP_TODAY, S("Today")))
end
if SHOW_AREA_TOOLTIPS then
formspec = formspec .. "box["..x..","..y..";1,1;"..box_color.."]"
.. "label["..(x+0.15)..","..(y+0.075)..";"..day_str.."]"
else
local day_num = pday
if is_holiday and settings.show_holidays then
day_num = minetest.colorize(holiday_color, pday)
end
-- Fake button to display the day box. Clicking has no effect, this
-- fake button is only used to support tooltips as a workaround
-- for lacking support of area tooltips
formspec = formspec .. "image_button["..x..","..y..";1,1;"..
F("calendar_legacy_daybox.png^[colorize:"..box_color..":255]")..
";day"..iday..";"..F(day_num).."]"
end
if #tooltip_lines > 0 then
local tooltips = F(table.concat(tooltip_lines, "\n"))
if SHOW_AREA_TOOLTIPS then
formspec = formspec .. "tooltip["..x..","..y..";1,1;"..F(tooltips).."]"
else
formspec = formspec .. "tooltip[day"..iday..";"..F(tooltips).."]"
end
end
tdays = tdays + 1
end
y = y + 1 + DAYBOX_OFFSET
if settings.show_weekdays and calendar.get_weekday(tdays_start) <= calendar.get_weekday(tdays - 1) then
y = y + 1 + DAYBOX_OFFSET
end
y = y + DAYBOX_OFFSET
local chg_months = settings.changable == "full" or settings.changable == "months"
local chg_years = settings.changable == "full"
-- Add controls
if chg_months then
if wanted_months > 0 or wanted_years > 0 then
if (chg_years or wanted_months > 0) or (not chg_years and wanted_months > 0) then
formspec = formspec .. "button[1.5,"..y..";1,1;prev_month;<]"
.. "tooltip[prev_month;"..F(S("Previous month")).."]"
end
if chg_years then
formspec = formspec .. "button[0.5,"..y..";1,1;prev_year;<<]"
.. "tooltip[prev_year;"..F(S("Previous year")).."]"
end
end
if settings.today_button then
formspec = formspec .. "button[2.5,"..y..";2,1;today;"..F(S("Today")).."]"
end
if (chg_years or wanted_months < calendar.MONTHS - 1) or (not chg_years and wanted_months < calendar.MONTHS - 1) then
formspec = formspec .. "button[4.5,"..y..";1,1;next_month;>]"
.. "tooltip[next_month;"..F(S("Next month")).."]"
end
if chg_years then
formspec = formspec .. "button[5.5,"..y..";1,1;next_year;>>]"
.. "tooltip[next_year;"..F(S("Next year")).."]"
end
end
local size_x = math.max(calendar.WEEK_DAYS+2, 7)
local size_y = y+1.5
-- Formspec config
if minetest.features.formspec_version_element then
formspec = "formspec_version[3]" .. formspec
end
formspec = "size["..size_x..","..size_y.."]" .. formspec
minetest.show_formspec(player_name, "calendar:calendar", formspec)
player_current_calendars[player_name] =
{ years = wanted_years, months = wanted_months, settings = settings, caption_format = caption_format }
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "calendar:calendar" then
return
end
if not player:is_player() then
return
end
local name = player:get_player_name()
local cur_years, cur_months
if not player_current_calendars then
return
end
local show = false
cur_years = player_current_calendars[name].years
cur_months = player_current_calendars[name].months
local settings = player_current_calendars[name].settings
if fields.today then
cur_years, cur_months = nil, nil
show = true
end
if settings.changable == "full" then
if fields.next_year then
cur_years = cur_years + 1
show = true
elseif fields.prev_year then
if cur_years == 0 then
cur_months = 0
else
cur_years = cur_years - 1
end
show = true
end
end
if fields.next_month then
cur_months = cur_months + 1
if cur_months > calendar.MONTHS - 1 then
if settings.changable == "full" then
cur_months = 0
cur_years = cur_years + 1
else
cur_months = calendar.MONTHS - 1
end
end
show = true
elseif fields.prev_month then
cur_months = cur_months - 1
if cur_months < 0 and cur_years > 0 then
if settings.changable == "full" then
cur_months = calendar.MONTHS - 1
cur_years = cur_years - 1
else
cur_months = 0
end
end
show = true
end
if show then
calendar.show_calendar(name,
settings,
cur_months, cur_years,
player_current_calendars[name].caption_format
)
end
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
player_current_calendars[name] = nil
end)