Advertisement
AceScottie

rapidTk Calendar.py

Dec 13th, 2022
570
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.11 KB | Source Code | 0 0
  1. ##utility code to make some stuff easier
  2. from datetime import datetime
  3. from functools import wraps
  4. def cache(func):
  5.     cached = {}
  6.     @wraps(func)
  7.     def wrapper(*args, **kwargs):
  8.         key = str(args) + str(kwargs)
  9.         if key not in cached:
  10.             cached[key] = func(*args, **kwargs)
  11.         else:
  12.             print(f'using cache {args}')
  13.         return cached[key]
  14.     return wrapper
  15. class simpledate(datetime):
  16.     def simplify(self, **kwargs):
  17.         [kwargs.pop(key, None) for key in ['hour', 'minute', 'second', 'microsecond']]
  18.         return super().replace(**kwargs, hour=0, minute=0, second=0, microsecond=0)
  19.     def replace(self, **kwargs):
  20.         return self.simplify(**kwargs)     
  21.     @classmethod
  22.     def now(cls, tz=None):
  23.         return super().now(tz=tz).simplify()
  24. ##end of utility code
  25.  
  26. from collections.abc import Callable
  27. from dateutil.relativedelta import relativedelta
  28. from tkinter import *
  29. from tkinter.simpledialog import askstring, askinteger
  30. from rapidTk import *
  31.  
  32. root = rapidTk()
  33. root.geometry("400x400+300+300")
  34.  
  35.  
  36. class Calendar(cFrame):
  37.     def __init__(self, master, **kwargs):
  38.         self.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
  39.         self.short_days = ['Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
  40.         self.months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']
  41.         self.short_months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
  42.         self.master = master
  43.         self.date = kwargs.pop('date', simpledate.now())
  44.         self.func = kwargs.pop('func', self.__ignore)
  45.         super(Calendar, self).__init__(self.master)
  46.         self.configure(**kwargs)
  47.         pp = PackProcess()
  48.         t_frame = pp.add(cFrame(self), side=TOP, fill=X)
  49.         self.c_frame = pp.add(cFrame(self), side=TOP, fill=X)
  50.         pp.add(cButton(t_frame, text="<", command=self.previous_month), side=LEFT)
  51.         self.month_l = pp.add(cLabel(t_frame, text=self.date.strftime("%B %Y"), borderwidth=1, relief='raised', height=2), side=LEFT, fill=X, expand=1)
  52.         pp.add(cButton(t_frame, text=">", command=self.next_month), side=RIGHT)
  53.         pp.pack()
  54.         self.create_month_view(self.get_month(self.date), self.func)
  55.         self.__buttons = {}
  56.         context = {
  57.         'Reset':self.reset,
  58.         'Select Year':self.select_year,
  59.         'Select Month':self.select_month,
  60.         }
  61.         self.menu = cMenu(self, context=context)
  62.         self.month_l.bind("<Button-3>", self.menu._do_popup)
  63.     def reset(self):
  64.         self.specific_date(simpledate.now())
  65.     def select_year(self):
  66.         x = askinteger('Year Selection', 'Please input the year')
  67.         self.specific_date(self.date.replace(year=x))
  68.     def select_month(self):
  69.         x = askstring('Month Selection', 'Please Enter the month').lower()
  70.         if x in self.months:
  71.             x = self.months.index(x)+1
  72.         elif x in self.short_months:
  73.             x = self.short_months.index(x)+1
  74.         else:
  75.             try:
  76.                 x = int(x)
  77.             except:
  78.                 return
  79.         self.specific_date(self.date.replace(month=int(x)))
  80.     @staticmethod
  81.     def pad(tx: str) -> str:
  82.         return f'{tx if int(tx)>=10 else "0"+tx}'
  83.     @cache
  84.     def get_month(self, date: datetime) -> list:
  85.         first = date.replace(day=1)
  86.         last = date.replace(day=1,
  87.                                 month=date.month+1 if date.month+1 < 13 else 1,
  88.                                 year=date.year if date.month+1 < 13 else date.year+1
  89.                                 ) - relativedelta(days=1)
  90.         weeks = list(range(1, last.day+1))
  91.         for _ in range(first.weekday()): weeks.insert(0, 0) ##pad extra days at start of month
  92.         month = [weeks[s:s+7] for s in range(0,len(weeks),7)] ##create the basic output from splitting weeks into segments
  93.         for _ in range(7-len(month[-1])): month[-1].append(0) ##padd extra days at end of month
  94.         for index1, w in enumerate(month):
  95.             for index2, d in enumerate(w):
  96.                 month[index1][index2] = self.pad(str(d)) ##makes sure all numbers are strings of 2 digits.
  97.         return month
  98.     @classmethod
  99.     def date(self) -> datetime:
  100.         return self.date
  101.     def set_date(self, d: datetime) -> datetime:
  102.         self.date = d
  103.         return self.date
  104.     def specific_date(self, date:datetime):
  105.         self.set_date(date)
  106.         self.month_l.configure(text=self.date.strftime("%B %Y"))
  107.         self.create_month_view(self.get_month(self.date), self.func)
  108.     def next_month(self):
  109.         self.set_date(
  110.             self.date.replace(
  111.                 day=1,
  112.                 month=self.date.month+1 if self.date.month+1 < 13 else 1,
  113.                 year=self.date.year if self.date.month+1 < 13 else self.date.year+1,
  114.                 hour=0
  115.                 )
  116.         )
  117.         self.month_l.configure(text=self.date.strftime("%B %Y"))
  118.         self.create_month_view(self.get_month(self.date), self.func)
  119.     def previous_month(self):
  120.         self.set_date(
  121.             self.date.replace(
  122.                 day=1,
  123.                 month=self.date.month-1 if self.date.month > 1 else 12,
  124.                 year=self.date.year if self.date.month > 1 else self.date.year-1,
  125.             )
  126.         )
  127.         self.month_l.configure(text=self.date.strftime("%B %Y"))
  128.         self.create_month_view(self.get_month(self.date), self.func)
  129.     def create_month_view(self, dates: list, func:Callable[[Event, str], None]):
  130.         if len(dates) < 6:
  131.             dates.append(['00']*7)
  132.         dates = [item for sublist in dates for item in sublist]
  133.         for child in self.c_frame.winfo_children():
  134.             child.grid_forget()
  135.             child.destroy()
  136.         row = 1
  137.         self.__buttons = {}
  138.        
  139.         gp = GridProcess()
  140.         for index, day in enumerate(self.short_days):
  141.             gp.add(cLabel(self.c_frame, text=day, width=5, height=2, borderwidth=1, relief='ridge'), row=0, column=index)
  142.         for index, date in enumerate(dates):
  143.             if index != 0 and index%7 == 0:
  144.                 row +=1
  145.             self.__buttons[date] = gp.add(cButton(self.c_frame,
  146.                                                 text=date if date != '00' else '',
  147.                                                 state='disabled' if date == '00' else 'normal',
  148.                                                 cursor='' if date == '00' else 'hand2',
  149.                                                 width=4,
  150.                                                 command=lambda e=Event(), d=date: func(e, d)
  151.                                                 ), row=row, column=index%7)
  152.         del self.__buttons['00']
  153.         gp.grid()
  154.     def __ignore(self, event, day):
  155.         pass
  156.  
  157. def get_day(event:Event, day:str):
  158.     print(day)
  159. if __name__ == "__main__":
  160.     pp=PackProcess()
  161.     c_frame = pp.add(cFrame(root), side=TOP, fill=X, expand=1)
  162.     t_frame = pp.add(cFrame(root), side=TOP, fill=X, expand=1)
  163.     cholder = pp.add(cFrame(c_frame), side=TOP, fill=X, expand=1)
  164.     cal = pp.add(Calendar(cholder), side=TOP)
  165.     pp.pack()
  166.    
  167.     root.mainloop()
Tags: python rapidTk
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement