Files
leonwww/flumi/addons/DatePicker/MonthView.gd
2025-08-02 14:18:14 +03:00

147 lines
4.3 KiB
GDScript

class_name MonthView
extends VBoxContainer
@export var calendar: Calendar
var buttons: GridContainer
var dates: Array = []
var _updating: bool = false
func _ready():
buttons = $Days
for i in range(buttons.get_child_count()):
buttons.get_child(i).toggled.connect(_on_day_toggled.bind(i))
refresh()
func _on_day_toggled(toggled: bool, button_index: int):
if _updating or button_index >= dates.size() or not dates[button_index]:
return
var button = buttons.get_child(button_index)
if not toggled:
button.set_pressed_no_signal(true)
return
for i in range(buttons.get_child_count()):
if i != button_index:
buttons.get_child(i).set_pressed_no_signal(false)
calendar.selected = dates[button_index]
calendar.date_time = dates[button_index].duplicate()
calendar.hide()
calendar.finished.emit()
func previous():
var new_date = calendar.date_time.duplicate()
new_date.month -= 1
if new_date.month < 1:
new_date.month = 12
new_date.year -= 1
calendar.date_time = new_date
refresh()
func next():
var new_date = calendar.date_time.duplicate()
new_date.month += 1
if new_date.month > 12:
new_date.month = 1
new_date.year += 1
calendar.date_time = new_date
refresh()
func refresh():
_updating = true
calendar.header.text = "%s %s" % [num_to_month(calendar.date_time.month), calendar.date_time.year]
dates.clear()
dates.resize(buttons.get_child_count())
for i in range(buttons.get_child_count()):
var button = buttons.get_child(i)
button.text = ""
button.set_pressed_no_signal(false)
dates[i] = null
var first_day = calendar.date_time.duplicate()
first_day.day = 1
var start_day = Time.get_datetime_dict_from_unix_time(
Time.get_unix_time_from_datetime_dict(first_day)
).weekday % 7
var days_in_month = get_days_in_month(calendar.date_time.year, calendar.date_time.month)
var prev_month_num = calendar.date_time.month - 1
var prev_year = calendar.date_time.year
if prev_month_num < 1:
prev_month_num = 12
prev_year -= 1
var prev_days = get_days_in_month(prev_year, prev_month_num)
var gray_color = Color(0.51, 0.54, 0.596)
var dark_color = Color(0.133, 0.137, 0.137)
# Fill previous month days
for i in range(start_day):
var day = prev_days - start_day + i + 1
var button = buttons.get_child(i)
dates[i] = {"year": prev_year, "month": prev_month_num, "day": day}
button.text = str(day)
button.add_theme_color_override("font_color", gray_color)
button.add_theme_color_override("font_hover_color", gray_color)
button.set_pressed_no_signal(
day == calendar.selected.day and
calendar.selected.year == prev_year and
calendar.selected.month == prev_month_num
)
# Fill current month days
for i in range(days_in_month):
var button = buttons.get_child(i + start_day)
dates[i + start_day] = {"year": calendar.date_time.year, "month": calendar.date_time.month, "day": i + 1}
button.text = str(i + 1)
button.add_theme_color_override("font_color", dark_color)
button.add_theme_color_override("font_hover_color", dark_color)
button.set_pressed_no_signal(
i + 1 == calendar.selected.day and
calendar.selected.year == calendar.date_time.year and
calendar.selected.month == calendar.date_time.month
)
var next_month_num = calendar.date_time.month + 1
var next_year = calendar.date_time.year
if next_month_num > 12:
next_month_num = 1
next_year += 1
# Fill next month days
for i in range(days_in_month + start_day, buttons.get_child_count()):
var day = i + 1 - days_in_month - start_day
var button = buttons.get_child(i)
dates[i] = {"year": next_year, "month": next_month_num, "day": day}
button.text = str(day)
button.add_theme_color_override("font_color", gray_color)
button.add_theme_color_override("font_hover_color", gray_color)
button.set_pressed_no_signal(
day == calendar.selected.day and
calendar.selected.year == next_year and
calendar.selected.month == next_month_num
)
_updating = false
func get_days_in_month(year: int, month: int) -> int:
var thirty_one = [1, 3, 5, 7, 8, 10, 12]
var thirty = [4, 6, 9, 11]
if month in thirty_one:
return 31
elif month in thirty:
return 30
elif month == 2:
return 29 if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) else 28
else:
return 0
static func num_to_month(month: int) -> String:
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
return months[month - 1]