Captain_s-Log/app/ui/calendar_widget.py

189 lines
6.9 KiB
Python
Raw Normal View History

2026-07-04 16:04:48 +03:00
"""Виджет календаря"""
import tkinter as tk
from tkinter import ttk
import calendar
from datetime import datetime
from app.config import Config
class CalendarWidget(tk.Frame):
"""Кастомный виджет календаря"""
def __init__(self, parent, db, on_date_select=None):
super().__init__(parent, bg=Config.COLORS['calendar_bg'])
self.db = db
self.on_date_select = on_date_select
self.current_date = datetime.now()
self.selected_date = datetime.now()
self.create_widgets()
self.update_calendar()
def create_widgets(self):
# Заголовок с месяцем и годом
self.header_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
self.header_frame.pack(fill='x', pady=(10, 5))
self.prev_btn = tk.Button(
self.header_frame,
text="",
command=self.prev_month,
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['fg'],
relief='flat',
font=('Arial', 12),
cursor='hand2'
)
self.prev_btn.pack(side='left', padx=(20, 0))
self.month_label = tk.Label(
self.header_frame,
text="",
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['calendar_header'],
font=('Arial', 14, 'bold')
)
self.month_label.pack(side='left', expand=True)
self.next_btn = tk.Button(
self.header_frame,
text="",
command=self.next_month,
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['fg'],
relief='flat',
font=('Arial', 12),
cursor='hand2'
)
self.next_btn.pack(side='right', padx=(0, 20))
# Дни недели
days_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
days_frame.pack(fill='x', padx=5, pady=5)
days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
for i, day in enumerate(days):
days_frame.grid_columnconfigure(i, weight=1)
tk.Label(
days_frame,
text=day,
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 9, 'bold')
).grid(row=0, column=i)
# Сетка календаря
self.calendar_frame = tk.Frame(self, bg=Config.COLORS['calendar_bg'])
self.calendar_frame.pack(fill='both', expand=True, padx=5, pady=5)
self.day_buttons = []
for row in range(6):
self.calendar_frame.grid_rowconfigure(row, weight=1)
for col in range(7):
self.calendar_frame.grid_columnconfigure(col, weight=1)
btn = tk.Label(
self.calendar_frame,
text="",
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['fg'],
font=('Arial', 10),
cursor='hand2'
)
btn.grid(row=row, column=col, sticky='nsew', padx=1, pady=1)
btn.bind('<Button-1>', lambda e, r=row, c=col: self.on_day_click(r, c))
self.day_buttons.append(btn)
def update_calendar(self):
year = self.current_date.year
month = self.current_date.month
# Обновляем заголовок
months = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
self.month_label.config(text=f"{months[month - 1]} {year}")
# Получаем дни с заметками
days_with_notes = self.db.get_dates_with_notes(year, month)
# Создаем календарь
cal = calendar.monthcalendar(year, month)
for idx, btn in enumerate(self.day_buttons):
row = idx // 7
col = idx % 7
if row < len(cal) and col < len(cal[row]):
day = cal[row][col]
if day != 0:
btn.config(text=str(day))
# Определяем цвет фона
today = datetime.now()
is_today = (day == today.day and
month == today.month and
year == today.year)
is_selected = (day == self.selected_date.day and
month == self.selected_date.month and
year == self.selected_date.year)
has_notes = day in days_with_notes
if is_today and is_selected:
btn.config(
bg=Config.COLORS['today_bg'],
fg=Config.COLORS['fg']
)
elif is_today:
btn.config(
bg=Config.COLORS['today_bg'],
fg=Config.COLORS['fg']
)
elif is_selected:
btn.config(
bg=Config.COLORS['accent'],
fg=Config.COLORS['fg']
)
elif has_notes:
btn.config(
bg='#5a7a3a',
fg=Config.COLORS['fg']
)
else:
btn.config(
bg=Config.COLORS['calendar_bg'],
fg=Config.COLORS['fg']
)
else:
btn.config(text="", bg=Config.COLORS['calendar_bg'])
else:
btn.config(text="", bg=Config.COLORS['calendar_bg'])
def prev_month(self):
if self.current_date.month == 1:
self.current_date = self.current_date.replace(year=self.current_date.year - 1, month=12)
else:
self.current_date = self.current_date.replace(month=self.current_date.month - 1)
self.update_calendar()
def next_month(self):
if self.current_date.month == 12:
self.current_date = self.current_date.replace(year=self.current_date.year + 1, month=1)
else:
self.current_date = self.current_date.replace(month=self.current_date.month + 1)
self.update_calendar()
def on_day_click(self, row, col):
year = self.current_date.year
month = self.current_date.month
cal = calendar.monthcalendar(year, month)
if row < len(cal) and col < len(cal[row]):
day = cal[row][col]
if day != 0:
self.selected_date = datetime(year, month, day)
self.update_calendar()
if self.on_date_select:
self.on_date_select(self.selected_date)