98 lines
3.1 KiB
GDScript
98 lines
3.1 KiB
GDScript
extends Button
|
|
|
|
signal date_selected(date_str: String)
|
|
|
|
@onready var popup = $PopupPanel
|
|
@onready var month_year_lbl = $PopupPanel/VBox/Header/MonthYearLbl
|
|
@onready var days_grid = $PopupPanel/VBox/DaysGrid
|
|
@onready var prev_btn = $PopupPanel/VBox/Header/PrevBtn
|
|
@onready var next_btn = $PopupPanel/VBox/Header/NextBtn
|
|
@onready var clear_btn = $PopupPanel/VBox/ClearBtn
|
|
|
|
var current_date: Dictionary
|
|
var view_date: Dictionary
|
|
|
|
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
|
|
|
func _ready() -> void:
|
|
var now = Time.get_datetime_dict_from_system()
|
|
view_date = {"year": now.year, "month": now.month, "day": now.day}
|
|
|
|
pressed.connect(_on_button_pressed)
|
|
prev_btn.pressed.connect(_on_prev_month)
|
|
next_btn.pressed.connect(_on_next_month)
|
|
clear_btn.pressed.connect(_on_clear_pressed)
|
|
|
|
_update_calendar()
|
|
|
|
func _on_button_pressed() -> void:
|
|
_update_calendar()
|
|
popup.popup_centered()
|
|
|
|
func _on_prev_month() -> void:
|
|
view_date.month -= 1
|
|
if view_date.month < 1:
|
|
view_date.month = 12
|
|
view_date.year -= 1
|
|
_update_calendar()
|
|
|
|
func _on_next_month() -> void:
|
|
view_date.month += 1
|
|
if view_date.month > 12:
|
|
view_date.month = 1
|
|
view_date.year += 1
|
|
_update_calendar()
|
|
|
|
func _on_clear_pressed() -> void:
|
|
clear_date()
|
|
|
|
func clear_date() -> void:
|
|
current_date = {}
|
|
text = "Select Date..."
|
|
emit_signal("date_selected", "")
|
|
popup.hide()
|
|
|
|
func _update_calendar() -> void:
|
|
month_year_lbl.text = str(MONTHS[view_date.month - 1]) + " " + str(view_date.year)
|
|
|
|
for child in days_grid.get_children():
|
|
child.queue_free()
|
|
|
|
var first_day_dict = {"year": view_date.year, "month": view_date.month, "day": 1}
|
|
var first_day_unix = Time.get_unix_time_from_datetime_dict(first_day_dict)
|
|
var first_day_weekday = Time.get_datetime_dict_from_unix_time(first_day_unix).weekday
|
|
|
|
# Godot weekday: 0 = Sunday, 1 = Monday...
|
|
for i in range(first_day_weekday):
|
|
var empty = Control.new()
|
|
days_grid.add_child(empty)
|
|
|
|
var days_in_month = _get_days_in_month(view_date.month, view_date.year)
|
|
|
|
for d in range(1, days_in_month + 1):
|
|
var btn = Button.new()
|
|
btn.text = str(d)
|
|
btn.custom_minimum_size = Vector2(32, 32)
|
|
if not current_date.is_empty() and current_date.year == view_date.year and current_date.month == view_date.month and current_date.day == d:
|
|
btn.add_theme_color_override("font_color", Color.YELLOW)
|
|
btn.pressed.connect(_on_day_clicked.bind(d))
|
|
days_grid.add_child(btn)
|
|
|
|
func _on_day_clicked(day: int) -> void:
|
|
current_date = {"year": view_date.year, "month": view_date.month, "day": day}
|
|
var date_str = "%04d-%02d-%02dT00:00:00Z" % [current_date.year, current_date.month, current_date.day]
|
|
text = "%04d-%02d-%02d" % [current_date.year, current_date.month, current_date.day]
|
|
emit_signal("date_selected", date_str)
|
|
popup.hide()
|
|
|
|
func get_date_iso() -> String:
|
|
if current_date.is_empty():
|
|
return ""
|
|
return "%04d-%02d-%02dT00:00:00Z" % [current_date.year, current_date.month, current_date.day]
|
|
|
|
func _get_days_in_month(month: int, year: int) -> int:
|
|
if month in [1, 3, 5, 7, 8, 10, 12]: return 31
|
|
if month in [4, 6, 9, 11]: return 30
|
|
if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0): return 29
|
|
return 28
|