Version 1.1.1
[minetest_calendar.git] / gui.lua
blob843e90034fd5469502d116df1e3391cafda60b9e
1 local S = calendar._get_translator("calendar")
2 local F = minetest.formspec_escape
4 local player_current_calendars = {}
6 -- Colors
7 local COLOR_HOLIDAY = "#00FF00"
8 local COLOR_DAYBOX_HOLIDAY = "#00940FFF"
9 local COLOR_DAYBOX = "#1A1A1AFF"
10 local COLOR_DAYBOX_TODAY = "#FFF508FF"
11 local COLOR_TOOLTIP_TODAY = COLOR_DAYBOX_TODAY
13 -- Default settings
14 local ORDINAL = true
15 local SHOW_WEEKDAYS = true
16 local SHOW_TODAY = true
17 local SHOW_HOLIDAYS = true
18 local CHANGABLE = "full"
19 local TODAY_BUTTON = true
20 local DEFAULT_SETTINGS = {
21 ordinal = ORDINAL,
22 show_weekdays = SHOW_WEEKDAYS,
23 show_today = SHOW_TODAY,
24 show_holidays = SHOW_HOLIDAYS,
25 changable = CHANGABLE,
26 today_button = TODAY_BUTTON,
29 -- Offset between dayboxes
30 local DAYBOX_OFFSET
31 if minetest.features.formspec_version_element then
32 DAYBOX_OFFSET = 0.1
33 else
34 DAYBOX_OFFSET = 0
35 end
37 -- Check if area tooltips are supported.
38 -- minetest.features, doesn't tell us that directly, but
39 -- the formspec version element was added after area tooltips,
40 -- so if those are present, area tooltips have to be supported as well.
41 local SHOW_AREA_TOOLTIPS = minetest.features.formspec_version_element
43 function calendar.show_calendar(player_name, settings, wanted_months, wanted_years, caption_format)
44 -- Get settings, use defaults if needed
45 if not settings then
46 settings = DEFAULT_SETTINGS
47 end
48 for k,v in pairs(DEFAULT_SETTINGS) do
49 if settings[k] == nil then
50 settings[k] = v
51 end
52 end
54 local days, months, years = calendar.get_date()
55 local total_days = minetest.get_day_count()
56 local wanted_dyears
57 if not wanted_months then
58 wanted_months = months
59 end
60 if not wanted_years then
61 wanted_years = years
62 end
63 wanted_dyears = wanted_years
64 if settings.ordinal then
65 wanted_dyears = wanted_dyears + 1
66 end
67 local tdays = 0
68 tdays = tdays + wanted_years * (calendar.MONTHS * calendar.MONTH_DAYS)
69 tdays = tdays + wanted_months * calendar.MONTH_DAYS
71 -- Render caption
72 local formspec = ""
73 local caption = ""
74 if caption_format then
75 local args = {}
76 if caption_format[3] then
77 for a=3, #caption_format do
78 table.insert(args, calendar.get_date_string(caption_format[a], tdays))
79 end
80 end
81 caption = calendar._translate(caption_format[2], caption_format[1], unpack(args))
82 else
83 if settings.ordinal then
84 caption = S("@1, year @2", S(calendar.month_names[wanted_months+1]), wanted_dyears)
85 else
86 caption = S("@1, @2 years", S(calendar.month_names[wanted_months+1]), wanted_dyears)
87 end
88 end
89 if caption ~= "" then
90 formspec = formspec .. "label[0.5,0.5;"..F(caption).."]"
91 end
93 -- Render weekday names
94 local tdays_start = tdays
95 local weekday, x, y
96 if settings.show_weekdays then
97 weekday = calendar.get_weekday(tdays)
98 x, y = 0.75, 1.2
99 for w=1, #calendar.weekday_names_short do
100 formspec = formspec .. "label["..x..","..y..";"..F(S(calendar.weekday_names_short[w])).."]"
101 x = x + 1 + DAYBOX_OFFSET
103 else
104 weekday = 0
107 -- Render day boxes, day numbers and highlights
108 x, y = 0.5, 1.7
109 for iday=0, calendar.MONTH_DAYS - 1 do
110 weekday = weekday + 1
111 if weekday > calendar.WEEK_DAYS then
112 weekday = 1
113 y = y + 1 + DAYBOX_OFFSET
115 x = (weekday * (1 + DAYBOX_OFFSET)) - 0.5
116 local pday = iday
117 if settings.ordinal then
118 pday = iday + 1
120 local day_str = tostring(pday)
121 local holiday_color
122 local box_color = COLOR_DAYBOX
123 local holidays = calendar.get_holidays(tdays)
124 local tooltip_lines = {}
125 -- Highlight holiday
126 local is_holiday = false
127 if settings.show_holidays and #holidays > 0 then
128 is_holiday = true
129 local text_color = COLOR_HOLIDAY
130 for h=1, #holidays do
131 if holidays[h].text_color then
132 text_color = holidays[h].text_color
133 else
134 text_color = COLOR_HOLIDAY
136 table.insert(tooltip_lines, minetest.colorize(text_color, holidays[h].name))
138 holiday_color = holidays[1].text_color or COLOR_HOLIDAY
139 day_str = minetest.colorize(holiday_color, day_str)
140 box_color = holidays[1].daybox_color or COLOR_DAYBOX_HOLIDAY
142 day_str = F(day_str)
143 -- Highlight today
144 if settings.show_today and tdays == total_days then
145 if SHOW_AREA_TOOLTIPS then
146 formspec = formspec .. "box["..(x-0.05)..","..(y-0.05)..";1.1,1.1;"..COLOR_DAYBOX_TODAY.."]"
147 else
148 formspec = formspec .. "box["..(x-0.075)..","..(y-0.075)..";0.95,1.05;"..COLOR_DAYBOX_TODAY.."]"
150 table.insert(tooltip_lines, minetest.colorize(COLOR_TOOLTIP_TODAY, S("Today")))
152 if SHOW_AREA_TOOLTIPS then
153 formspec = formspec .. "box["..x..","..y..";1,1;"..box_color.."]"
154 .. "label["..(x+0.15)..","..(y+0.075)..";"..day_str.."]"
155 else
156 local day_num = pday
157 if is_holiday and settings.show_holidays then
158 day_num = minetest.colorize(holiday_color, pday)
160 -- Fake button to display the day box. Clicking has no effect, this
161 -- fake button is only used to support tooltips as a workaround
162 -- for lacking support of area tooltips
163 formspec = formspec .. "image_button["..x..","..y..";1,1;"..
164 F("calendar_legacy_daybox.png^[colorize:"..box_color..":255]")..
165 ";day"..iday..";"..F(day_num).."]"
167 if #tooltip_lines > 0 then
168 local tooltips = F(table.concat(tooltip_lines, "\n"))
169 if SHOW_AREA_TOOLTIPS then
170 formspec = formspec .. "tooltip["..x..","..y..";1,1;"..F(tooltips).."]"
171 else
172 formspec = formspec .. "tooltip[day"..iday..";"..F(tooltips).."]"
175 tdays = tdays + 1
177 y = y + 1 + DAYBOX_OFFSET
178 if settings.show_weekdays and calendar.get_weekday(tdays_start) <= calendar.get_weekday(tdays - 1) then
179 y = y + 1 + DAYBOX_OFFSET
181 y = y + DAYBOX_OFFSET
182 local chg_months = settings.changable == "full" or settings.changable == "months"
183 local chg_years = settings.changable == "full"
184 -- Add controls
185 if chg_months then
187 if wanted_months > 0 or wanted_years > 0 then
188 if (chg_years or wanted_months > 0) or (not chg_years and wanted_months > 0) then
189 formspec = formspec .. "button[1.5,"..y..";1,1;prev_month;<]"
190 .. "tooltip[prev_month;"..F(S("Previous month")).."]"
192 if chg_years then
193 formspec = formspec .. "button[0.5,"..y..";1,1;prev_year;<<]"
194 .. "tooltip[prev_year;"..F(S("Previous year")).."]"
197 if settings.today_button then
198 formspec = formspec .. "button[2.5,"..y..";2,1;today;"..F(S("Today")).."]"
201 if (chg_years or wanted_months < calendar.MONTHS - 1) or (not chg_years and wanted_months < calendar.MONTHS - 1) then
202 formspec = formspec .. "button[4.5,"..y..";1,1;next_month;>]"
203 .. "tooltip[next_month;"..F(S("Next month")).."]"
205 if chg_years then
206 formspec = formspec .. "button[5.5,"..y..";1,1;next_year;>>]"
207 .. "tooltip[next_year;"..F(S("Next year")).."]"
210 local size_x = math.max(calendar.WEEK_DAYS+2, 7)
211 local size_y = y+1.5
213 -- Formspec config
214 if minetest.features.formspec_version_element then
215 formspec = "formspec_version[3]" .. formspec
217 formspec = "size["..size_x..","..size_y.."]" .. formspec
218 minetest.show_formspec(player_name, "calendar:calendar", formspec)
220 player_current_calendars[player_name] =
221 { years = wanted_years, months = wanted_months, settings = settings, caption_format = caption_format }
224 minetest.register_on_player_receive_fields(function(player, formname, fields)
225 if formname ~= "calendar:calendar" then
226 return
228 if not player:is_player() then
229 return
231 local name = player:get_player_name()
232 local cur_years, cur_months
233 if not player_current_calendars then
234 return
236 local show = false
237 cur_years = player_current_calendars[name].years
238 cur_months = player_current_calendars[name].months
239 local settings = player_current_calendars[name].settings
240 if fields.today then
241 cur_years, cur_months = nil, nil
242 show = true
244 if settings.changable == "full" then
245 if fields.next_year then
246 cur_years = cur_years + 1
247 show = true
248 elseif fields.prev_year then
249 if cur_years == 0 then
250 cur_months = 0
251 else
252 cur_years = cur_years - 1
254 show = true
257 if fields.next_month then
258 cur_months = cur_months + 1
259 if cur_months > calendar.MONTHS - 1 then
260 if settings.changable == "full" then
261 cur_months = 0
262 cur_years = cur_years + 1
263 else
264 cur_months = calendar.MONTHS - 1
267 show = true
268 elseif fields.prev_month then
269 cur_months = cur_months - 1
270 if cur_months < 0 and cur_years > 0 then
271 if settings.changable == "full" then
272 cur_months = calendar.MONTHS - 1
273 cur_years = cur_years - 1
274 else
275 cur_months = 0
278 show = true
280 if show then
281 calendar.show_calendar(name,
282 settings,
283 cur_months, cur_years,
284 player_current_calendars[name].caption_format
287 end)
289 minetest.register_on_leaveplayer(function(player)
290 local name = player:get_player_name()
291 player_current_calendars[name] = nil
292 end)