Integrated new date chooser!! (FINALLY)

This commit is contained in:
PySimpleGUI 2020-03-30 09:56:42 -04:00
parent 81c021332d
commit 08e11e860c
1 changed files with 92 additions and 43 deletions

View File

@ -1,6 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
version = __version__ = "4.18.0.4 Unreleased - Print and MLine.Print fixed sep char handling, popup_get_date, icon parm popup_animated, popup button size (6,1)" version = __version__ = "4.18.0.5 Unreleased - Print and MLine.Print fixed sep char handling, popup_get_date, icon parm popup_animated, popup button size (6,1), NEW CALENDAR chooser integrated"
port = 'PySimpleGUI' port = 'PySimpleGUI'
@ -118,6 +118,7 @@ import datetime
import time import time
import pickle import pickle
import calendar import calendar
import datetime
import textwrap import textwrap
import inspect import inspect
# from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments # from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments
@ -128,7 +129,6 @@ from math import fabs
from functools import wraps from functools import wraps
from subprocess import run, PIPE from subprocess import run, PIPE
from threading import Thread from threading import Thread
import calendar as cal
import itertools import itertools
import os import os
@ -2787,6 +2787,11 @@ class Button(Element):
self.TKCal = None self.TKCal = None
self.CalendarCloseWhenChosen = None self.CalendarCloseWhenChosen = None
self.CalendarDefaultDate_M_D_Y = (None, None, None) self.CalendarDefaultDate_M_D_Y = (None, None, None)
self.CalendarCloseWhenChosen = False
self.CalendarLocale = None
self.CalendarFormat = None
self.CalendarNoTitlebar = True
self.CalendarBeginAtSundayPlus = 0
self.InitialFolder = initial_folder self.InitialFolder = initial_folder
self.Disabled = disabled self.Disabled = disabled
self.ChangeSubmits = change_submits or enable_events self.ChangeSubmits = change_submits or enable_events
@ -2937,37 +2942,48 @@ class Button(Element):
Window._DecrementOpenCount() Window._DecrementOpenCount()
elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window
# ------------ new chooser code ------------- # ------------ new chooser code -------------
#
# if self.CalendarDefaultDate_M_D_Y == (None, None, None): if self.CalendarDefaultDate_M_D_Y == (None, None, None):
# now = datetime.datetime.now() now = datetime.datetime.now()
# cur_month, cur_day, cur_year = now.month, now.day, now.year cur_month, cur_day, cur_year = now.month, now.day, now.year
# else: else:
# cur_month, cur_day, cur_year = self.CalendarDefaultDate_M_D_Y cur_month, cur_day, cur_year = self.CalendarDefaultDate_M_D_Y
#
# date_chosen = popup_get_date(start_mon=cur_month, start_day=cur_day, start_year=cur_year, close_when_chosen=self.CalendarCloseWhenChosen) date_chosen = popup_get_date(start_mon=cur_month, start_day=cur_day, start_year=cur_year, close_when_chosen=self.CalendarCloseWhenChosen, no_titlebar=self.CalendarNoTitlebar, begin_at_sunday_plus=self.CalendarBeginAtSundayPlus, locale=self.CalendarLocale)
# if date_chosen is not None:
# strvar.set(date_chosen) month, day, year = date_chosen
# self.TKStringVar.set(date_chosen) now = datetime.datetime.now()
hour, minute, second = now.hour, now.minute, now.second
try:
date_string = calendar.datetime.datetime(year, month, day, hour, minute, second).strftime(self.CalendarFormat)
except Exception as e:
print('Bad format string', e)
date_string = 'Bad format string'
target_element.update(date_string)
strvar.set(date_string)
self.TKStringVar.set(date_string)
# ------------ old chooser code ------------- # ------------ old chooser code -------------
should_submit_window = False # should_submit_window = False
root = tk.Toplevel() # root = tk.Toplevel()
root.title('Calendar Chooser') # root.title('Calendar Chooser')
root.wm_attributes("-topmost", 1) # root.wm_attributes("-topmost", 1)
self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, # self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element,
close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.CalendarDefaultDate_M_D_Y, # close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.CalendarDefaultDate_M_D_Y,
locale=self.CalendarLocale, format=self.CalendarFormat) # locale=self.CalendarLocale, format=self.CalendarFormat)
self.TKCal.pack(expand=1, fill='both') # self.TKCal.pack(expand=1, fill='both')
root.update() # root.update()
#
if type(Window._user_defined_icon) is bytes: # if type(Window._user_defined_icon) is bytes:
calendar_icon = tkinter.PhotoImage(data=Window._user_defined_icon) # calendar_icon = tkinter.PhotoImage(data=Window._user_defined_icon)
else: # else:
calendar_icon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) # calendar_icon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
try: # try:
root.tk.call('wm', 'iconphoto', root._w, calendar_icon) # root.tk.call('wm', 'iconphoto', root._w, calendar_icon)
except: # except:
pass # pass
elif self.BType == BUTTON_TYPE_SHOW_DEBUGGER: elif self.BType == BUTTON_TYPE_SHOW_DEBUGGER:
if self.ParentForm.DebuggerEnabled: if self.ParentForm.DebuggerEnabled:
_Debugger.debugger._build_floating_window() _Debugger.debugger._build_floating_window()
@ -8925,21 +8941,30 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True
image_filename=None, image_data=None, image_size=(None, None), image_filename=None, image_data=None, image_size=(None, None),
image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None, image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None,
button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None,
key=None, locale=None, format=None, metadata=None): key=None, locale=None, format='%Y-%m-%d %H:%M:%S', begin_at_sunday_plus=0, no_titlebar=True, metadata=None):
""" """
Button that will show a calendar chooser window. Fills in the target element with result
:param button_text: text in the button :param button_text: text in the button
:type button_text: (str) :type button_text: (str)
:param target: :param target: Key or "coordinate" (see docs) of target element
:type target: Union[(int, int), Any]
:param close_when_date_chosen: (Default = True) :param close_when_date_chosen: (Default = True)
:param default_date_m_d_y: (Default = (None)) :type close_when_date_chosen: bool
:param default_date_m_d_y: Beginning date to show
:type default_date_m_d_y: (int, int or None, int)
:param image_filename: image filename if there is a button image :param image_filename: image filename if there is a button image
:type image_filename: image filename if there is a button image
:param image_data: in-RAM image to be displayed on button :param image_data: in-RAM image to be displayed on button
:type image_data: in-RAM image to be displayed on button
:param image_size: (Default = (None)) :param image_size: (Default = (None))
:param image_subsample:amount to reduce the size of the image :type image_size: (Default = (None))
:param image_subsample: amount to reduce the size of the image
:type image_subsample: amount to reduce the size of the image
:param tooltip: text, that will appear when mouse hovers over the element :param tooltip: text, that will appear when mouse hovers over the element
:type tooltip: (str) :type tooltip: (str)
:param border_width: width of border around element :param border_width: width of border around element
:type border_width: width of border around element
:param size: (w,h) w=characters-wide, h=rows-high :param size: (w,h) w=characters-wide, h=rows-high
:type size: Tuple[int, int] :type size: Tuple[int, int]
:param auto_size_button: True if button size is determined by button text :param auto_size_button: True if button size is determined by button text
@ -8951,13 +8976,21 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True
:param font: specifies the font family, size, etc :param font: specifies the font family, size, etc
:type font: Union[str, Tuple[str, int]] :type font: Union[str, Tuple[str, int]]
:param bind_return_key: (Default = False) :param bind_return_key: (Default = False)
:type bind_return_key: bool
:param focus: if focus should be set to this :param focus: if focus should be set to this
:type focus: bool
:param pad: Amount of padding to put around element in pixels (left/right, top/bottom) :param pad: Amount of padding to put around element in pixels (left/right, top/bottom)
:type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int)
:param key: key for uniquely identify this element (for window.FindElement) :param key: key for uniquely identify this element (for window.FindElement)
:type key: Union[str, int, tuple] :type key: Union[str, int, tuple]
:param locale: :param locale: defines the locale used to get day names
:param format: :type locale: str
:param format: formats result using this strftime format
:type format: str
:param no_titlebar: if True no titlebar will be shown on the date chooser window
:type no_titlebar: bool
:param metadata: Anything you want to store along with this button
:type metadata: Any
:return: returns a button :return: returns a button
:rtype: (Button) :rtype: (Button)
""" """
@ -8970,6 +9003,8 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True
button.CalendarDefaultDate_M_D_Y = default_date_m_d_y button.CalendarDefaultDate_M_D_Y = default_date_m_d_y
button.CalendarLocale = locale button.CalendarLocale = locale
button.CalendarFormat = format button.CalendarFormat = format
button.CalendarNoTitlebar = no_titlebar
button.CalendarBeginAtSundayPlus = begin_at_sunday_plus
return button return button
@ -14247,20 +14282,22 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N
def popup_get_date(start_mon, start_day, start_year, begin_at_sunday_plus=0, no_titlebar=True, keep_on_top=True, location=(None, None), close_when_chosen=False, icon=None): def popup_get_date(start_mon, start_day, start_year, begin_at_sunday_plus=0, no_titlebar=True, keep_on_top=True, location=(None, None), close_when_chosen=False, icon=None, locale=None):
""" """
Display a calendar window, get the user's choice, return as a tuple (mon, day, year) Display a calendar window, get the user's choice, return as a tuple (mon, day, year)
:param start_mon: The starting month :param start_mon: The starting month
:type start_mon: int :type start_mon: int
:param start_day: The starting day - optional. Set to 0 if no date to be chosen at start :param start_day: The starting day - optional. Set to 0 if no date to be chosen at start
:type start_day: int :type start_day: int or None
:param start_year: The starting year :param start_year: The starting year
:type start_year: int :type start_year: int
:param begin_at_sunday_plus: Determines the left-most day in the display. 0=sunday, 1=monday, etc :param begin_at_sunday_plus: Determines the left-most day in the display. 0=sunday, 1=monday, etc
:type begin_at_sunday_plus: int :type begin_at_sunday_plus: int
:param icon: Same as Window icon parameter. Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO :param icon: Same as Window icon parameter. Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO
:type icon: str :type icon: str
:param locale: locale used to get the day names
:type locale: str
:return: Tuple containing (month, day, year) of chosen date or None if was cancelled :return: Tuple containing (month, day, year) of chosen date or None if was cancelled
:rtype: None or (int, int, int) :rtype: None or (int, int, int)
""" """
@ -14271,7 +14308,7 @@ def popup_get_date(start_mon, start_day, start_year, begin_at_sunday_plus=0, no
def update_days(window, month, year, begin_at_sunday_plus): def update_days(window, month, year, begin_at_sunday_plus):
[window[(week, day)].update('') for day in range(7) for week in range(6)] [window[(week, day)].update('') for day in range(7) for week in range(6)]
weeks = cal.monthcalendar(year, month) weeks = calendar.monthcalendar(year, month)
month_days = list(itertools.chain.from_iterable([[0 for _ in range(8 - begin_at_sunday_plus)]] + weeks)) month_days = list(itertools.chain.from_iterable([[0 for _ in range(8 - begin_at_sunday_plus)]] + weeks))
if month_days[6] == 0: if month_days[6] == 0:
month_days = month_days[7:] month_days = month_days[7:]
@ -14296,12 +14333,24 @@ def popup_get_date(start_mon, start_day, start_year, begin_at_sunday_plus=0, no
cur_year = start_year cur_year = start_year
cur_day = start_day cur_day = start_day
def get_month_name(month_no, locale):
with calendar.different_locale(locale):
return calendar.month_name[month_no]
def get_day_name(day_no, locale):
with calendar.different_locale(locale):
return calendar.day_abbr[day_no]
month_names = [get_month_name(month, locale) for month in range(1,13)]
day_names = [get_day_name(day, locale) for day in range(0,7)]
days_layout = make_days_layout() days_layout = make_days_layout()
layout = [[B('', font=arrow_font, border_width=0, key='-MON-DOWN-'), layout = [[B('', font=arrow_font, border_width=0, key='-MON-DOWN-'),
Text('{} {}'.format(cal.month_name[cur_month], cur_year), size=(16,1), justification='c', font=mon_year_font, key='-MON-YEAR-'), Text('{} {}'.format(month_names[cur_month-1], cur_year), size=(16,1), justification='c', font=mon_year_font, key='-MON-YEAR-'),
B('', font=arrow_font,border_width=0, key='-MON-UP-')]] B('', font=arrow_font,border_width=0, key='-MON-UP-')]]
layout += [[Col([[T(cal.day_abbr[i - (8 - begin_at_sunday_plus) % 7], size=(4,1), font=day_font, background_color=theme_text_color(), text_color=theme_background_color(), pad=(0,0)) for i in range(7)]], background_color=theme_text_color(), pad=(0,0))]] layout += [[Col([[T(day_names[i - (8 - begin_at_sunday_plus) % 7], size=(4,1), font=day_font, background_color=theme_text_color(), text_color=theme_background_color(), pad=(0,0)) for i in range(7)]], background_color=theme_text_color(), pad=(0,0))]]
layout += days_layout layout += days_layout
if not close_when_chosen: if not close_when_chosen:
layout += [[Button('Ok', border_width=0,font='TkFixedFont 8'), Button('Cancel',border_width=0, font='TkFixedFont 8')]] layout += [[Button('Ok', border_width=0,font='TkFixedFont 8'), Button('Cancel',border_width=0, font='TkFixedFont 8')]]
@ -14336,7 +14385,7 @@ def popup_get_date(start_mon, start_day, start_year, begin_at_sunday_plus=0, no
elif cur_month < 1: elif cur_month < 1:
cur_month = 12 cur_month = 12
cur_year -= 1 cur_year -= 1
window['-MON-YEAR-'].update('{} {}'.format(cal.month_name[cur_month], cur_year)) window['-MON-YEAR-'].update('{} {}'.format(month_names[cur_month-1], cur_year))
update_days(window, cur_month, cur_year, begin_at_sunday_plus) update_days(window, cur_month, cur_year, begin_at_sunday_plus)
if prev_choice: if prev_choice:
window[prev_choice].update(background_color=theme_background_color(), text_color=theme_text_color()) window[prev_choice].update(background_color=theme_background_color(), text_color=theme_text_color())